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.
Any suid process will default to have its /proc/self
directory owned by root for security reasons (to prevent users from inducing a core dump and inspecting its memory for valuable info).
You can set the owner after a suid
by manually making the process dumpable with the prctl PR_SET_DUMPABLE
.
Here's proc(5)
, containing a description of what's going on and how to affect it:
/proc/[pid]
There is a numerical subdirectory for each running
process; the subdirectory is named by the process
ID.
Each /proc/[pid] subdirectory contains the pseudo-
files and directories described below. These
files are normally owned by the effective user and
effective group ID of the process. However, as a
security measure, the ownership is made root:root
if the process's "dumpable" attribute is set to a
value other than 1. This attribute may change for
the following reasons:
* The attribute was explicitly set via the
prctl(2) PR_SET_DUMPABLE operation.
* The attribute was reset to the value in the
file /proc/sys/fs/suid_dumpable (described
below), for the reasons described in prctl(2).
Resetting the "dumpable" attribute to 1 reverts
the ownership of the /proc/[pid]/* files to the
process's real UID and real GID.
Below, suid_dumpable
has this to say about why the default is what it is:
1 ("debug")
All processes dump core when possible.
(Reasons why a process might nevertheless
not dump core are described in core(5).)
The core dump is owned by the filesystem
user ID of the dumping process and no secu‐
rity is applied. This is intended for sys‐
tem debugging situations only: this mode is
insecure because it allows unprivileged
users to examine the memory contents of
privileged processes.
And as a bonus, prctl(2)
lists non-suid circumstances that affect dumpability:
PR_SET_DUMPABLE (since Linux 2.3.20)
(...)
Normally, this flag is set to 1. However, it is
reset to the current value contained in the file
/proc/sys/fs/suid_dumpable (which by default has
the value 0), in the following circumstances:
* The process's effective user or group ID is
changed.
* The process's filesystem user or group ID is
changed (see credentials(7)).
* The process executes (execve(2)) a set-user-ID
or set-group-ID program, resulting in a change
of either the effective user ID or the effec‐
tive group ID.
(...)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.