summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2009-11-25 14:04:18 +0100
committerAndreas Schwab <schwab@redhat.com>2009-11-25 14:04:18 +0100
commitf3a93a0820949f67c95eda882e4f4331ad26accd (patch)
treeac1945db69088fc86620e9d8264069a4c532925c
parent8757dec424e2fc887623104565243bdd66cd609b (diff)
Prevent unintended file desriptor leak in grantpt.
The pt_chown program is completely transparently called. It might not be able to live with the various file descriptors the program has open at the time of the call (e.g., under SELinux). Close all but the needed descriptor and connect stdin, stdout, and stderr with /dev/null. pt_chown shouldn't print anything when called to do real work. (cherry picked from commit 139ee080b6b428240bf49f3e6361f3ac729f891a)
-rw-r--r--ChangeLog6
-rw-r--r--login/programs/pt_chown.c5
-rw-r--r--sysdeps/unix/grantpt.c4
-rw-r--r--sysdeps/unix/sysv/linux/grantpt.c42
4 files changed, 54 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3cae5d1cf1..93c511c3f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2009-11-24 Ulrich Drepper <drepper@redhat.com>
+ * sysdeps/unix/grantpt.c (grantpt): Use CLOSE_ALL_FDS is available
+ before the exec.
+ * sysdeps/unix/sysv/linux/grantpt.c: New file.
+ * login/programs/pt_chown.c (main): Don't print message on errors
+ when doing real work.
+
* csu/elf-init.c (__libc_csu_irel): New function. Code to perform
irel relocations split out from...
(__libc_csu_init): ...here.
diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
index 7e279a5f3b..4c36f2ceac 100644
--- a/login/programs/pt_chown.c
+++ b/login/programs/pt_chown.c
@@ -154,8 +154,7 @@ main (int argc, char *argv[])
# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
cap_t caps = cap_init ();
if (caps == NULL)
- error (FAIL_ENOMEM, errno,
- _("Failed to initialize drop of capabilities"));
+ return FAIL_ENOMEM;
/* There is no reason why these should not work. */
cap_set_flag (caps, CAP_PERMITTED, ncap_list, cap_list, CAP_SET);
@@ -166,7 +165,7 @@ main (int argc, char *argv[])
cap_free (caps);
if (__builtin_expect (res != 0, 0))
- error (FAIL_EXEC, errno, _("cap_set_proc failed"));
+ return FAIL_EXEC;
}
#endif
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index 8c299e9147..b02bf7cccf 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -190,6 +190,10 @@ grantpt (int fd)
if (__dup2 (fd, PTY_FILENO) < 0)
_exit (FAIL_EBADF);
+#ifdef CLOSE_ALL_FDS
+ CLOSE_ALL_FDS ();
+#endif
+
execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL);
_exit (FAIL_EXEC);
}
diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
new file mode 100644
index 0000000000..6305ed4944
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/grantpt.c
@@ -0,0 +1,42 @@
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "not-cancel.h"
+#include "pty-private.h"
+
+
+/* Close all file descriptors except the one specified. */
+static void
+close_all_fds (void)
+{
+ DIR *dir = opendir ("/proc/self/fd");
+ if (dir != NULL)
+ {
+ struct dirent64 *d;
+ while ((d = readdir64 (dir)) != NULL)
+ if (isdigit (d->d_name[0]))
+ {
+ char *endp;
+ long int fd = strtol (d->d_name, &endp, 10);
+ if (*endp == '\0' && fd != PTY_FILENO && fd != dirfd (dir))
+ close_not_cancel_no_status (fd);
+ }
+
+ closedir (dir);
+
+ int nullfd = open_not_cancel_2 (_PATH_DEVNULL, O_RDONLY);
+ assert (nullfd == STDIN_FILENO);
+ nullfd = open_not_cancel_2 (_PATH_DEVNULL, O_WRONLY);
+ assert (nullfd == STDOUT_FILENO);
+ __dup2 (STDOUT_FILENO, STDERR_FILENO);
+ }
+}
+#define CLOSE_ALL_FDS() close_all_fds()
+
+#include <sysdeps/unix/grantpt.c>