summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalint Reczey <balint@balintreczey.hu>2017-02-24 01:32:27 +0100
committerBalint Reczey <balint@balintreczey.hu>2017-02-24 01:50:09 +0100
commitbc6cd09194f3d289bbd1729260ae2869989e9182 (patch)
tree9929a761327325355928a848aec26d46bc41261a
parentb8a7c3ac04619620f6bae08e74bc961f300fd9fb (diff)
downloadshadow-bc6cd09194f3d289bbd1729260ae2869989e9182.tar.gz
su: properly clear child PID (CVE-2017-2616)
Closes: #855943
-rw-r--r--debian/patches/0008-su-properly-clear-child-PID.patch60
-rw-r--r--debian/patches/series1
2 files changed, 61 insertions, 0 deletions
diff --git a/debian/patches/0008-su-properly-clear-child-PID.patch b/debian/patches/0008-su-properly-clear-child-PID.patch
new file mode 100644
index 00000000..25f435b6
--- /dev/null
+++ b/debian/patches/0008-su-properly-clear-child-PID.patch
@@ -0,0 +1,60 @@
+From 08fd4b69e84364677a10e519ccb25b71710ee686 Mon Sep 17 00:00:00 2001
+From: Tobias Stoeckmann <tobias@stoeckmann.org>
+Date: Thu, 23 Feb 2017 09:47:29 -0600
+Subject: [PATCH] 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.
+---
+ src/su.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+--- a/src/su.c
++++ b/src/su.c
+@@ -363,11 +363,13 @@
+ /* 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);
+@@ -377,9 +379,22 @@
+ snprintf (wait_msg, 256, _(" ...waiting for child to terminate.\n"));
+
+ (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);
+ }
+
diff --git a/debian/patches/series b/debian/patches/series
index a2082f51..553c190b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,6 +5,7 @@
0005-Update-for-German-man-pages.patch
0006-French-manpage-translation.patch
0007-Fix-some-spelling-issues-in-the-Norwegian-translatio.patch
+0008-su-properly-clear-child-PID.patch
# These patches are only for the testsuite:
#900_testsuite_groupmems
#901_testsuite_gcov