supervision - discussion about system services, daemon supervision, init, runlevel management, and tools such as s6 and runit
 help / color / mirror / Atom feed
* Improper setting / resetting of the signals mask
@ 2010-09-14 11:14 Ciprian Dorin, Craciun
  2010-09-14 13:49 ` Todd C. Miller
  2010-09-14 20:22 ` Laurent Bercot
  0 siblings, 2 replies; 3+ messages in thread
From: Ciprian Dorin, Craciun @ 2010-09-14 11:14 UTC (permalink / raw)
  To: supervision, sudo-users

    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.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Improper setting / resetting of the signals mask
  2010-09-14 11:14 Improper setting / resetting of the signals mask Ciprian Dorin, Craciun
@ 2010-09-14 13:49 ` Todd C. Miller
  2010-09-14 20:22 ` Laurent Bercot
  1 sibling, 0 replies; 3+ messages in thread
From: Todd C. Miller @ 2010-09-14 13:49 UTC (permalink / raw)
  Cc: supervision, sudo-users

In message <AANLkTik39j45XmArWreOJK71hMr561iD0iw04qYXN=2i@mail.gmail.com>
	so spake "Ciprian Dorin, Craciun" (ciprian.craciun):

>     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.)

The following patch should address that.

 - todd

--- sudo.c.orig	Mon Sep  6 08:16:09 2010
+++ sudo.c	Tue Sep 14 09:48:48 2010
@@ -1050,9 +1050,14 @@
 initial_setup()
 {
     int miss[3], devnull = -1;
+    sigset_t mask;
 #if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL))
     struct rlimit rl;
 #endif
+
+    /* Reset signal mask. */
+    (void) sigemptyset(&mask);
+    (void) sigprocmask(SIG_SETMASK, &mask, NULL);
 
 #if defined(__linux__)
     /*
____________________________________________________________
sudo-users mailing list <sudo-users@sudo.ws>
For list information, options, or to unsubscribe, visit:
http://www.sudo.ws/mailman/listinfo/sudo-users


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Improper setting / resetting of the signals mask
  2010-09-14 11:14 Improper setting / resetting of the signals mask Ciprian Dorin, Craciun
  2010-09-14 13:49 ` Todd C. Miller
@ 2010-09-14 20:22 ` Laurent Bercot
  1 sibling, 0 replies; 3+ messages in thread
From: Laurent Bercot @ 2010-09-14 20:22 UTC (permalink / raw)
  To: Ciprian Dorin, Craciun; +Cc: supervision, sudo-users

>     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.)

 Hello Ciprian,
 If you're going to blame sudo for not resetting the signal mask,
why not also blame bash, which is executed between runsv and sudo ? :)
It seems natural to think that a shell should reset the sigprocmask.
I just checked SUSv3, which says nothing about that; so, by default,
ignoring the sigprocmask is probably the right thing to do, and
bash (for once) gets it right.

 It is debatable whether sudo should be paranoid and also unblock
signals. On the one hand, the *point* of sudo is to be paranoid. On
the other hand, applications can and generally should expect to be
executed in a sane environment, and be liberal in what they accept
(i.e. they should not arbitrarily close fds or remove environment
variables, for instance - and I don't think they should arbitrarily
unblock signals either).

 What is certain is that runsv does the wrong thing here: blocked
signals should definitely be unblocked before exec'ing an external
command. I'm sure Gerrit will agree and fix that in a next release.

 In the meantime, let me suggest 2 workarounds:

 - You can use the 'trap' shell command to manually unblock signals.
SUSv3 does not even specify that using 'trap' should unblock the
trapped, or defaulted, signals, but not doing it would be clearly
absurd. 'trap - TERM' and you should be rolling.

 - In this precise case, you don't even need sudo. If all you want
is to give user 'joe' enough rights to control /service/foo, you
can make /service/foo/supervise/control writable by 'joe'. For
instance:
# chown joe /service/foo/supervise/control

 Then, no need for elaborate control scripts: all the complexity
of the script can be moved to the client side, and joe just runs
'sv force-restart /service/foo' when appropriate.

-- 
 Laurent


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-09-14 20:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-14 11:14 Improper setting / resetting of the signals mask Ciprian Dorin, Craciun
2010-09-14 13:49 ` Todd C. Miller
2010-09-14 20:22 ` Laurent Bercot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).