Bug 502 - Cannot run background process from sudoed script when I/O logging is enabled
Cannot run background process from sudoed script when I/O logging is enabled
Status: RESOLVED FIXED
Product: Sudo
Classification: Unclassified
Component: Sudoers
1.8.1
PC Linux
: low normal
Assigned To: Todd C. Miller
: 808 (view as bug list)
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2011-07-28 09:44 MDT by Giacomo Picconi
Modified: 2019-04-08 13:54 MDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Giacomo Picconi 2011-07-28 09:44:12 MDT
SUDO version:
stux@darkstar:/tmp$ sudo -V
Sudo version 1.8.1p2
Sudoers policy plugin version 1.8.1p2
Sudoers file grammar version 40
Sudoers I/O plugin version 1.8.1p2

Cannot run background process from sudoed script when I/O logging is enabled.

When I/O logging is enabled, sudo will run the command in a pseudo tty: if a sudoed script contais a background process call, when the sudoed script exits, the pseudo tty exits, and the backgrounded process (if still running) is killed too.

A temporarily workaround is to add a 'wait' call at the end of the sudoed script, that will prevent the sudoed script to exit before all called backgrounded processes has completed.

Example to reproduce the problem:
stux@darkstar:/tmp$ ls -al test.sh test2.sh
-rwxr--r-- 1 root root 32 Jul 28 14:27 test2.sh*
-rwxr--r-- 1 root root 23 Jul 28 15:10 test.sh*
stux@darkstar:/tmp$ cat test.sh
#!/bin/sh
./test2.sh &
stux@darkstar:/tmp$ cat test2.sh
#!/bin/sh
echo $$ > /tmp/debug
stux@darkstar:/tmp$ sudo ./test.sh
stux@darkstar:/tmp$ ls -altr /tmp/debug
/bin/ls: cannot access /tmp/debug: No such file or directory

This means that the background program ./test2.sh is not executed (file /tmp/debug does not exists).

If, in test.sh, you will execute test2.sh in foreground or (same thing) if you add a 'wait' call at the end of test.sh, the things will go right:

stux@darkstar:/tmp$ cat test.sh 
#!/bin/sh
./test2.sh &
wait
stux@darkstar:/tmp$ sudo ./test.sh
stux@darkstar:/tmp$ ls -altr /tmp/debug
-rw-r--r-- 1 root root 6 Jul 28 15:25 /tmp/debug
stux@darkstar:/tmp$

We need that sudo will not kill the backgrounded processes at exit, continuing logging the I/O of the sudoed command AND of the backgrounded process. I hope that this will be possible.

Hope that helps.
Giacomo
Comment 1 Todd C. Miller 2011-07-31 14:04:50 MDT
The problem is that the sudo process that does the logging waits for the command to complete, at which time is closes the pty master.  This causes the backgrounded command, which has the pty slave as its tty, to be sent SIGHUP by the kernel.  There's no way for sudo to tell that there is a backgrounded child process since when the command exits, any children it has are reparented to init (or whatever process 1 is).  This means there is no longer a parent-child relationship and sudo cannot wait for them as the wait system call will report that there are no children left.

This is a difficult problem to solve. Linux / Unix doesn't provide a mechanism to notify a process when, all users of a pty are finished.  On Linux it would be possible to periodically scan /proc/pid/status for every process on the system.  That is what lsof does but this is Linux-specific and somewhat race-prone.  On other systems it may be necessary to read kernel memory to find the users of the pty.  The Linux inotify interface might be usable to track when users of a tty have closed it but again, this is not portable.

Another possibility is to ptrace the child process and just tell it to ignore the SIGHUP.  The background process would continue running but no output would be logged after the pty was closed.  Of course, ptrace varies considerably from system to system so is not very portable either.
Comment 2 Todd C. Miller 2017-12-01 14:02:37 MST
It turns out this was a simpler issue than I realized.  The trick is for sudo to reclaim the controlling tty before it exits, becoming the foreground process.  Sudo and the command run in different process groups and the kernel only send SIGHUP to processes in the foreground process group, which now only consists of the sudo process itself.

The fix will be included in sudo 1.8.22.
Comment 3 Todd C. Miller 2017-12-01 14:08:20 MST
*** Bug 808 has been marked as a duplicate of this bug. ***
Comment 4 Todd C. Miller 2019-04-08 13:54:57 MDT
Fixed in sudo 1.8.22