Skip to content

Commit

Permalink
Prevent unintended file desriptor leak in grantpt.
Browse files Browse the repository at this point in the history
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 139ee08)
  • Loading branch information
Ulrich Drepper authored and Petr Baudis committed Dec 4, 2009
1 parent 4f9d265 commit 65a27b0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 3 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
5 changes: 2 additions & 3 deletions login/programs/pt_chown.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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

Expand Down
4 changes: 4 additions & 0 deletions sysdeps/unix/grantpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
42 changes: 42 additions & 0 deletions sysdeps/unix/sysv/linux/grantpt.c
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit 65a27b0

Please sign in to comment.