I have this small program:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <sys/prctl.h>
extern char **environ;
int main()
{
char * const arglist[] = { "/bin/ls", "-l", "/proc/self/maps", NULL };
uid_t uid, euid, suid;
gid_t gid, egid, sgid;
getresuid(&uid, &euid, &suid);
printf("Before: uid: %u, euid: %u, suid: %u\n", uid, euid, suid);
uid = euid;
setresuid(uid, euid, suid);
getresuid(&uid, &euid, &suid);
printf(" After: uid: %u, euid: %u, suid: %u\n", uid, euid, suid);
getresgid(&gid, &egid, &sgid);
printf("Before: gid: %u, egid: %u, sgid: %u\n", gid, egid, sgid);
gid = egid;
setresuid(gid, egid, sgid);
getresuid(&gid, &egid, &sgid);
printf(" After: gid: %u, egid: %u, sgid: %u\n", gid, egid, sgid);
printf("Get result == %d\n", prctl(PR_GET_DUMPABLE, 0, 0, 0, 0));
printf("Set result == %d\n", prctl(PR_SET_DUMPABLE, 1, 0, 0, 0));
printf("Get result == %d\n", prctl(PR_GET_DUMPABLE, 0, 0, 0, 0));
if (fork())
{
return 0;
}
execve(arglist[0], arglist, environ);
}
I compile this program into an executable named small-test
and change it's ownership to a testing user:
[omnifarious@foohost ~]$ ls -l small-test
-rwxrwxr-x. 1 testing testing 8512 Oct 23 12:55 small-test
Then I run the program:
[omnifarious@foohost ~]$ ./small-test
Before: uid: 1001, euid: 1001, suid: 1001
After: uid: 1001, euid: 1001, suid: 1001
Before: gid: 1001, egid: 1001, sgid: 1001
After: gid: 1001, egid: 1001, sgid: 1001
Get result == 1
Set result == 0
Get result == 1
-r--r--r--. 1 hopper hopper 0 Oct 23 14:50 /proc/self/maps
So far, so good. Then I do this:
[omnifarious@foohost ~]$ sudo chmod ug+s ./small-test
[omnifarious@foohost ~]$ ls -l ./small-test
-rwsrwsr-x. 1 testing testing 8512 Oct 23 12:55 ./small-test
[omnifarious@foohost ~]$ ./small-test
Before: uid: 1001, euid: 1002, suid: 1002
After: uid: 1002, euid: 1002, suid: 1002
Before: gid: 1001, egid: 1002, sgid: 1002
After: gid: 1002, egid: 1002, sgid: 1002
Get result == 0
Set result == 0
Get result == 1
-r--r--r--. 1 root root 0 Oct 23 12:59 /proc/self/maps
Why does /proc/self/maps
end up being owned by root
instead of by testing
or omnifarious
? Note that the result does not change if I remove the fork
.
The reason this is vexing me is that I need create a program that puts itself in a namespace as a user other than the one that executed it. This is so that I don't have access to cgroups and other things owned by the user that started the program. But I'm not being allowed to write to the program's uid_map
or gid_map
and so I can't set up the namespace properly.
Note: I edited this question to include a call to prctl
to set (and read) the DUMPABLE
flag as an answer (and the manual) indicated that resetting this should fix the owner on /proc/self/*
files. It didn't, as you can see by the new program.
Edit: The above program has a bug in which it is calling setresuid
instead of setresgid
. This is what caused my problem even after adding the call to prctl
. The prctl(PR_SET_DUMPABLE, 1);
call has no effect if the real and effective group and user ids of the process are not the same.