如何解决在尝试将GDB附加到进程时出现的"ptrace操作不允许"的问题?

139

我正在尝试使用GDB附加到一个程序,但是它返回:

附加到进程29139
无法附加到进程。如果您的UID与目标进程的UID匹配,请检查/proc/sys/kernel/yama/ptrace_scope的设置,或者尝试以root用户身份再次尝试。有关更多详细信息,请参见/etc/sysctl.d/10-ptrace.conf
ptrace:操作不允许。

gdb-debugger返回:

无法附加到进程,请检查权限并重试。

strace返回:

attach: ptrace(PTRACE_ATTACH, ...): 操作不允许

我将“kernel.yama.ptrace_scope”从1更改为0,并将/proc/sys/kernel/yama/ptrace_scope从1更改为0,并尝试使用set environment LD_PRELOAD=./ptrace.so来执行此操作:

#include <stdio.h>
int ptrace(int i, int j, int k, int l) {
    printf(" ptrace(%i, %i, %i, %i), returning -1\n", i, j, k, l);
    return 0;
}

但它仍然返回相同的错误。我该如何将其附加到调试器上?


有时即使在 root 权限下,当我尝试附加内核进程(例如 [nfsd])时,仍然会出现这个问题。显然,用户空间无法附加内核进程。 - pevik
16个回答

255

如果您正在使用Docker,可能需要这些选项:

docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined

如果您正在使用Podman,您可能还需要使用--cap-add选项:

podman run --cap-add=SYS_PTRACE

80
即使问题没有提到 Docker,我也因此到达了这里。这对我解决了问题,感谢您超越问题的范围。 - Perennialista
1
在进行docker构建时,我该如何做到这一点而不是运行?它似乎不接受那些参数?(我有一个奇怪的bug,只有在使用Dockerfile时才会出现) - fersarr
8
在我的容器规范中,只需要添加 cap_add:- SYS_PTRACE(冒号后面加上新行)到 docker-compose.yml 文件中。 - Rafał G.
5
在更新的 Docker 版本 18+ 中,不再需要使用 --security-opt seccomp=unconfined - B.Z.
2
有没有办法在运行中的Docker容器上应用此选项? - Raj
显示剩余2条评论

100

7
在我的情况下,只有在先用 sudo -i 命令打开根控制台后,echo ... 才能正常工作(由于重定向符号,sudo echo ... 无法正常工作)。请注意,此处不提供解释。 - R Yoda
有些 shell 构造在作为 sudo 等命令的参数时使用起来很棘手。 - jesup
27
使用sudo和重定向时,您可以使用echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - Daniel Serodio
3
使用 sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope" 命令可降低内核 Yama 模块对 ptrace 的限制。 - nav
3
那个 echo 0 > ... 的更改是永久的吗?重启后会恢复正常吗?我应该在容器内还是主机上执行这个操作? - Wyck
显示剩余2条评论

19

只想强调一个相关的答案。假设你是root用户并已经执行了以下操作:

strace -p 700

并获得:

strace: attach: ptrace(PTRACE_SEIZE, 700): Operation not permitted

检查:

grep TracerPid /proc/700/status
如果您看到类似于TracerPid: 12的内容,即不是0,那么它就是已经在使用ptrace系统调用的程序的PID。 both gdb and strace使用它,每次只能有一个处于活动状态。

18
我想补充一点,对于@wisbucky提到的选项,我需要--security-opt apparmor=unconfined。这是在Ubuntu 18.04上(Docker客户端和主机都是如此)。因此,在容器中启用gdb调试的完整命令如下: docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --security-opt apparmor=unconfined

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Rafael
4
@Rafael,回答已更新并包含完整的命令行。现在它提供了一个完全自包含的问题答案。 - Juraj Oršulić

15

由于大多数人来到这里都是因为Docker问题,所以我会添加 Kubernetes 的答案,因为这可能对某些人有用...


你必须在你的 Pod 的安全上下文中添加 SYS_PTRACE 权限,位于 spec.containers.securityContext 中:

       securityContext:
          capabilities:
            add: [ "SYS_PTRACE" ]

有2个不同位置的securityContext键。如果它告诉你该键未被识别,则你将其放错了位置。尝试另一个。

您可能还需要默认拥有root用户。因此,在其他安全上下文(spec.securityContext)中添加:

      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 101

注意:0是根用户。但是fsGroup值我不知道。对于我正在做的事情,我不在乎,但你可能会在意。

现在你可以做:

strace -s 100000 -e write=1  -e trace=write -p 16

您将不再收到“权限被拒绝”的错误提示!

警告:这是潘多拉魔盒。不建议在生产环境中使用。


13

以下内容并不完全针对上述用例,但我遇到了这个问题:

问题: 我的程序是在使用sudo启动后运行的,因此在启动gdb时会提示ptrace:操作不允许

解决方案: sudo gdb ...


2
但请注意,如果执行 echo 3 | sudo tee /proc/sys/kernel/yama/ptrace_scope (https://www.kernel.org/doc/Documentation/security/Yama.txt),即使使用 sudo gdb 也无法正常工作,并且它将无法查看您的 .gdbinit 脚本。 - Ciro Santilli OurBigBook.com

8
我为了处理以太网原始套接字,通过在Debian发行版中设置set capability命令来以更高的权限运行我的代码。我尝试了上述解决方案:echo 0 > /proc/sys/kernel/yama/ptrace_scope 或者修改/etc/sysctl.d/10-ptrace.conf文件中相应的值,但对我没有用。
此外,我还尝试了在已安装的gdb目录(usr/bin/gdb)中使用set capabilities命令,它是有效的:/sbin/setcap CAP_SYS_PTRACE=+eip /usr/bin/gdb,请确保以root用户权限运行此命令。

新增的功能是永久性的,除非您使用 setcap CAP_SYS_PTRACE=-eip /usr/bin/gdbsetcap -r /usr/bin/gdb 将它们移除。更多信息请参见此处 - Matthias Braun

4
Jesup的回答是正确的,这是由于Linux内核加固所致。在我的情况下,我正在使用Docker社区版Mac版,为了更改标志,我必须使用justin cormack的nsenter进入LinuxKit shell(参考:https://www.bretfisher.com/docker-for-mac-commands-for-getting-into-local-docker-vm/)。 docker run -it --rm --privileged --pid=host justincormack/nsenter1

/ # cat /etc/issue

Welcome to LinuxKit

                    ##         .
              ## ## ##        ==
           ## ## ## ## ##    ===
       /"""""""""""""""""\___/ ===
      {                       /  ===-
       \______ O           __/
         \    \         __/
          \____\_______/

/ # cat /proc/sys/kernel/yama/ptrace_scope

1

/ # echo 0 > /proc/sys/kernel/yama/ptrace_scope

/ # exit


2

也许有人已经使用gdb附加了这个进程。

  • ps -ef | grep gdb

无法使用gdb两次附加同一进程。


2
如果您正在使用FreeBSD,請編輯/etc/sysctl.conf文件,更改該行。
security.bsd.unprivileged_proc_debug=0

security.bsd.unprivileged_proc_debug=1

然后重新启动。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接