简体   繁体   English

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

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

I'm trying to attach a program with gdb but it returns:我试图用 gdb 附加一个程序,但它返回:

Attaching to process 29139附加到进程 29139
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.如果您的 uid 与目标进程的 uid 匹配,请检查 /proc/sys/kernel/yama/ptrace_scope 的设置,或以 root 用户身份重试。 For more details, see /etc/sysctl.d/10-ptrace.conf有关更多详细信息,请参阅 /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted. ptrace:不允许操作。

gdb-debugger returns "Failed to attach to process, please check privileges and try again." gdb-debugger 返回“无法附加到进程,请检查权限并重试。”

strace returns "attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted" strace 返回“附加:ptrace(PTRACE_ATTACH,...):不允许操作”

I changed "kernel.yama.ptrace_scope" 1 to 0 and /proc/sys/kernel/yama/ptrace_scope 1 to 0 and tried set environment LD_PRELOAD=./ptrace.so with this:我将 "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;
}

But it still returns the same error.但它仍然返回相同的错误。 How can I attach it to debuggers?如何将其附加到调试器?

If you are using Docker, you will probably need these options:如果您使用 Docker,您可能需要以下选项:

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

If you are using Podman, you will probably need its --cap-add option too:如果你正在使用 Podman,你可能也需要它的--cap-add选项:

podman run --cap-add=SYS_PTRACE

This is due to kernel hardening in Linux;这是由于 Linux 中的内核强化; you can disable this behavior by echo 0 > /proc/sys/kernel/yama/ptrace_scope or by modifying it in /etc/sysctl.d/10-ptrace.conf您可以通过echo 0 > /proc/sys/kernel/yama/ptrace_scope或通过在/etc/sysctl.d/10-ptrace.conf修改它来禁用此行为

See also this article about it in Fedora 22 (with links to the documentation) and this comment thread about Ubuntu and .另请参阅Fedora 22 中有关它的这篇文章(带有指向文档的链接)以及有关 Ubuntu和 .

I would like to add that I needed --security-opt apparmor=unconfined along with the options that @wisbucky mentioned.我想补充一点,我需要--security-opt apparmor=unconfined以及@wisbucky 提到的选项。 This was on Ubuntu 18.04 (both Docker client and host).这是在 Ubuntu 18.04(Docker 客户端和主机)上。 Therefore, the full invocation for enabling gdb debugging within a container is:因此,在容器内启用 gdb 调试的完整调用是:

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

Not really addressing the above use-case but I had this problem:没有真正解决上述用例,但我遇到了这个问题:

Problem : It happened that I started my program with sudo , so when launching gdb it was giving me ptrace: Operation not permitted .问题:碰巧我用sudo启动了我的程序,所以在启动 gdb 时它给了我ptrace: Operation not permitted

Solution : sudo gdb ...解决方案sudo gdb ...

Just want to emphasize a related answer .只是想强调一个相关的答案 Let's say that you're root and you've done:假设你是 root 并且你已经完成了:

strace -p 700

and get:并得到:

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

Check:检查:

cat /proc/700/status | grep TracerPid

If you see something like TracerPid: 12 , ie not zero, that's the PID of the program that is already using the ptrace system call.如果您看到类似TracerPid: 12 ,即不为零,那是已经在使用ptrace系统调用的程序的 PID。 Both gdb and strace use it, and there can only be one active at a time. gdbstrace使用它,并且一次只能激活一个。

