137

I'm trying to attach to a program with GDB but it returns:

Attaching to process 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. For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.

gdb-debugger returns:

Failed to attach to process, please check privileges and try again.

strace returns:

attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted

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:

#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?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
bbaytemir
  • 1,471
  • 2
  • 10
  • 5
  • I sometimes have this problem even under root, when I try to attach a kernel process, i.e. one in `[` `]` (e.g. `[nfsd]`). Obviously, user space cannot attach kernel process. – pevik May 26 '23 at 07:47

16 Answers16

250

If you are using Docker, you will probably need these options:

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 run --cap-add=SYS_PTRACE
psmears
  • 26,070
  • 4
  • 40
  • 48
wisbucky
  • 33,218
  • 10
  • 150
  • 101
  • 79
    Even if the question was not mentioning Docker, I got here because of that. This solved for me and thank you for going beyond the question. – Perennialista Mar 13 '18 at 17:31
  • This worked for me running GCC 8.2 and GDB 8.1 in Docker – ThetaSinner Jul 29 '18 at 18:27
  • 1
    how can I do this when doing docker build instead of run? it doesn't seem to take those args? (i have a weird bug that only happens when using the Dockerfile) – fersarr Oct 04 '18 at 10:31
  • This worked for me to get strace running in docker container – fty4 Jan 17 '19 at 15:00
  • 7
    In docker-compose.yml I just had to add `cap_add: - SYS_PTRACE` (with new line after the colon) in my container specification. – Rafał G. Feb 04 '20 at 09:16
  • 4
    In newer Docker version 18+, `--security-opt seccomp=unconfined` is no longer needed. – B.Z. Sep 24 '20 at 15:58
  • 2
    Is there a way to apply this option on a running docker container? – Raj Apr 28 '23 at 21:49
98

This is due to kernel hardening in 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

See also this article about it in Fedora 22 (with links to the documentation) and this comment thread about Ubuntu and .

jesup
  • 6,765
  • 27
  • 32
18

I would like to add that I needed --security-opt apparmor=unconfined along with the options that @wisbucky mentioned. This was on Ubuntu 18.04 (both Docker client and host). Therefore, the full invocation for enabling gdb debugging within a container is:

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

Juraj Oršulić
  • 363
  • 2
  • 6
18

Just want to emphasize a related answer. Let's say that you're root and you've done:

strace -p 700

and get:

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

Check:

grep TracerPid /proc/700/status

If you see something like TracerPid: 12, i.e. not 0, that's the PID of the program that is already using the ptrace system call. Both gdb and strace use it, and there can only be one active at a time.

Nagev
  • 10,835
  • 4
  • 58
  • 69
14

As most of us land here for Docker issues I'll add the Kubernetes answer as it might come in handy for someone...


You must add the SYS_PTRACE capability in your pod's security context at spec.containers.securityContext:

       securityContext:
          capabilities:
            add: [ "SYS_PTRACE" ]

There are 2 securityContext keys at 2 different places. If it tells 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. So in the other security context (spec.securityContext) add :

      securityContext:
        runAsUser: 0
        runAsGroup: 0
        fsGroup: 101

FYI : 0 is root. But the fsGroup value is unknown to me. 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.

Doctor
  • 7,115
  • 4
  • 37
  • 55
13

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.

Solution: sudo gdb ...

Maxim Chetrusca
  • 3,262
  • 1
  • 32
  • 28
  • 2
    But note that `sudo gdb` will also not work if `echo 3 | sudo tee /proc/sys/kernel/yama/ptrace_scope` (https://www.kernel.org/doc/Documentation/security/Yama.txt), and it won't see your `.gdbinit` scripts. – Ciro Santilli OurBigBook.com Apr 28 '18 at 07:55
8

I was running my code with higher privileges to deal with Ethernet Raw Sockets by setting set capability command in Debian Distribution. 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.

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. Be sure to run this command with root privileges.

SufAB
  • 93
  • 1
  • 8
  • The added capabilities are permanent unless you take them away with `setcap CAP_SYS_PTRACE=-eip /usr/bin/gdb` or `setcap -r /usr/bin/gdb`. See [this](https://unix.stackexchange.com/questions/303423/unset-setcap-additional-capabilities-on-excutable) for more. – Matthias Braun May 17 '23 at 12:05
4

Jesup's answer is correct; it is due to Linux kernel hardening. 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/ ).

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

Community
  • 1
  • 1
YudhiWidyatama
  • 1,684
  • 16
  • 14
2

Maybe someone has attached this process with gdb.

  • ps -ef | grep gdb

can't gdb attach the same process twice.

Raymond
  • 71
  • 1
2

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. 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);

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); in the debugee. Then the debugee will allow debugger to debug it. This works without sudo and without reboot.

