summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2009-11-30 15:01:58 +0100
committerAndreas Schwab <schwab@redhat.com>2009-11-30 15:01:58 +0100
commit54ff413202df84fc1e90d5299a9eb55f2bf4eb31 (patch)
tree2e5c0006e2aaf0514cf30373e9b3ff1dc0c1fe6b /sysdeps
parentb127b8513f55a7d1a9312f32740914ed764f080c (diff)
parentb55ec98c6490b944593243c7da54dda1796e3f84 (diff)
Merge remote branch 'origin/master' into fedora/master
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/grantpt.c59
-rw-r--r--sysdeps/unix/sysv/linux/grantpt.c42
-rw-r--r--sysdeps/unix/sysv/linux/ptsname.c37
3 files changed, 97 insertions, 41 deletions
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index 8c299e9147..260e8273f8 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -38,7 +38,7 @@
this buffer, a sufficiently long buffer is allocated using malloc,
and returned in PTS. 0 is returned upon success, -1 otherwise. */
static int
-pts_name (int fd, char **pts, size_t buf_len)
+pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp)
{
int rv;
char *buf = *pts;
@@ -49,7 +49,7 @@ pts_name (int fd, char **pts, size_t buf_len)
if (buf_len)
{
- rv = __ptsname_r (fd, buf, buf_len);
+ rv = __ptsname_internal (fd, buf, buf_len, stp);
if (rv != 0)
{
if (rv == ENOTTY)
@@ -108,15 +108,8 @@ grantpt (int fd)
#endif
char *buf = _buf;
struct stat64 st;
- char *grtmpbuf;
- struct group grbuf;
- size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
- struct group *p;
- uid_t uid;
- gid_t gid;
- pid_t pid;
-
- if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf)), 0))
+
+ if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf), &st), 0))
{
int save_errno = errno;
@@ -126,34 +119,42 @@ grantpt (int fd)
return -1;
/* If the filedescriptor is no TTY, grantpt has to set errno
- to EINVAL. */
+ to EINVAL. */
if (save_errno == ENOTTY)
- __set_errno (EINVAL);
+ __set_errno (EINVAL);
else
__set_errno (save_errno);
return -1;
}
- if (__xstat64 (_STAT_VER, buf, &st) < 0)
- goto cleanup;
-
/* Make sure that we own the device. */
- uid = __getuid ();
+ uid_t uid = __getuid ();
if (st.st_uid != uid)
{
if (__chown (buf, uid, st.st_gid) < 0)
goto helper;
}
- /* Get the group ID of the special `tty' group. */
- if (grbuflen == (size_t) -1L)
- /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX.
- Try a moderate value. */
- grbuflen = 1024;
- grtmpbuf = (char *) __alloca (grbuflen);
- __getgrnam_r (TTY_GROUP, &grbuf, grtmpbuf, grbuflen, &p);
- gid = p ? p->gr_gid : __getgid ();
+ static int tty_gid = -1;
+ if (__builtin_expect (tty_gid == -1, 0))
+ {
+ char *grtmpbuf;
+ struct group grbuf;
+ size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
+ struct group *p;
+
+ /* Get the group ID of the special `tty' group. */
+ if (grbuflen == (size_t) -1L)
+ /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX.
+ Try a moderate value. */
+ grbuflen = 1024;
+ grtmpbuf = (char *) __alloca (grbuflen);
+ __getgrnam_r (TTY_GROUP, &grbuf, grtmpbuf, grbuflen, &p);
+ if (p != NULL)
+ tty_gid = p->gr_gid;
+ }
+ gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;
/* Make sure the group of the device is that special group. */
if (st.st_gid != gid)
@@ -174,9 +175,9 @@ grantpt (int fd)
goto cleanup;
/* We have to use the helper program. */
- helper:
+ helper:;
- pid = __fork ();
+ pid_t pid = __fork ();
if (pid == -1)
goto cleanup;
else if (pid == 0)
@@ -190,6 +191,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..f2fc60f83a
--- /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>
diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c
index 9c364b18b4..129d09085e 100644
--- a/sysdeps/unix/sysv/linux/ptsname.c
+++ b/sysdeps/unix/sysv/linux/ptsname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2001, 2002, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
@@ -67,14 +67,10 @@ ptsname (int fd)
}
-/* Store at most BUFLEN characters of the pathname of the slave pseudo
- terminal associated with the master FD is open on in BUF.
- Return 0 on success, otherwise an error number. */
int
-__ptsname_r (int fd, char *buf, size_t buflen)
+__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
{
int save_errno = errno;
- struct stat64 st;
unsigned int ptyno;
if (buf == NULL)
@@ -93,7 +89,7 @@ __ptsname_r (int fd, char *buf, size_t buflen)
if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
{
/* Buffer we use to print the number in. For a maximum size for
- `int' of 8 bytes we never need more than 20 digits. */
+ `int' of 8 bytes we never need more than 20 digits. */
char numbuf[21];
const char *devpts = _PATH_DEVPTS;
const size_t devptslen = strlen (_PATH_DEVPTS);
@@ -121,21 +117,23 @@ __ptsname_r (int fd, char *buf, size_t buflen)
return ERANGE;
}
- if (__fxstat64 (_STAT_VER, fd, &st) < 0)
+ if (__fxstat64 (_STAT_VER, fd, stp) < 0)
return errno;
/* Check if FD really is a master pseudo terminal. */
- if (! MASTER_P (st.st_rdev))
+ if (! MASTER_P (stp->st_rdev))
{
__set_errno (ENOTTY);
return ENOTTY;
}
- ptyno = minor (st.st_rdev);
+ ptyno = minor (stp->st_rdev);
+#if __LINUX_KERNEL_VERSION >= 131443
/* This is for the old BSD pseudo terminals. As of Linux
- 2.1.115 these are no longer supported. */
- if (major (st.st_rdev) == 4)
+ 2.1.115 these are no longer supported. */
+ if (major (stp->st_rdev) == 4)
ptyno -= 128;
+#endif
if (ptyno / 16 >= strlen (__libc_ptyname1))
{
@@ -149,12 +147,12 @@ __ptsname_r (int fd, char *buf, size_t buflen)
p[2] = '\0';
}
- if (__xstat64 (_STAT_VER, buf, &st) < 0)
+ if (__xstat64 (_STAT_VER, buf, stp) < 0)
return errno;
/* Check if the name we're about to return really corresponds to a
slave pseudo terminal. */
- if (! S_ISCHR (st.st_mode) || ! SLAVE_P (st.st_rdev))
+ if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev))
{
/* This really is a configuration problem. */
__set_errno (ENOTTY);
@@ -164,4 +162,15 @@ __ptsname_r (int fd, char *buf, size_t buflen)
__set_errno (save_errno);
return 0;
}
+
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+ terminal associated with the master FD is open on in BUF.
+ Return 0 on success, otherwise an error number. */
+int
+__ptsname_r (int fd, char *buf, size_t buflen)
+{
+ struct stat64 st;
+ return __ptsname_internal (fd, buf, buflen, &st);
+}
weak_alias (__ptsname_r, ptsname_r)