Search code examples
linuxbashshellexecsudo

Switch user without creating an intermediate process


I'm able to use sudo or su to execute a command as another user. By combining with exec, I'm able to replace the current process with sudo or su, and a child process running the command. But I want to replace the current process with the command running as another user. How do I do that?

Testing with sleep inf as the command, and someguy as the user:

exec su someguy -c 'sleep inf'

This gives me from pstree:

bash───su───sleep

And

exec sudo -u someguy sleep inf

gives

bash───sudo───sleep

In both cases I just want the sleep command, with bash as the parent.

I expect I could do this from C with something some sequence of setuid() and exec().


Solution

  • The difference between sudo sleep and exec sudo sleep is that in the second command sudo process replaces bash image and calling shell process exits when sleep exits

    pstree -p $$
    bash(8765)───pstree(8943)
    
    ((sleep 1; pstree -p $$ )&); sudo -u user sleep 2
    bash(8765)───sudo(8897)───sleep(8899)
    
    ((sleep 1; pstree -p $$ )&); exec sudo -u user sleep 2
    sudo(8765)───sleep(8993)
    

    however the fact that sudo or su fork a new process depends on design and their implementation (some sources found here).

    From sudo man page :

    Process model

    When sudo runs a command, it calls fork(2), sets up the execution environment as described above, and calls the execve system call in the child process. The main sudo process waits until the command has completed, then passes the command's exit status to the security policy's close function and exits. If an I/O logging plugin is config- ured or if the security policy explicitly requests it, a new pseudo-terminal (“pty”) is created and a second sudo process is used to relay job control signals between the user's existing pty and the new pty the command is being run in. This extra process makes it possible to, for example, suspend and resume the command. Without it, the com- mand would be in what POSIX terms an “orphaned process group” and it would not receive any job control signals. As a special case, if the policy plugin does not define a close function and no pty is required, sudo will execute the command directly instead of calling fork(2) first. The sudoers policy plugin will only define a close function when I/O logging is enabled, a pty is required, or the pam_session or pam_setcred options are enabled. Note that pam_session and pam_setcred are enabled by default on sys- tems using PAM.