Usually, debugee also need to call waitpid to avoid exit after crash so debugger can find the pid of debugee.

linux40
  • 368
  • 1
  • 9
2

If you are using FreeBSD, edit /etc/sysctl.conf, change the line

security.bsd.unprivileged_proc_debug=0

to

security.bsd.unprivileged_proc_debug=1

Then reboot.

Bruno Haible
  • 1,203
  • 8
  • 8
1

If permissions are a problem, you probably will want to use 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. Run the program in docker with

$ sudo gdbserver :34567 myprogram arguments

(pick a port number, 1025-65535). Then, in gdb on the host, say

(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. This will attach at a point before main runs. You can tb main and c to stop at main, or wherever you like. Run gdb under cgdb, emacs, vim, or even in some IDE, or plain. You can run gdb in your source or build tree, so it knows where everything is. (If it can't find your sources, use the dir command.) This is usually much better than running it in the docker image.

gdbserver relies on ptrace, so you will also need to do the other things suggested above. --privileged --pid=host sufficed for me.

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).

0

I don't know what you are doing with LD_PRELOAD or your ptrace function.

Why don't you try attaching gdb to a very simple program? Make a program that simply repeatedly prints Hello or something and use gdb --pid [hello program PID] to attach to it.

If that does not work then you really do have a problem.

Another issue is the user ID. Is the program that you are tracing setting itself to another UID? If it is then you cannot ptrace it unless you are using the same user ID or are root.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • it attachs simple programs but i'm trying to attach a crackme file. it has anti-debug protection [like this](http://xorl.wordpress.com/2009/01/01/quick-anti-debugging-trick-for-gdb/). – bbaytemir Oct 06 '13 at 23:53
  • @user2850750: I added another bit to the answer. – Zan Lynx Oct 07 '13 at 01:42
  • i'm trying it as a root – bbaytemir Oct 08 '13 at 18:56
  • @user2850750: Alright. Well then, is it possible that gdb is somehow calling the ptrace function in your shared object? If you run gdb on a hello world program with your preload object does it also fail? – Zan Lynx Oct 08 '13 at 19:55
0

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. But the most strange thing that happened is the gdb showed me a message that says:

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.

I found the process 3755 in /proc/$pid but I don't understand what was it!!

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.

the problem is solved and I was enabled to attach to another process either by gdb or ptrace_attach syscall.

(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.

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

0

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.

sudo docker run -itd --name=testliz --privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined ubuntu
RobC
  • 22,977
  • 20
  • 73
  • 80
0

From man prctl(2):

PR_SET_PTRACER (since Linux 3.4)
    This  is  meaningful  only when the Yama LSM is enabled and in mode 1 ("restricted ptrace", visible via /proc/sys/kernel/yama/ptrace_scope).
    When a "ptracer process ID" is passed in arg2, the caller is declaring that the ptracer process can ptrace(2) the calling process as  if  it
    were  a  direct  process ancestor.  Each PR_SET_PTRACER operation replaces the previous "ptracer process ID".  Employing PR_SET_PTRACER with
    arg2 set to 0 clears the caller's "ptracer process ID".  If arg2 is PR_SET_PTRACER_ANY, the ptrace restrictions introduced by Yama  are  ef‐
    fectively disabled for the calling process.

To allow your program to be debugged by any process you can add the line:

#include <sys/prctl.h>

int main(void)
{
    // allows any process to attach
    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...);
    
    // your code
}

This is useful if you don't know the PID of the debugging process. Furthermore, this only affects the security of your program, as opposed to setting /proc/sys/kernel/yama/ptrace_scope to 0, which makes the entire system less secure.

ealker
  • 68
  • 7