From: Tobias Stoeckmann Date: Mon, 23 Mar 2026 18:41:12 +0000 (+0100) Subject: su: Fix signal race during shutdown X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb2f6b0cc040e1af410d4f1f350e276a19d9ba2c;p=thirdparty%2Futil-linux.git su: Fix signal race during shutdown The caught_signal variable could be modified while the original signal handler is restored. If this happens, su does not kill itself with the signal but just triggers another installed signal handler, ultimately exiting with return value 1 instead. Prevent this race by storing the value on stack and then proceed with this definitely fixed value. Signed-off-by: Tobias Stoeckmann --- diff --git a/login-utils/su-common.c b/login-utils/su-common.c index d51fca09e..acdb60a99 100644 --- a/login-utils/su-common.c +++ b/login-utils/su-common.c @@ -633,6 +633,8 @@ static void create_watching_parent(struct su_context *su) supam_cleanup(su, PAM_SUCCESS); if (caught_signal) { + int sig; + if (su->child != (pid_t)-1) { DBG(SIG, ul_debug("killing child")); sleep(2); @@ -647,7 +649,8 @@ static void create_watching_parent(struct su_context *su) * terminal settings (kzak -- Jun 2013). */ DBG(SIG, ul_debug("restore signals setting")); - switch (caught_signal) { + sig = caught_signal; + switch (sig) { case SIGTERM: sigaction(SIGTERM, &su->oldact[SIGTERM_IDX], NULL); break; @@ -660,11 +663,11 @@ static void create_watching_parent(struct su_context *su) default: /* just in case that signal stuff initialization failed and * caught_signal = true */ - caught_signal = SIGKILL; + sig = SIGKILL; break; } - DBG(SIG, ul_debug("self-send %d signal", caught_signal)); - kill(getpid(), caught_signal); + DBG(SIG, ul_debug("self-send %d signal", sig)); + kill(getpid(), sig); } DBG(MISC, ul_debug("exiting [rc=%d]", status));