Suid and std::process bug?

I have a rust executable that attempts to subprocess and give ownership of a directory away via sudo chown. The executable is owned by a service account (jobsys) and has its suid bit set.

In my sudoers file, i have it set up for password-less usage for jobsys. eg

jobsys   ALL=(ALL) NOPASSWD: ALL

However, when I call the program, I am prompted for a password. I have confirmed that the euid is correct in the subprocess, as i print it out prior to calling sudo chown.

And if I su to jobsys and call the program directly, I am not prompted for a password so I know that the sudoers file is set up correctly.

Furthermore, this is a reimplementation of a program written in python (and wrapped in c) which worked well (albeit slowly… not this part) enough. However, I thought i would port this to rust…

So the question is whether there is some potential bug in std::subprocess (like not paying attention to euid) or if I am making some sort of incorrect assumption…

IIRC, the effective UID will be changed to root when you execute sudo because of its setuid bit, then sudo will use the real UID to determine permissions.

I thought the point of the setuid bit was to execute as the effective user not the real user

man 7 credentials:

A child process created by fork(2) inherits copies of its parent’s user and groups IDs. During an execve(2), a process’s real user and group ID and supplementary group IDs are preserved; the effective and saved set IDs may be changed, as described in execve(2).

man 2 execve:

If the set-user-ID bit is set on the program file referred to by pathname, then the effective user ID of the calling process is changed to that of the owner of the program file. Similarly, when the set-group-ID bit of the program file is set the effective group ID of the calling process is set to the group of the program file.
…
The effective user ID of the process is copied to the saved set-user-ID; similarly, the effective group ID is copied to the saved set-group-ID. This copying takes place after any effective ID changes that occur because of the set-user-ID and set-group-ID mode bits.

The process’s real UID and real GID, as well its supplementary group IDs, are unchanged by a call to execve().

So if your service executable is owned by jobsys with the setuid bit set, then when it is executed the process will start with the effective UID jobsys, without changing the real UID. You could use setreuid here to fully set yourself as jobsys, but be careful about who may be executing the service before you do this!

When that process executes sudo (setuid and owned by root), the sudo process will start with the effective UID root, still without changing the real UID at first. Then sudo will do its thing, checking its real UID for configured permissions, then setting the requested UID etc. for the command that it is going to execute.

1 Like

Some programs (e.g., dash) still check that euid == ruid as a safeguard .