Use of setreuid() where _POSIX_SAVED_IDS is not set

1.4k views Asked by At

I am exploring the suid area, and found myself unable to answer this question. For the sake of the question, lets assume the program binary is suid, owned by user 1001 and ran by user 1000 (both non-root) - therefor RUID=1000, EUID=1001.

When _POSIX_SAVED_IDS is set, I can use setuid() and seteuid() in order to change the RUID and EUID (respectively) between 1000 and 1001.

However, when _POSIX_SAVED_IDS is not set, seteuid(1000) will render doing seteuid(1001) impossible later, and setuid(1001) will do the same to setuid(1000) later on.

In order to change the EUID to the RUID and keep the possibility of going back later on, the solution I found here GNU Setuid Program Example is to use setreuid(1001,1000) (swapping them). What are the effects of this on the program, since it changes the RUID? From what I understand, it changes the owner of the process, and therefor has implications on permissions of killing or interacting with the process.
What systems do not use _POSIX_SAVED_IDS?

2

There are 2 answers

4
R.. GitHub STOP HELPING ICE On

Since POSIX requires _POSIX_SAVED_IDS to be defined with positive value, no systems should lack _POSIX_SAVED_IDS.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html

0
Norbert Lange On

I just had to deal with this and the part below is not properly answered so far.

In order to change the EUID to the RUID and keep the possibility of going back later on, the solution I found here GNU Setuid Program Example is to use setreuid(1001,1000) (swapping them). What are the effects of this on the program, since it changes the RUID? From what I understand, it changes the owner of the process, and therefor has implications on permissions of killing or interacting with the process.

what happens everywhere, is that the EUID is the only thing that's used for permissions like accessing files or being able to kill processes (some rare exceptions might apply). The idea is that you can switch back and forth between the EUID and RUID, but only between those. The Kernel needs to keep track of those two ids.

seteuid for non-root users is only allowed to switch to one of EUID, RUID and - should the kernel support it - SUID.

With a system being conform with POSIX, a SUID is avaliable, so this will happen:

// uids are: EUID=1001, RUID=1000, SUID=1001
seteuid(1000) ; // works because RUID=1000
// uids are: EUID=1000, RUID=1000, SUID=1001
seteuid(1001); // works because SUID=1001

on systems without a SUID:

// uids are: EUID=1001, RUID=1000
seteuid(1000); // works because RUID=1000
// uids are: EUID=1000, RUID=1000
seteuid(1001); // fails, neither EUID, nor RUID is 1001

conversely

// uids are: EUID=1001, RUID=1000
setreuid(1001, 1000) ; // works because EUID=1001 and RUID=1000
// uids are: EUID=1000, RUID=1001
setreuid(1000, 1001); // works because EUID=1000 and RUID=1001

I have not found a standard way of permanently dropping privileges on a POSIX conform system, as this required modifying the SUID. only a gnu extension is avaliable:

// uids are: EUID=1001, RUID=1000, SUID=1001
setresuid(1000, 1000, 1000);
// uids are: EUID=1000, RUID=1000, SUID=1000

see: https://people.eecs.berkeley.edu/~daw/papers/setuid-usenix02.pdf