]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Prevent unintended file desriptor leak in grantpt.
authorAndreas Schwab <schwab@redhat.com>
Wed, 25 Nov 2009 13:04:18 +0000 (14:04 +0100)
committerAndreas Schwab <schwab@redhat.com>
Wed, 25 Nov 2009 13:04:18 +0000 (14:04 +0100)
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)

ChangeLog
login/programs/pt_chown.c
sysdeps/unix/grantpt.c
sysdeps/unix/sysv/linux/grantpt.c [new file with mode: 0644]

index 3cae5d1cf150ebcc6e8298f6c52ebb270025fe4d..93c511c3f00129a56c8f58d3ec655cd1d7f47f68 100644 (file)
--- 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.
index 7e279a5f3b6848170146d5964e8e7f07f34392c6..4c36f2ceac7d5408d255c39f25efe989942a4a2d 100644 (file)
@@ -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
 
index 8c299e91478a2b610c59a84b797ac601f361edc9..b02bf7cccf485bba4d167f71778ff76d929882a6 100644 (file)
@@ -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 (file)
index 0000000..6305ed4
--- /dev/null
@@ -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>