What Do Getresuid() and Setresuid() Do

What do getresuid() and setresuid() do?

From the credentials(7) man page (abridged):

On Linux, each process has the following user and group identifiers:

  • Real user ID and real group ID. These IDs determine who owns the process.

  • Effective user ID and effective group ID. These IDs are used by the kernel to determine the permissions that the process will have when accessing shared resources such as message queues, shared memory, and semaphores. On most UNIX systems, these IDs also determine the permissions when accessing files. However, Linux uses the file system IDs for this task.

  • Saved set-user-ID and saved set-group-ID. These IDs are used in set-user-ID and set-group-ID programs to save a copy of the corresponding effective IDs that were set when the program was executed. A set-user-ID program can assume and drop privileges by switching its effective user ID back and forth between the values in its real user ID and saved set-user-ID.

Those functions get and set all three of those UIDs in one call. And as always, see the full man page for complete details.

warning: implicit declaration of function ‘getresuid’ (and ‘seteuid’)

getresuid() and seteuid() are GNU extension function, add

#define _GNU_SOURCE

before including all the headers, or add -D_GNU_SOURCE in GCC options.

You shouldn't define __USE_GNU macro directly, it's supposed to be used only internally in glibc.

seteuid/geteuid: Program always has root id

From the man page of geteuid() on my Mac (OS X 10.6.7):

The real user ID is that of the user who has invoked the program. As the effective user ID gives the process additional permissions during execution of ``set-user-ID'' mode processes, getuid() is used to determine the real-user-id of the calling process.

Since you have set the suid bit, the effective user id of the program is the file owner (root) from the start of execution.

setreuid call fails to re-establish process permissions

You're first call to setreuid is actually a no-op - it does not drop privileges, you are essentially saying set my real uid to my getuid and my effective uid to my geteuid, which in the case of a setuid app is the same as you obtained.

At the start of a setuid root program run as user bob, then getuid() == bob, geteuid() == root

If you want to drop privileges, then you should probably have called:

setreuid(euid, ruid);

Thad would have set the effective uid to bob and the real uid to rood. Everything done after that point will be as if by the unprivileged user bob, understanding that you have not completely dropped the ability to switch back to root privileges at this point, because you have not wiped out the saved-user-id information.

Obtaining root privileges would be done by:

setreuid(ruid, euid);

Similarly, at the end, when you are re-dropping privileges, you need to do the same:

setreuid(euid, ruid);

i.e. set the effective uid to the id bob. the [answer here][1] is a similar situation, which explains the details a little more concisely.

Generally, when checking this information, a little printerhelper like:

void printids(char *header) {
uid_t ruid, euid, saveduid;
getresuid(&ruid, &euid, &saveduid);
printf("%s ruid=%d euid=%d saveduid=%d\n", header, ruid, euid, saveduid);
}

assists in determining the privileges/uid information at all the steps.

it would be a little simpler to just use seteuid() for the temporary changing of the privileges, rather than the little more heavy handed setreuid(). You can also use the setresuid() call to be more explicit on the setting of the real, effective and saved userid values.

Saving and dropping privileges:

setresuid(ruid, ruid, euid);

Re-obtaining root privileges:

setresuid(euid, euid, -1);

Dropping back to non-root privileges:

setresuid(ruid, ruid, -1);

i.e. we let the saved user-id keep the root information, and manipulate the realuid and euid values toggling between root/non-root

Is getresuid deprecated in c99?

You need to define before all the headers

#define _GNU_SOURCE

as getresuid is a GNU extension function.

Why do files in /proc/self end up being owned by root if a program has its setuid bit set?

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

permanently drop root privileges on modern Linux

The "canonical" way to do this was implemented by D.J.Bernstein in his 'setuidgid' code, which was originally used into his QMail program, nowadays included in 'daemontools'.

The actual code used in GNU coreutils is based on DJB's description of the procedure, its code is visible here https://github.com/wertarbyte/coreutils/blob/master/src/setuidgid.c



Related Topics



Leave a reply



Submit