Jesup's answer is correct; Jesup 的回答是正确的; it is due to Linux kernel hardening.这是由于Linux内核加固。 In my case, I am using Docker Community for Mac, and in order to do change the flag I must enter the LinuxKit shell using justin cormack's nsenter (ref: https://www.bretfisher.com/docker-for-mac-commands-for-getting-into-local-docker-vm/ ).就我而言,我使用的是 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 / # cat /etc/issue

Welcome to LinuxKit欢迎使用 LinuxKit

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

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

1 1

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

/ # exit / # 退出

Maybe someone has attached this process with gdb.也许有人用 gdb 附加了这个过程。

  • ps -ef | ps -ef | grep gdb grep gdb

can't gdb attach the same process twice.不能 gdb 两次附加相同的进程。

I was running my code with higher privileges to deal with Ethernet Raw Sockets by setting set capability command in Debian Distribution.我通过在 Debian 发行版中设置设置功能命令以更高的权限运行我的代码来处理以太网原始套接字。 I tried the above solution: echo 0 > /proc/sys/kernel/yama/ptrace_scope or by modifying it in /etc/sysctl.d/10-ptrace.conf but that did not work for me.我尝试了上述解决方案: echo 0 > /proc/sys/kernel/yama/ptrace_scope或通过在/etc/sysctl.d/10-ptrace.conf修改它,但这对我不起作用。

Additionally, I also tried with set capabilities command for gdb in installed directory (usr/bin/gdb) and it works: /sbin/setcap CAP_SYS_PTRACE=+eip /usr/bin/gdb .此外,我还尝试在安装目录 (usr/bin/gdb) 中为 gdb 设置功能命令,它可以工作: /sbin/setcap CAP_SYS_PTRACE=+eip /usr/bin/gdb Be sure to run this command with root privileges.请务必使用 root 权限运行此命令。

As most of us land here for Docker issues I'll add the Kubernetes answer as it might come in handy for someone...由于我们大多数人都因 Docker 问题来到这里,我将添加Kubernetes答案,因为它可能对某些人有用...


You must add the SYS_PTRACE capability in your pod's security context at spec.containers.securityContext :您必须在 pod 的安全上下文中添加SYS_PTRACE功能,位于spec.containers.securityContext

       securityContext:
          capabilities:
            add: [ "SYS_PTRACE" ]

There are 2 securityContext keys at 2 different places.在 2 个不同的地方有 2 个securityContext键。 If it tell you that the key is not recognized than you missplaced it.如果它告诉您密钥未被识别,那么您将其放错了位置。 Try the other one.试试另一个。

You probably need to have a root user too as default.默认情况下,您可能还需要一个 root 用户。 So in the other security context ( spec.securityContext ) add :所以在其他安全上下文( spec.securityContext )中添加:

      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 101

FYI : 0 is root.仅供参考:0 是根。 But the fsGroup value is unknown to me.但是我不知道 fsGroup 的值。 For what I'm doing I don't care but you might.对于我在做什么,我不在乎,但你可能会在乎。

Now you can do :现在你可以这样做:

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

You won't get the permission denied anymore !你不会再得到拒绝的许可了!

BEWARE : This is the Pandora box.当心:这是潘多拉盒子。 Having this in production it NOT recommended.不推荐在生产中使用它。

If permissions are a problem, you probably will want to use gdbserver.如果权限有问题,您可能需要使用 gdbserver。 (I almost always use gdbserver when I gdb, docker or no, for numerous reasons.) You will need gdbserver (Deb) or gdb-gdbserver (RH) installed in the docker image. (出于多种原因,当我使用 gdb、docker 或不使用 gdb 时,我几乎总是使用 gdbserver。)您需要在 docker 映像中安装 gdbserver (Deb) 或 gdb-gdbserver (RH)。 Run the program in docker with在 docker 中运行程序

$ sudo gdbserver :34567 myprogram arguments

(pick a port number, 1025-65535). (选择一个端口号,1025-65535)。 Then, in gdb on the host, say然后,在主机上的 gdb 中,说

(gdb) target remote 172.17.0.4:34567

where 172.17.0.4 is the IP address of the docker image as reported by /sbin/ip addr list run in the docker image.其中172.17.0.4是在 docker 镜像/sbin/ip addr list运行的/sbin/ip addr list报告的 docker 镜像的 IP 地址。 This will attach at a point before main runs.这将附加在main运行之前的某个点。 You can tb main and c to stop at main , or wherever you like.你可以tb mainc停在main ,或者你喜欢的任何地方。 Run gdb under cgdb, emacs, vim, or even in some IDE, or plain.在 cgdb、emacs、vim 甚至一些 IDE 中运行 gdb,或者普通。 You can run gdb in your source or build tree, so it knows where everything is.您可以在源代码或构建树中运行 gdb,因此它知道一切都在哪里。 (If it can't find your sources, use the dir command.) This is usually much better than running it in the docker image. (如果找不到您的源,请使用dir命令。)这通常比在 docker 映像中运行要好得多。

gdbserver relies on ptrace , so you will also need to do the other things suggested above. gdbserver 依赖于ptrace ,因此您还需要执行上面建议的其他操作。 --privileged --pid=host sufficed for me. --privileged --pid=host对我来说就足够了。

If you deploy to other OSes or embedded targets, you can run gdbserver or a gdb stub there, and run gdb the same way, connecting across a real network or even via a serial port ( /dev/ttyS0 ).如果您部署到其他操作系统或嵌入式目标,您可以在那里运行 gdbserver 或 gdb 存根,并以相同的方式运行 gdb,通过真实网络甚至通过串行端口( /dev/ttyS0 )连接。

I was going to answer this old question as it is unaccepted and any other answers are not got the point.我打算回答这个老问题,因为它不被接受,任何其他答案都没有重点。 The real answer may be already written in /etc/sysctl.d/10-ptrace.conf as it is my case under Ubuntu.真正的答案可能已经写在/etc/sysctl.d/10-ptrace.conf因为这是我在 Ubuntu 下的情况。 This file says:这个文件说:

For applications launching crash handlers that need PTRACE, exceptions can be registered by the debugee by declaring in the segfault handler specifically which process will be using PTRACE on the debugee: prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);对于启动需要 PTRACE 的崩溃处理程序的应用程序,调试者可以通过在段错误处理程序中具体声明哪个进程将在被调试者上使用 PTRACE 来注册异常: prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);

