aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-11-24 18:24:14 -0800
committerUlrich Drepper <drepper@redhat.com>2009-11-24 18:24:14 -0800
commit139ee080b6b428240bf49f3e6361f3ac729f891a (patch)
tree6d995b56cab939c5107371e83cd5fa53fe3c3284 /sysdeps
parentfa214705b957d20621cb1190b467aa88bc9b69a3 (diff)
downloadglibc-139ee080b6b428240bf49f3e6361f3ac729f891a.zip
glibc-139ee080b6b428240bf49f3e6361f3ac729f891a.tar.gz
glibc-139ee080b6b428240bf49f3e6361f3ac729f891a.tar.bz2
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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/grantpt.c4
-rw-r--r--sysdeps/unix/sysv/linux/grantpt.c42
2 files changed, 46 insertions, 0 deletions
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index e140fb2..2a7a963 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -194,6 +194,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 0000000..6305ed4
--- /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>