aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoffrey Thomas <geofft@ldpreload.com>2015-10-19 19:33:28 +0530
committerSiddhesh Poyarekar <siddhesh@redhat.com>2015-10-19 19:33:28 +0530
commit2028f49dabb94bd56a85a7be16141bee4853aae6 (patch)
tree069f111a51dac97c261ca5a155f7168ea8a111b1
parent361468f226cb99fdebd8fabb3d9428a3632dc2d1 (diff)
downloadglibc-2028f49dabb94bd56a85a7be16141bee4853aae6.zip
glibc-2028f49dabb94bd56a85a7be16141bee4853aae6.tar.gz
glibc-2028f49dabb94bd56a85a7be16141bee4853aae6.tar.bz2
pt_chown: Clear any signal mask inherited from the parent process.
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.
-rw-r--r--ChangeLog5
-rw-r--r--login/programs/pt_chown.c6
2 files changed, 11 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b787dc..554384a 100644
--- 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.
diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
index e8d4716..4f67af7 100644
--- a/login/programs/pt_chown.c
+++ b/login/programs/pt_chown.c
@@ -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)
{