So just do the same thing as above: keep /proc/sys/kernel/yama/ptrace_scope as 1 and add 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); in the debugee.在调试器中。 Then the debugee will allow debugger to debug it.然后被调试者将允许调试器对其进行调试。 This works without sudo and without reboot.这无需sudo且无需重启即可工作。

Usually, debugee also need to call waitpid to avoid exit after crash so debugger can find the pid of debugee.通常,debugee 还需要调用waitpid以避免崩溃后退出,以便调试器可以找到 debugee 的 pid。

I don't know what you are doing with LD_PRELOAD or your ptrace function.我不知道你在用 LD_PRELOAD 或你的 ptrace 函数做什么。

Why don't you try attaching gdb to a very simple program?为什么不尝试将 gdb 附加到一个非常简单的程序? Make a program that simply repeatedly prints Hello or something and use gdb --pid [hello program PID] to attach to it.制作一个简单地重复打印 Hello 或其他内容的程序,并使用 gdb --pid [hello program PID] 附加到它。

If that does not work then you really do have a problem.如果这不起作用,那么您确实有问题。

Another issue is the user ID.另一个问题是用户 ID。 Is the program that you are tracing setting itself to another UID?您正在跟踪的程序是否将自身设置为另一个 UID? If it is then you cannot ptrace it unless you are using the same user ID or are root.如果是,则除非您使用相同的用户 ID 或者是 root,否则您无法对其进行 ptrace。

I have faced the same problem and try a lot of solution but finally, I have found the solution, but really I don't know what the problem was.我遇到了同样的问题并尝试了很多解决方案,但最后,我找到了解决方案,但我真的不知道问题是什么。 First I modified the ptrace_conf value and login into Ubuntu as a root but the problem still appears.首先我修改了 ptrace_conf 值并以 root 身份登录到 Ubuntu 但问题仍然出现。 But the most strange thing that happened is the gdb showed me a message that says:但发生的最奇怪的事情是 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.

With ps command terminal, the process 3755 was not listed.使用 ps 命令终端,未列出进程 3755。

I found the process 3755 in /proc/$pid but I don't understand what was it!!我在 /proc/$pid 中找到了进程 3755 但我不明白它是什么!!

Finally, I deleted the target file (foo.c) that I try to attach it vid gdb and tracer c program using PTRACE_ATTACH syscall, and in the other folder, I created another c program and compiled it.最后,我删除了我尝试使用 PTRACE_ATTACH 系统调用将其附加到 vid gdb 和 tracer c 程序的目标文件 (foo.c),并在另一个文件夹中,我创建了另一个 c 程序并对其进行了编译。

the problem is solved and I was enabled to attach to another process either by gdb or ptrace_attach syscall.问题解决了,我可以通过 gdb 或 ptrace_attach 系统调用附加到另一个进程。

(gdb) attach 4416

Attaching to process 4416

and I send a lot of signals to process 4416. I tested it with both gdb and ptrace, both of them run correctly.我发送了很多信号来处理 4416。我用 gdb 和 ptrace 测试了它,它们都运行正确。

really I don't know the problem what was, but I think it is not a bug in Ubuntu as a lot of sites have referred to it, such https://askubuntu.com/questions/143561/why-wont-strace-gdb-attach-to-a-process-even-though-im-root我真的不知道问题是什么,但我认为这不是 Ubuntu 中的错误,因为很多网站都提到了它,例如https://askubuntu.com/questions/143561/why-wont-strace- gdb-attach-to-a-process-even-though-im-root

Extra information额外信息

If you wanna make changes in the interfaces such as add the ovs bridge, you must use --privileged instead of --cap-add NET_ADMIN .如果您想对接口进行更改,例如添加 ovs 网桥,则必须使用--privileged而不是--cap-add NET_ADMIN

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

If you are using FreeBSD, edit /etc/sysctl.conf , change the line如果您使用的是 FreeBSD,请编辑/etc/sysctl.conf ,更改行

security.bsd.unprivileged_proc_debug=0

to

security.bsd.unprivileged_proc_debug=1

Then reboot.然后重启。

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

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