繁体   English   中英

尝试将 GDB 附加到进程时如何解决“不允许 ptrace 操作”?

[英]How to solve “ptrace operation not permitted” when trying to attach GDB to a process?

我试图用 gdb 附加一个程序,但它返回:

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

gdb-debugger 返回“无法附加到进程,请检查权限并重试。”

strace 返回“附加: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;
}

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

如果您使用 Docker,您可能需要以下选项:

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

如果你正在使用 Podman,你可能也需要它的--cap-add选项:

podman run --cap-add=SYS_PTRACE

这是由于 Linux 中的内核强化; 您可以通过echo 0 > /proc/sys/kernel/yama/ptrace_scope或通过在/etc/sysctl.d/10-ptrace.conf修改它来禁用此行为

另请参阅Fedora 22 中有关它的这篇文章(带有指向文档的链接)以及有关 Ubuntu和 .

我想补充一点,我需要--security-opt apparmor=unconfined以及@wisbucky 提到的选项。 这是在 Ubuntu 18.04(Docker 客户端和主机)上。 因此,在容器内启用 gdb 调试的完整调用是:

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

没有真正解决上述用例,但我遇到了这个问题:

问题:碰巧我用sudo启动了我的程序,所以在启动 gdb 时它给了我ptrace: Operation not permitted

解决方案sudo gdb ...

只是想强调一个相关的答案 假设你是 root 并且你已经完成了:

strace -p 700

并得到:

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

检查:

cat /proc/700/status | grep TracerPid

如果您看到类似TracerPid: 12 ,即不为零,那是已经在使用ptrace系统调用的程序的 PID。 gdbstrace使用它,并且一次只能激活一个。

Jesup 的回答是正确的; 这是由于Linux内核加固。 就我而言,我使用的是 Mac 的 Docker 社区,为了更改标志,我必须使用 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

欢迎使用 LinuxKit

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

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

1

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

/ # 退出

也许有人用 gdb 附加了这个过程。

  • ps -ef | grep gdb

不能 gdb 两次附加相同的进程。

我通过在 Debian 发行版中设置设置功能命令以更高的权限运行我的代码来处理以太网原始套接字。 我尝试了上述解决方案: echo 0 > /proc/sys/kernel/yama/ptrace_scope或通过在/etc/sysctl.d/10-ptrace.conf修改它,但这对我不起作用。

此外,我还尝试在安装目录 (usr/bin/gdb) 中为 gdb 设置功能命令,它可以工作: /sbin/setcap CAP_SYS_PTRACE=+eip /usr/bin/gdb 请务必使用 root 权限运行此命令。

由于我们大多数人都因 Docker 问题来到这里,我将添加Kubernetes答案,因为它可能对某些人有用...


您必须在 pod 的安全上下文中添加SYS_PTRACE功能,位于spec.containers.securityContext

       securityContext:
          capabilities:
            add: [ "SYS_PTRACE" ]

在 2 个不同的地方有 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

你不会再得到拒绝的许可了!

当心:这是潘多拉盒子。 不推荐在生产中使用它。

如果权限有问题,您可能需要使用 gdbserver。 (出于多种原因,当我使用 gdb、docker 或不使用 gdb 时,我几乎总是使用 gdbserver。)您需要在 docker 映像中安装 gdbserver (Deb) 或 gdb-gdbserver (RH)。 在 docker 中运行程序

$ sudo gdbserver :34567 myprogram arguments

(选择一个端口号,1025-65535)。 然后,在主机上的 gdb 中,说

(gdb) target remote 172.17.0.4:34567

其中172.17.0.4是在 docker 镜像/sbin/ip addr list运行的/sbin/ip addr list报告的 docker 镜像的 IP 地址。 这将附加在main运行之前的某个点。 你可以tb mainc停在main ,或者你喜欢的任何地方。 在 cgdb、emacs、vim 甚至一些 IDE 中运行 gdb,或者普通。 您可以在源代码或构建树中运行 gdb,因此它知道一切都在哪里。 (如果找不到您的源,请使用dir命令。)这通常比在 docker 映像中运行要好得多。

gdbserver 依赖于ptrace ,因此您还需要执行上面建议的其他操作。 --privileged --pid=host对我来说就足够了。

如果您部署到其他操作系统或嵌入式目标,您可以在那里运行 gdbserver 或 gdb 存根,并以相同的方式运行 gdb,通过真实网络甚至通过串行端口( /dev/ttyS0 )连接。

我打算回答这个老问题,因为它不被接受,任何其他答案都没有重点。 真正的答案可能已经写在/etc/sysctl.d/10-ptrace.conf因为这是我在 Ubuntu 下的情况。 这个文件说:

对于启动需要 PTRACE 的崩溃处理程序的应用程序,调试者可以通过在段错误处理程序中具体声明哪个进程将在被调试者上使用 PTRACE 来注册异常: prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);

因此,只需执行与上述相同的操作:保持/proc/sys/kernel/yama/ptrace_scope为 1 并添加prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0); 在调试器中。 然后被调试者将允许调试器对其进行调试。 这无需sudo且无需重启即可工作。

通常,debugee 还需要调用waitpid以避免崩溃后退出,以便调试器可以找到 debugee 的 pid。

我不知道你在用 LD_PRELOAD 或你的 ptrace 函数做什么。

为什么不尝试将 gdb 附加到一个非常简单的程序? 制作一个简单地重复打印 Hello 或其他内容的程序,并使用 gdb --pid [hello program PID] 附加到它。

如果这不起作用,那么您确实有问题。

另一个问题是用户 ID。 您正在跟踪的程序是否将自身设置为另一个 UID? 如果是,则除非您使用相同的用户 ID 或者是 root,否则您无法对其进行 ptrace。

我遇到了同样的问题并尝试了很多解决方案,但最后,我找到了解决方案,但我真的不知道问题是什么。 首先我修改了 ptrace_conf 值并以 root 身份登录到 Ubuntu 但问题仍然出现。 但发生的最奇怪的事情是 gdb 向我显示了一条消息:

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 warning: process 3767 is already traced by process 3755 ptrace: Operation not permitted.

使用 ps 命令终端,未列出进程 3755。

我在 /proc/$pid 中找到了进程 3755 但我不明白它是什么!!

最后,我删除了我尝试使用 PTRACE_ATTACH 系统调用将其附加到 vid gdb 和 tracer c 程序的目标文件 (foo.c),并在另一个文件夹中,我创建了另一个 c 程序并对其进行了编译。

问题解决了,我可以通过 gdb 或 ptrace_attach 系统调用附加到另一个进程。

(gdb) attach 4416

Attaching to process 4416

我发送了很多信号来处理 4416。我用 gdb 和 ptrace 测试了它,它们都运行正确。

我真的不知道问题是什么,但我认为这不是 Ubuntu 中的错误,因为很多网站都提到了它,例如https://askubuntu.com/questions/143561/why-wont-strace- gdb-attach-to-a-process-even-though-im-root

额外信息

如果您想对接口进行更改,例如添加 ovs 网桥,则必须使用--privileged而不是--cap-add NET_ADMIN

sudo docker run -itd --name=testliz --privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined ubuntu

如果您使用的是 FreeBSD,请编辑/etc/sysctl.conf ,更改行

security.bsd.unprivileged_proc_debug=0

security.bsd.unprivileged_proc_debug=1

然后重启。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM