【问题标题】:How to solve "ptrace operation not permitted" when trying to attach GDB to a process?尝试将 GDB 附加到进程时如何解决“不允许 ptrace 操作”?
【发布时间】:2013-10-13 10:56:51
【问题描述】:

我正在尝试使用 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, ...): Operation not allowed”

我将 "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;
}

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

【问题讨论】:

    标签: c linux debugging gdb strace


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 它附加了简单的程序,但我正在尝试附加一个crackme文件。它具有反调试保护like this
    • @user2850750:我在答案中添加了一点。
    • 我正在以 root 身份尝试
    • @user2850750:好的。那么,gdb 是否有可能以某种方式调用共享对象中的 ptrace 函数?如果您使用预加载对象在 hello world 程序上运行 gdb,它也会失败吗?
    【解决方案2】:

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

    另请参阅this article about it in Fedora 22(带有文档链接)和this comment thread about Ubuntu 和。

    【讨论】:

    • 一些 shell 结构很难在 sudo 等命令的参数中使用。
    • 使用sudo和重定向时可以使用echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
    • 本站的cmet比大部分答案都好。
    • sudo bash -c "echo 0 &gt; /proc/sys/kernel/yama/ptrace_scope"
    【解决方案3】:

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

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

    解决方案sudo gdb ...

    【讨论】:

    【解决方案4】:

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

    • ps -ef | grep gdb

    gdb 不能两次附加同一个进程。

    【讨论】:

      【解决方案5】:

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

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

      如果您使用的是 Podman,您可能还需要它的 --cap-add 选项:

      podman run --cap-add=SYS_PTRACE
      

      【讨论】:

      • 即使问题没有提到 Docker,我也因此来到这里。这为我解决了问题,感谢您提出问题。
      • 这对我在 Docker 中运行 GCC 8.2 和 GDB 8.1 很有用
      • 在执行 docker build 而不是 run 时如何执行此操作?它似乎不需要那些参数? (我有一个奇怪的错误,只有在使用 Dockerfile 时才会发生)
      • 在 docker-compose.yml 中,我只需要在容器规范中添加 cap_add: - SYS_PTRACE(冒号后新行)。
      • 在较新的 Docker 版本 18+ 中,不再需要 --security-opt seccomp=unconfined
      【解决方案6】:

      我遇到过同样的问题并尝试了很多解决方案,但最终我找到了解决方案,但我真的不知道问题是什么。首先我修改了 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

      附加到进程 4416

      我向进程 4416 发送了很多信号。我用 gdb 和 ptrace 对其进行了测试,它们都运行正常。

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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

        【解决方案8】:

        Jesup 的回答是正确的;这是由于Linux内核加固。就我而言,我使用的是 Docker Community for 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

        欢迎使用 LinuxKit

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

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

        1

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

        /#退出

        【讨论】:

          【解决方案9】:

          额外信息

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

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

          【讨论】:

            【解决方案10】:

            如果权限有问题,您可能需要使用 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 镜像的 IP 地址,由运行在 docker 镜像中的 /sbin/ip addr list 报告。这将附加在main 运行之前的某个点。您可以tb mainc 停在main 或任何您喜欢的地方。在 cgdb、emacs、vim 下运行 gdb,甚至在某些 IDE 中运行 gdb。您可以在源代码或构建树中运行 gdb,因此它知道所有内容在哪里。 (如果它找不到您的源代码,请使用dir 命令。)这通常比在 docker 映像中运行要好得多。

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

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

            【讨论】:

              【解决方案11】:

              我通过在 Debian 发行版中设置 set capability 命令以更高的权限运行我的代码来处理以太网原始套接字。我尝试了上述解决方案:echo 0 &gt; /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 权限运行此命令。

              【讨论】:

                【解决方案12】:

                我打算回答这个老问题,因为它未被接受,任何其他答案都没有意义。真正的答案可能已经写在/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来避免crash后退出,这样debugger才能找到debugee的pid。

                【讨论】:

                  【解决方案13】:

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

                  strace -p 700
                  

                  然后得到:

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

                  检查:

                  grep TracerPid /proc/700/status
                  

                  如果您看到类似TracerPid: 12 的内容,即not 0,那是已经在使用ptrace 系统调用的程序的PID。 gdbstrace 都使用它,并且一次只能有一个活动。

                  【讨论】:

                    【解决方案14】:

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

                    security.bsd.unprivileged_proc_debug=0
                    

                    security.bsd.unprivileged_proc_debug=1
                    

                    然后重启。

                    【讨论】:

                      【解决方案15】:

                      由于我们大多数人都因 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
                      

                      您不会再获得被拒绝的权限!

                      注意:这是潘多拉魔盒。不建议在生产中使用它。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2017-06-21
                        • 2020-08-12
                        • 1970-01-01
                        • 2014-04-02
                        • 1970-01-01
                        • 2021-07-17
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多