Skip to contentSkip to conversation

strace -p <pid> EPERM after root process changed uid/gid to non-root user

DISCUSSION Ole Bjorn Hessen 1 participant 2 messages Sep 28, 2012 – Oct 8, 2012

lore
Share & tools
lore
#0 lore raw

Hi,

I have a program that starts as root and changes uid/gid to a non-root user on linux. I'd like to run strace -p on that process as non-root but I do only get ptrace(PTRACE_ATTACH, ...): Operation not permitted. I can send kill to that program though as that non-root user.

Anybody care to explain what magic is neccessary for a root program to reduce priv level so that an unpriv process can strace -p that program:

Attach is a small program that changes uid from root to "news". Try to strace that program in another window:

## in window 1

echo '
#include <sys/types.h>
#include <unistd.h>

#define UID 9

int main(char **argv, int argc) {
    setresgid(UID, UID, UID);
    gid_t list[2];
    list[0] = UID;
    list[1] = 0;
    setgroups(1, list);
    setresuid(UID, UID, UID);
    while (1) {
        sleep(1);
        write(1, "hello\n", 6);
    }

return 1;
}
' > /tmp/ffo.c

gcc -o /tmp/ffo /tmp/ffo.c
super sh
/tmp/ffo

## in window 2
su news
strace -p $(ps -ef | grep ffo | grep -v grep | awk '{print $2}')
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted

## kill is ok though
kill $(ps -ef | grep ffo | grep -v grep | awk '{print $2}')

--

Kind regards,

Ole Bjorn Hessen.
Telenor
----------

#1 lore raw

Hi,

I got an email from Celelibi pointing me in the right direction (thanks!).

It seems like that it is neccessary to use prctl(PR_SET_DUMPABLE, 1) to let strace -p to work. The dumpable flag is cleared in some setuid situations.

Linux requires that real uid of strace process matches all of real uid, effective uid and saved uid and the real gid must match the real gid, effective gid and saved gid. And the dumpable flag must be set.

--

#include <sys/types.h>
#include <unistd.h>
#include <sys/prctl.h>

#define UID 9
#define GID 13

int main(int argc, char **argv) {
    setresgid(GID, GID, GID);
    setresuid(UID, UID, UID);
    prctl(PR_SET_DUMPABLE, 1);
    while (1) {
        sleep(1);
        write(1, "hello\n", 6);
    }

return 1;
}

Kind regards
Ole Bjorn Hessen.
Telenor