I have an executable binary which was compiled from a C source file
The executable has the setuid permission on
I noticed that, if the owner of the executable is root, I can use
setuid(geteuid());
when compiling the file to set the real UID of my the process running the executable to be root. Then, anyone who runs the executable can run it as root.
However, I noticed that only happens when the owner of the executable is root. It did not work when I tried to give test_user ownership of the executable (and fixing permissions to contain setuid again). After reading these documentation pages (1, 2, 3) and reading this post, I noticed that setuid(new_euid)
is meant to change the effective UID instead of the real UID of the process running the exectuable. It just happens that, under particular circumstances (effective UID is root), setuid(new_euid)
also sets the real UID and saved UID of the process running the executable to new_euid
.
I solved the issue by using setreuid
instead of setuid
, as follows:
setreuid(geteuid(), geteuid());
Which allowed me to set the real UID of the process to be the effective UID (owner of the executable) and reset effective UID to it's value (redundant).
I understand that setuid()
will work under certain conditions, but is not less confusing and more appropriate to just use setreuid()
, setresuid()
, or seteuid()
when changing real UID, saved UID, or effective UID is desired since they always work?
Moreover: I understand that seteuid()
appears to be doing the same as setuid()
with the difference explained here (effective UID is root). This is supposed to not allow root priviledged programs regain priviledges after dropping them (because all 3 UIDs would be changed to the same value using setuid()
)? So should I just use setuid()
for root priviledged programs even when it is not as clear compared to setresuid()
for example?
I see that setuid()
can be secure since it doesn't allow root priviledged programs regain priviledges once droped, but that behavior can be implemented using the other mentioned functions with less confussion.
Another thing getuid()
returns the real UID of the process while setuid()
is meant for modifying effective UID (unless priviledged), which is also confusing.