diff options
author | Karel Zak | 2017-08-11 17:05:00 +0200 |
---|---|---|
committer | Karel Zak | 2017-09-18 11:48:56 +0200 |
commit | 8ce9c38690103fa18fc17fa209996ce747186cd4 (patch) | |
tree | 6f0ac7897a3519f166f97b6f524e63d290acf168 /login-utils | |
parent | su: clean up signals usage (diff) | |
download | kernel-qcow2-util-linux-8ce9c38690103fa18fc17fa209996ce747186cd4.tar.gz kernel-qcow2-util-linux-8ce9c38690103fa18fc17fa209996ce747186cd4.tar.xz kernel-qcow2-util-linux-8ce9c38690103fa18fc17fa209996ce747186cd4.zip |
su: unblock signals is all initialized
This patch a little bit reorders signals initialization. The original
code unblocks SIGINT SIGQUIT before signal handler is set for the
signals. It means there is a small possible race.
It seems better to compose wanted mask, setup handlers and then
unblock all the wanted signals.
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'login-utils')
-rw-r--r-- | login-utils/su-common.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/login-utils/su-common.c b/login-utils/su-common.c index 542f9f07d..d2b0ad1ea 100644 --- a/login-utils/su-common.c +++ b/login-utils/su-common.c @@ -364,12 +364,9 @@ static void create_watching_parent(struct su_context *su) warn(_("cannot change directory to %s"), "/"); /* + * Signals setup + * * 1) block all signals - * 2) add handler for SIGTERM - * 3) unblock signals: - * - SIGINT SIGQUIT (if no session) - * - SIGTERM SIGALRM - * 4) add handler for SIGINT SIGQUIT (if no session) */ sigfillset(&ourset); if (sigprocmask(SIG_BLOCK, &ourset, NULL)) { @@ -382,32 +379,51 @@ static void create_watching_parent(struct su_context *su) action.sa_handler = su_catch_sig; sigemptyset(&action.sa_mask); action.sa_flags = 0; + sigemptyset(&ourset); + /* 2a) add wanted signals to the mask (for session) */ if (!su->same_session && (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT))) { - warn(_("cannot set signal handler")); + warn(_("cannot initialize signal mask for session")); caught_signal = true; } + /* 2b) add wanted generic signals to the mask */ if (!caught_signal && (sigaddset(&ourset, SIGTERM) - || sigaddset(&ourset, SIGALRM) - || sigaction(SIGTERM, &action, &oldact[SIGTERM_IDX]) - || sigprocmask(SIG_UNBLOCK, &ourset, NULL))) { + || sigaddset(&ourset, SIGALRM))) { - warn(_("cannot set signal handler")); + warn(_("cannot initialize signal mask")); caught_signal = true; } + + /* 3a) set signal handlers (for session) */ if (!caught_signal && !su->same_session && (sigaction(SIGINT, &action, &oldact[SIGINT_IDX]) || sigaction(SIGQUIT, &action, &oldact[SIGQUIT_IDX]))) { + warn(_("cannot set signal handler for session")); + caught_signal = true; + } + + /* 3b) set signal handlers */ + if (!caught_signal + && sigaction(SIGTERM, &action, &oldact[SIGTERM_IDX])) { + warn(_("cannot set signal handler")); caught_signal = true; } + + /* 4) unblock wanted signals */ + if (!caught_signal + && sigprocmask(SIG_UNBLOCK, &ourset, NULL)) { + + warn(_("cannot set signal mask")); + caught_signal = true; + } } /* |