[sudo-users] Improper setting / resetting of the signals mask
Ciprian Dorin, Craciun
ciprian.craciun at gmail.com
Tue Sep 14 07:14:45 EDT 2010
Hello all!
Sorry for cross-posting, but this "bug" is relevant to both
projects (`runit` and `sudo`), so please forgive me in advance. :)
In short `sudo` doesn't seem to reset (zero out) its inherited
signal mask, and `runit` seems to leave some signals blocked when
exec-ing children. (And the side-effect is breaking some service
management scripts.)
Now the long story:
* (`runit` specific) it seems that when `runit` starts the
`./contro/t` script it leaves some signals blocked (at least the mask
0x14000) (see below in the transcript from `ps s $PID`); (it seems
that this happens only for `./contro/X` and not for the `./run`
scripts;)
* (`sudo` specific) it seems that when `sudo` starts it doesn't
reset the inherited blocked signals, on which it seems to rely for
detecting when the child process finished; (and this only happens with
the latest versions of `sudo` (`1.7.4p3`), because until now sudo
didn't forked and waited for the child but instead it `execve`-d it;
now because it uses the `pam-session` feature it waits for the child
to terminate...)
The following snippet is part of the `./control/t` script which
only sends `TERM` followed by `KILL` signals to the service. It uses
`sudo` to elevate the rights from my normal user to that of root.
~~~~
#!/bin/bash
set -e +m -u -o pipefail || exit 1
exec 2>&1
echo "before sudo" >>/tmp/transcript.txt
ps s "${$}" >>/tmp/transcript.txt
test "${#}" -eq 0
test "${UID}" -eq 0 || exec sudo -u "#0" -g "#${UID}" -E -P -n -- "${0}" "${@}"
echo "after sudo" >>/tmp/transcript.txt
ps s "${$}" >>/tmp/transcript.txt
pid="$( cat ./supervise/pid )"
test -e "/proc/${pid}" || exit 1
kill -s TERM "${pid}" || true
sleep 0.1s
test -e "/proc/${pid}" || exit 0
sleep 1s
test -e "/proc/${pid}" || exit 0
kill -s KILL "${pid}" || true
exit 0
~~~~
And the following is the result of running the script. See the
BLOCKED (0x14000) signal mask:
* the first "before sudo" text and the `ps` output line is before
executing `sudo` (thus showing that `runit` doesn't clear the blocked
signals mask);
* the second "before sudo" text and the `ps` line is after
executing `sudo` (and before the UID test) and the masks are just like
the previous output (thus showing that sudo doesn't reset the masks);
~~~~
before sudo
UID PID PENDING BLOCKED IGNORED
CAUGHT STAT TTY TIME COMMAND
10101 5935 0000000000000000 0000000000014000 0000000000000004
0000000000010002 S ? 0:00 /bin/bash control/t
before sudo
UID PID PENDING BLOCKED IGNORED
CAUGHT STAT TTY TIME COMMAND
0 5937 0000000000000000 0000000000014000 0000000000000004
0000000000010002 S ? 0:00 /bin/bash control/t
~~~~
And the following is the result of running the same script but
with a minor modification (see the `nosig` wrapper in front of `sudo`
which is just a simple C application that manually clears all signal
masks before `execve`-ing):
* see that the BLOCKED mask before using `nosig` is the same as in
the previous case, but:
* by using `nosig` followed by `sudo` the signal masks are cleared
(I think that the "0x10000" signal is blocked by BASH in any case);
~~~~
test "${UID}" -eq 0 || exec nosig sudo -u "#0" -g "#${UID}" -E -P -n
-- "${0}" "${@}"
~~~~
before sudo
UID PID PENDING BLOCKED IGNORED
CAUGHT STAT TTY TIME COMMAND
10101 6067 0000000000000000 0000000000014000 0000000000000004
0000000000010002 S ? 0:00 /bin/bash control/t
before sudo
UID PID PENDING BLOCKED IGNORED
CAUGHT STAT TTY TIME COMMAND
0 6069 0000000000000000 0000000000010000 0000000000000004
0000000000010002 S ? 0:00 /bin/bash control/t
~~~~
So thank you for paying attention to my report, and I hope it'll
be helpful for the developers.
Ciprian.
More information about the sudo-users
mailing list