| shadow-4.2.1: Fix CVE-2017-2616 |
| |
| [No upstream tracking] -- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=855943 |
| |
| su: properly clear child PID |
| |
| If su is compiled with PAM support, it is possible for any local user |
| to send SIGKILL to other processes with root privileges. There are |
| only two conditions. First, the user must be able to perform su with |
| a successful login. This does NOT have to be the root user, even using |
| su with the same id is enough, e.g. "su $(whoami)". Second, SIGKILL |
| can only be sent to processes which were executed after the su process. |
| It is not possible to send SIGKILL to processes which were already |
| running. I consider this as a security vulnerability, because I was |
| able to write a proof of concept which unlocked a screen saver of |
| another user this way. |
| |
| Upstream-Status: Backport [https://github.com/shadow-maint/shadow/commit/08fd4b69e84364677a10e519ccb25b71710ee686] |
| CVE: CVE-2017-2616 |
| bug: 855943 |
| Signed-off-by: Andrej Valek <andrej.valek@siemens.com> |
| |
| diff --git a/src/su.c b/src/su.c |
| index 3704217..1efcd61 100644 |
| --- a/src/su.c |
| +++ b/src/su.c |
| @@ -363,20 +363,35 @@ static void prepare_pam_close_session (void) |
| /* wake child when resumed */ |
| kill (pid, SIGCONT); |
| stop = false; |
| + } else { |
| + pid_child = 0; |
| } |
| } while (!stop); |
| } |
| |
| - if (0 != caught) { |
| + if (0 != caught && 0 != pid_child) { |
| (void) fputs ("\n", stderr); |
| (void) fputs (_("Session terminated, terminating shell..."), |
| stderr); |
| (void) kill (-pid_child, caught); |
| |
| (void) signal (SIGALRM, kill_child); |
| + (void) signal (SIGCHLD, catch_signals); |
| (void) alarm (2); |
| |
| - (void) wait (&status); |
| + sigemptyset (&ourset); |
| + if ((sigaddset (&ourset, SIGALRM) != 0) |
| + || (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0)) { |
| + fprintf (stderr, _("%s: signal masking malfunction\n"), Prog); |
| + kill_child (0); |
| + } else { |
| + while (0 == waitpid (pid_child, &status, WNOHANG)) { |
| + sigsuspend (&ourset); |
| + } |
| + pid_child = 0; |
| + (void) sigprocmask (SIG_UNBLOCK, &ourset, NULL); |
| + } |
| + |
| (void) fputs (_(" ...terminated.\n"), stderr); |
| } |
| |