pt_chown: Clear any signal mask inherited from the parent process.
authorGeoffrey Thomas <geofft@ldpreload.com>
Mon, 19 Oct 2015 14:03:28 +0000 (19:33 +0530)
committerSiddhesh Poyarekar <siddhesh@redhat.com>
Mon, 19 Oct 2015 14:03:28 +0000 (19:33 +0530)
If grantpt() is called from a thread that is masking signals (for
instance, from a program using signalfd or using a dedicated
signal-handling thread), then that mask will get inherited to pt_chown.
This means that signals like SIGINT will not interrup pt_chown, so if it
hangs (e.g., because getgrnam("tty") hangs on a remote name service),
Ctrl-C will terminate the parent process but leave pt_chown around. Since
it's setuid, it's hard to kill any other way.

It is safe for pt_chown to unmask all signals, because grantpt() can be
(and usually is) called from an unprivileged process with all signals
unmasked.

ChangeLog
login/programs/pt_chown.c

index 6b787dc..554384a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-19  Geoffrey Thomas  <geofft@ldpreload.com>
+
+       * login/programs/pt_chown.c: Include signal.h
+       (main): Clear any signal mask from the parent process.
+
 2015-10-19  Joseph Myers  <joseph@codesourcery.com>
 
        * configure.ac (libc_cv_gnu89_inline): Remove configure test.
index e8d4716..4f67af7 100644 (file)
@@ -23,6 +23,7 @@
 #include <grp.h>
 #include <libintl.h>
 #include <locale.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -148,6 +149,11 @@ main (int argc, char *argv[])
   uid_t euid = geteuid ();
   uid_t uid = getuid ();
   int remaining;
+  sigset_t signalset;
+
+  /* Clear any signal mask from the parent process.  */
+  sigemptyset (&signalset);
+  sigprocmask (SIG_SETMASK, &signalset, NULL);
 
   if (argc == 1 && euid == 0)
     {