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.
This commit is contained in:
Ulrich Drepper 2009-11-24 18:24:14 -08:00
parent fa214705b9
commit 139ee080b6
4 changed files with 54 additions and 3 deletions

View File

@ -1,5 +1,11 @@
2009-11-24 Ulrich Drepper <drepper@redhat.com> 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.
* sysdeps/unix/grantpt.c (grantpt): Only get tty group information * sysdeps/unix/grantpt.c (grantpt): Only get tty group information
once. once.

View File

@ -154,8 +154,7 @@ main (int argc, char *argv[])
# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0])) # define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
cap_t caps = cap_init (); cap_t caps = cap_init ();
if (caps == NULL) if (caps == NULL)
error (FAIL_ENOMEM, errno, return FAIL_ENOMEM;
_("Failed to initialize drop of capabilities"));
/* There is no reason why these should not work. */ /* There is no reason why these should not work. */
cap_set_flag (caps, CAP_PERMITTED, ncap_list, cap_list, CAP_SET); cap_set_flag (caps, CAP_PERMITTED, ncap_list, cap_list, CAP_SET);
@ -166,7 +165,7 @@ main (int argc, char *argv[])
cap_free (caps); cap_free (caps);
if (__builtin_expect (res != 0, 0)) if (__builtin_expect (res != 0, 0))
error (FAIL_EXEC, errno, _("cap_set_proc failed")); return FAIL_EXEC;
} }
#endif #endif

View File

@ -194,6 +194,10 @@ grantpt (int fd)
if (__dup2 (fd, PTY_FILENO) < 0) if (__dup2 (fd, PTY_FILENO) < 0)
_exit (FAIL_EBADF); _exit (FAIL_EBADF);
#ifdef CLOSE_ALL_FDS
CLOSE_ALL_FDS ();
#endif
execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL); execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL);
_exit (FAIL_EXEC); _exit (FAIL_EXEC);
} }

View File

@ -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>