为什么即使我是root,strace/gdb也无法附加到一个进程上呢?

我以root身份登录,但是strace给了我这个错误信息:
root@kyznecov-System:/home/kyznecov# ps -e | grep 111 3807 pts/2 00:00:00 111 3810 pts/2 00:00:00 111 root@kyznecov-System:/home/kyznecov# strace -p 3810
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted 无法附加到进程。如果您的uid与目标进程的uid匹配,请检查/proc/sys/kernel/yama/ptrace_scope的设置,或者尝试以root用户再次运行。有关更多详细信息,请参阅/etc/sysctl.d/10-ptrace.conf root@kyznecov-System:/home/kyznecov
root@kyznecov-System:/home/kyznecov# cat /proc/sys/kernel/yama/ptrace_scope 0
然后我尝试在Eclipse CDT中使用gdb调试一个带有forking的多进程程序,结果给了我相同的错误信息:
有什么想法吗?

由于ptrace_scope为零,这应该没有关系,但只是作为一个实验,你能否尝试一下更简单的strace用法,其中跟踪进程是被跟踪进程的父进程。例如,strace /bin/echo test?这样会得到相同的错误信息吗? - Jordan Uggla
@EliahKagan,理论上来说,如果没有内核错误,OP所描述的情况是不可能发生的。如果你在接下来的24小时内有时间,并且能够将你的评论转化为一个答案,那将非常好——我在Precise上的测试没有发现任何问题,这样一来,就可以确定地回答说OP的配置中存在一些小问题……自从他在5月29日提出初始问题以来,他就再也没有回来过。 - ish
@EliahKagan,重新阅读“操作不允许”这一部分时,我突然想到了一件事——因为在我被称为OpenVZ VPS/VMs上的root用户时,我已经看到过很多次这种情况(它们共享主机机器内核,所以你只是自己小岛的国王)...也许这就是问题所在?请参考此粘贴 - ish
@izx 你的粘贴已过期。我在容器内遇到了这个问题,如果你有任何见解,那将是很好的。 - Kunal Tyagi
2个回答

一个导致出现错误的原因是: attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted 这是因为该进程已经被使用 gdbstrace 或类似工具附加过了。要检查是否是这种情况,请运行以下命令: grep TracerPid /proc/$THE_PID/status 如果结果不为零,则表示存在一个正在对该进程进行跟踪的现有程序的进程ID。

我们在Eclipse中调试时并不注意到这一点......因为它已经使用了GDB。 - ernesto
谢谢你指出这一点。我正在通过一个strace包装器运行一个程序。该程序进行fork操作,然后执行自身。被执行的子进程由于运行strace包装器而很快终止,因为它无法附加,原因是父进程已经在strace的控制下。 - Rob Kennedy
如果一个进程已经附加到GDB,是否可以同时附加Strace?还是只能一次附加一个? - txs

izx所评论的,这只能是由于内核漏洞才可能发生。因此,任何目前能够出现这个问题的人,包括尤其是这个问题的原始提问者,都应该仔细阅读那个页面,并在受影响的机器上运行ubuntu-bug linux,将其报告为一个bug。这应该报告给Ubuntu中的linux,而不是报告给主线(上游)内核,除非你能在主线内核上复现它(你必须加载yama)。
每个Ubuntu版本的预期行为,从Ubuntu 10.10开始,是进程A无法跟踪运行中的进程B,除非B是A的直接子进程(或者A以root身份运行)。这是一种安全增强措施,使得被攻击者入侵的进程无法使用内核提供的调试工具来发现其他进程的信息。这在Security Features社区维基页面的ptrace scope部分有所解释。
这种限制性行为是默认设置,但可以更改为允许进程A跟踪任何与进程A自身具有相同用户ID的正在运行的进程B。也就是说,您可以配置系统以允许您的任何进程相互调试。这简化了将调试器附加到已经运行的进程上。
此设置在sysctl中通过/proc/sys/kernel/yama/ptrace_scope公开。1表示更严格的行为,0表示不那么严格的行为。可以使用以下命令读取该设置:
cat /proc/sys/kernel/yama/ptrace_scope

非默认行为(较少限制)可以通过以下方式设置:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

并且更加严格(默认)的行为可以通过以下方式进行设置(或重新设置):
echo 1 | sudo tee /proc/sys/kernel/yama/ptrace_scope

原帖提问者不仅无法使用ptrace-scopestrace实例附加到当前正在运行的进程上,而且在以root身份运行strace时仍然无法这样做。很难看出这可能是除了一个错误之外的任何事情 - 我强烈建议将其报告为错误。
起初,我认为我能够重现忽略ptrace_scope设置为0并被视为1的问题。但我不再相信这是真的,因为我已经再次做了所有相同的事情,但我无法重现这个问题。我已在以下环境中进行了测试:
  • 我每天用作主要框的Lubuntu Precise amd64物理机器。
  • 运行Lubuntu Precise i386(12.04)live CD的VirtualBox虚拟机。
  • 运行Quantal i386(Ubuntu+1)daily-live(20120608)的相同VirtualBox虚拟机。
在所有三台机器上,出现了预期的行为,我无法重现这个问题的原始发布者所问的条件。以下是来自终端的一些文本(来自Precise live系统):
lubuntu@lubuntu:~$ nano&
[1] 3492
lubuntu@lubuntu:~$ strace -p 3492
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted
Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf

[1]+  Stopped                 nano
lubuntu@lubuntu:~$ cat /proc/sys/kernel/yama/ptrace_scope
1
lubuntu@lubuntu:~$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
0
lubuntu@lubuntu:~$ strace -p 3492
Process 3492 attached - interrupt to quit
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
ioctl(1, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = ? ERESTARTSYS (To be restarted)
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
ioctl(1, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = ? ERESTARTSYS (To be restarted)
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---

strace 继续产生消息直到我暂停它,如预期的那样。

我在此再次建议将此问题报告为错误。在https://bugs.launchpad.net(其中包括任何已报告的Ubuntu错误)上进行最全面的搜索,以查找ptrace_scope文本,只会产生少数结果,显然没有一个是关于此错误的报告。报告错误将有助于他人,可能会导致解决方法或修复,并且很可能是解决此问题的唯一有意义的方式(假设问题仍然存在)。

谢谢你的建议,明天我会仔细阅读并可能添加一些副标题,但我认为这已经非常详尽了 :) - ish
在我的帖子中,你可以看到: root@kyznecov-System:/home/kyznecov# cat /proc/sys/kernel/yama/ptrace_scope 0我已经执行了以下操作: echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - andreykyz
在控制台上一切都很顺利。但是如果我在Eclipse中运行程序,并尝试从控制台使用strace,就会遇到问题。 - andreykyz
2可能是已经被追踪的过程的副作用吗?当我在父进程上使用gdb并允许fork-mode子进程时,我遇到了同样的问题。 - Jamie Pate
2我也在14.04上遇到了这个bug。有人知道是否曾经为此报告过bug吗? - detly