Message ID | cfe04259c4ce7addd48e9479ad6a620967681f34.1590574208.git.fweimer@redhat.com |
---|---|
State | New |
Headers | show |
Series | Linux: Rework Linux PTY support | expand |
On Wed, May 27, 2020 at 12:14:37PM +0200, Florian Weimer via Libc-alpha wrote: > Current systems do not have BSD terminals, so the fallback code in > posix_openpt/getpt does not do anything. Also remove the file system > check for /dev/pts. Current systems always have a devpts file system > mounted there if /dev/ptmx exists. Good change! In addition, on newer kernels you also have TIOCGPTPEER which wouldn't even require /dev/pts be present and permits race-free access to a /dev/pts/* device solely based on the /dev/ptmx fd. And we've made sure that glibc already supports that. So ack from me. Christian
On 27/05/2020 07:14, Florian Weimer via Libc-alpha wrote: > Current systems do not have BSD terminals, so the fallback code in > posix_openpt/getpt does not do anything. Also remove the file system > check for /dev/pts. Current systems always have a devpts file system > mounted there if /dev/ptmx exists. > > grantpt is now essentially a no-op. It only verifies that the > argument is a ptmx-descriptor. Therefore, this change indirectly > addresses bug 24941. LGTM with some comments below, thanks. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > NEWS | 12 ++++ > sysdeps/unix/sysv/linux/getpt.c | 67 +--------------------- > sysdeps/unix/sysv/linux/grantpt.c | 73 ++++++++++++------------ > sysdeps/unix/sysv/linux/ptsname.c | 95 ++----------------------------- > 4 files changed, 55 insertions(+), 192 deletions(-) > > diff --git a/NEWS b/NEWS > index 55389b8466..b8e0408a56 100644 > --- a/NEWS > +++ b/NEWS > @@ -52,6 +52,18 @@ Changes to build and runtime requirements: > * powerpc64le requires GCC 7.4 or newer. This is required for supporting > long double redirects. > > +* On Linux, the system administrator needs to configure /dev/pts with > + the intended access modes for pseudo-terminals. glibc no longer > + attemps to adjust permissions of terminal devices. The previous glibc > + defaults ("tty" group, user read/write and group write) already > + corresponded to what most systems used, so that grantpt did not > + perform any adjustments. > + > +* On Linux, the posix_openpt and getpt functions no longer attempt to > + use legacy (BSD) pseudo-terminals and assume that if /dev/ptmx exists > + (and pseudo-terminals are supported), a devpts file system is mounted > + on /dev/pts. Current systems already meet these requirements. > + > Security related changes: > > CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack Ok, although "Current systems" is somewhat vague (does it refer to minimum kernel version or a common practice?). > diff --git a/sysdeps/unix/sysv/linux/getpt.c b/sysdeps/unix/sysv/linux/getpt.c > index 1803b232c9..3cc745e11a 100644 > --- a/sysdeps/unix/sysv/linux/getpt.c > +++ b/sysdeps/unix/sysv/linux/getpt.c > @@ -16,69 +16,18 @@ > License along with the GNU C Library; if not, see > <https://www.gnu.org/licenses/>. */ > > -#include <errno.h> > #include <fcntl.h> > -#include <stdlib.h> > #include <unistd.h> > #include <paths.h> > -#include <sys/statfs.h> > - > -#include "linux_fsinfo.h" > > /* Path to the master pseudo terminal cloning device. */ > #define _PATH_DEVPTMX _PATH_DEV "ptmx" > -/* Directory containing the UNIX98 pseudo terminals. */ > -#define _PATH_DEVPTS _PATH_DEV "pts" > - > -/* Prototype for function that opens BSD-style master pseudo-terminals. */ > -extern int __bsd_getpt (void) attribute_hidden; > > /* Open a master pseudo terminal and return its file descriptor. */ > int > __posix_openpt (int oflag) > { > - static int have_no_dev_ptmx; > - int fd; > - > - if (!have_no_dev_ptmx) > - { > - fd = __open (_PATH_DEVPTMX, oflag); > - if (fd != -1) > - { > - struct statfs fsbuf; > - static int devpts_mounted; > - > - /* Check that the /dev/pts filesystem is mounted > - or if /dev is a devfs filesystem (this implies /dev/pts). */ > - if (devpts_mounted > - || (__statfs (_PATH_DEVPTS, &fsbuf) == 0 > - && fsbuf.f_type == DEVPTS_SUPER_MAGIC) > - || (__statfs (_PATH_DEV, &fsbuf) == 0 > - && fsbuf.f_type == DEVFS_SUPER_MAGIC)) > - { > - /* Everything is ok. */ > - devpts_mounted = 1; > - return fd; > - } > - > - /* If /dev/pts is not mounted then the UNIX98 pseudo terminals > - are not usable. */ > - __close (fd); > - have_no_dev_ptmx = 1; > - __set_errno (ENOENT); > - } > - else > - { > - if (errno == ENOENT || errno == ENODEV) > - have_no_dev_ptmx = 1; > - else > - return -1; > - } > - } > - else > - __set_errno (ENOENT); > - > - return -1; > + return __open (_PATH_DEVPTMX, oflag); > } > weak_alias (__posix_openpt, posix_openpt) > Ok. As side note I think we should change its prototype at include/stdlib.h from attribute_hidden to a proper hidden_def/hidden_proto. > @@ -86,16 +35,6 @@ weak_alias (__posix_openpt, posix_openpt) > int > __getpt (void) > { > - int fd = __posix_openpt (O_RDWR); > - if (fd == -1) > - fd = __bsd_getpt (); > - return fd; > + return __posix_openpt (O_RDWR); > } > - > - > -#define PTYNAME1 "pqrstuvwxyzabcde"; > -#define PTYNAME2 "0123456789abcdef"; > - > -#define __getpt __bsd_getpt > -#define HAVE_POSIX_OPENPT > -#include <sysdeps/unix/bsd/getpt.c> > +weak_alias (__getpt, getpt) Ok. > diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c > index 2030e07fa6..43122f9a76 100644 > --- a/sysdeps/unix/sysv/linux/grantpt.c > +++ b/sysdeps/unix/sysv/linux/grantpt.c > @@ -1,44 +1,41 @@ > -#include <assert.h> > -#include <ctype.h> > -#include <dirent.h> > -#include <errno.h> > -#include <fcntl.h> > -#include <paths.h> > -#include <stdlib.h> > -#include <unistd.h> > +/* grantpt implementation for Linux. > + Copyright (C) 1998-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. Should we keep copying the 'Contributed by' in this case? Specially for the case where the implementation is really a stripped down version? > > -#include <not-cancel.h> > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > > -#include "pty-private.h" > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > > -#if HAVE_PT_CHOWN > -/* 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_nocancel_nostatus (fd); > - } > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <errno.h> > +#include <stdlib.h> > +#include <sys/ioctl.h> > +#include <termios.h> > > - __closedir (dir); > +int > +grantpt (int fd) > +{ > + /* Without pt_chown on Linux, we have delegated the creation of the > + pty node with the right group and permission mode to the kernel, and > + non-root users are unlikely to be able to change it. Therefore let's > + consider that POSIX enforcement is the responsibility of the whole > + system and not only the GNU libc. */ > > - int nullfd = __open_nocancel (_PATH_DEVNULL, O_RDONLY); > - assert (nullfd == STDIN_FILENO); > - nullfd = __open_nocancel (_PATH_DEVNULL, O_WRONLY); > - assert (nullfd == STDOUT_FILENO); > - __dup2 (STDOUT_FILENO, STDERR_FILENO); > - } > + /* Verify that fd refers to a ptmx descriptor. */ > + unsigned int ptyno; > + int ret = __ioctl (fd, TIOCGPTN, &ptyno); > + if (ret != 0 && errno == ENOTTY) > + /* POSIX requires EINVAL instead of ENOTTY provided by the kernel. */ > + __set_errno (EINVAL); > + return ret; > } > -# define CLOSE_ALL_FDS() close_all_fds() > -#endif > - > -#include <sysdeps/unix/grantpt.c> Ok. > diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c > index 81d9d26f1e..3e9be3f0d4 100644 > --- a/sysdeps/unix/sysv/linux/ptsname.c > +++ b/sysdeps/unix/sysv/linux/ptsname.c > @@ -21,39 +21,14 @@ > #include <stdlib.h> > #include <string.h> > #include <sys/ioctl.h> > -#include <sys/stat.h> > -#include <sys/sysmacros.h> > #include <termios.h> > #include <unistd.h> > > #include <_itoa.h> > > -/* Check if DEV corresponds to a master pseudo terminal device. */ > -#define MASTER_P(Dev) \ > - (__gnu_dev_major ((Dev)) == 2 \ > - || (__gnu_dev_major ((Dev)) == 4 \ > - && __gnu_dev_minor ((Dev)) >= 128 && __gnu_dev_minor ((Dev)) < 192) \ > - || (__gnu_dev_major ((Dev)) >= 128 && __gnu_dev_major ((Dev)) < 136)) > - > -/* Check if DEV corresponds to a slave pseudo terminal device. */ > -#define SLAVE_P(Dev) \ > - (__gnu_dev_major ((Dev)) == 3 \ > - || (__gnu_dev_major ((Dev)) == 4 \ > - && __gnu_dev_minor ((Dev)) >= 192 && __gnu_dev_minor ((Dev)) < 256) \ > - || (__gnu_dev_major ((Dev)) >= 136 && __gnu_dev_major ((Dev)) < 144)) > - > -/* Note that major number 4 corresponds to the old BSD style pseudo > - terminal devices. As of Linux 2.1.115 these are no longer > - supported. They have been replaced by major numbers 2 (masters) > - and 3 (slaves). */ > - > /* Directory where we can find the slave pty nodes. */ > #define _PATH_DEVPTS "/dev/pts/" > > -/* The are declared in getpt.c. */ > -extern const char __libc_ptyname1[] attribute_hidden; > -extern const char __libc_ptyname2[] attribute_hidden; > - > /* Static buffer for `ptsname'. */ > static char buffer[sizeof (_PATH_DEVPTS) + 20]; > > @@ -68,19 +43,15 @@ ptsname (int fd) > } > Ok. > > +/* 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_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) > +__ptsname_r (int fd, char *buf, size_t buflen) > { > int save_errno = errno; > unsigned int ptyno; > > - if (!__isatty (fd)) > - { > - __set_errno (ENOTTY); > - return ENOTTY; > - } > - > -#ifdef TIOCGPTN > if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) > { > /* Buffer we use to print the number in. For a maximum size for > @@ -101,67 +72,11 @@ __ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) > > memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p); > } > - else if (errno != EINVAL) > - return errno; > else > -#endif > - { > - char *p; > - > - if (buflen < strlen (_PATH_TTY) + 3) > - { > - __set_errno (ERANGE); > - return ERANGE; > - } > - > - if (__fxstat64 (_STAT_VER, fd, stp) < 0) > - return errno; > - > - /* Check if FD really is a master pseudo terminal. */ > - if (! MASTER_P (stp->st_rdev)) > - { > - __set_errno (ENOTTY); > - return ENOTTY; > - } > - > - ptyno = __gnu_dev_minor (stp->st_rdev); > - > - if (ptyno / 16 >= strlen (__libc_ptyname1)) > - { > - __set_errno (ENOTTY); > - return ENOTTY; > - } > - > - p = __stpcpy (buf, _PATH_TTY); > - p[0] = __libc_ptyname1[ptyno / 16]; > - p[1] = __libc_ptyname2[ptyno % 16]; > - p[2] = '\0'; > - } > - > - if (__xstat64 (_STAT_VER, buf, stp) < 0) > + /* Bad file descriptor, or not a ptmx descriptor. */ > return errno; > > - /* Check if the name we're about to return really corresponds to a > - slave pseudo terminal. */ > - if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev)) > - { > - /* This really is a configuration problem. */ > - __set_errno (ENOTTY); > - return ENOTTY; > - } > - > __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) > Ok.
* Adhemerval Zanella: >> diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c >> index 2030e07fa6..43122f9a76 100644 >> --- a/sysdeps/unix/sysv/linux/grantpt.c >> +++ b/sysdeps/unix/sysv/linux/grantpt.c >> @@ -1,44 +1,41 @@ >> -#include <assert.h> >> -#include <ctype.h> >> -#include <dirent.h> >> -#include <errno.h> >> -#include <fcntl.h> >> -#include <paths.h> >> -#include <stdlib.h> >> -#include <unistd.h> >> +/* grantpt implementation for Linux. >> + Copyright (C) 1998-2020 Free Software Foundation, Inc. >> + This file is part of the GNU C Library. >> + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. > > Should we keep copying the 'Contributed by' in this case? Specially > for the case where the implementation is really a stripped down > version? Zack, is it okay if I remove the “Contributed by” line, as Adhemerval suggests? Full patch is here: <https://sourceware.org/pipermail/libc-alpha/2020-May/114379.html> Thanks, Florian
* Adhemerval Zanella via Libc-alpha: >> +* On Linux, the system administrator needs to configure /dev/pts with >> + the intended access modes for pseudo-terminals. glibc no longer >> + attemps to adjust permissions of terminal devices. The previous glibc >> + defaults ("tty" group, user read/write and group write) already >> + corresponded to what most systems used, so that grantpt did not >> + perform any adjustments. >> + >> +* On Linux, the posix_openpt and getpt functions no longer attempt to >> + use legacy (BSD) pseudo-terminals and assume that if /dev/ptmx exists >> + (and pseudo-terminals are supported), a devpts file system is mounted >> + on /dev/pts. Current systems already meet these requirements. >> + >> Security related changes: >> >> CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack > > Ok, although "Current systems" is somewhat vague (does it refer to minimum > kernel version or a common practice?). Common practice (and the missing pt_chown binary). > Ok. As side note I think we should change its prototype at include/stdlib.h > from attribute_hidden to a proper hidden_def/hidden_proto. There's a stub implementation of posix_openpt for Hurd, so I think this should be a separate patch. I'm going to push this with an INSTALL update after some further testing. Thanks, Florian
diff --git a/NEWS b/NEWS index 55389b8466..b8e0408a56 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,18 @@ Changes to build and runtime requirements: * powerpc64le requires GCC 7.4 or newer. This is required for supporting long double redirects. +* On Linux, the system administrator needs to configure /dev/pts with + the intended access modes for pseudo-terminals. glibc no longer + attemps to adjust permissions of terminal devices. The previous glibc + defaults ("tty" group, user read/write and group write) already + corresponded to what most systems used, so that grantpt did not + perform any adjustments. + +* On Linux, the posix_openpt and getpt functions no longer attempt to + use legacy (BSD) pseudo-terminals and assume that if /dev/ptmx exists + (and pseudo-terminals are supported), a devpts file system is mounted + on /dev/pts. Current systems already meet these requirements. + Security related changes: CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack diff --git a/sysdeps/unix/sysv/linux/getpt.c b/sysdeps/unix/sysv/linux/getpt.c index 1803b232c9..3cc745e11a 100644 --- a/sysdeps/unix/sysv/linux/getpt.c +++ b/sysdeps/unix/sysv/linux/getpt.c @@ -16,69 +16,18 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#include <errno.h> #include <fcntl.h> -#include <stdlib.h> #include <unistd.h> #include <paths.h> -#include <sys/statfs.h> - -#include "linux_fsinfo.h" /* Path to the master pseudo terminal cloning device. */ #define _PATH_DEVPTMX _PATH_DEV "ptmx" -/* Directory containing the UNIX98 pseudo terminals. */ -#define _PATH_DEVPTS _PATH_DEV "pts" - -/* Prototype for function that opens BSD-style master pseudo-terminals. */ -extern int __bsd_getpt (void) attribute_hidden; /* Open a master pseudo terminal and return its file descriptor. */ int __posix_openpt (int oflag) { - static int have_no_dev_ptmx; - int fd; - - if (!have_no_dev_ptmx) - { - fd = __open (_PATH_DEVPTMX, oflag); - if (fd != -1) - { - struct statfs fsbuf; - static int devpts_mounted; - - /* Check that the /dev/pts filesystem is mounted - or if /dev is a devfs filesystem (this implies /dev/pts). */ - if (devpts_mounted - || (__statfs (_PATH_DEVPTS, &fsbuf) == 0 - && fsbuf.f_type == DEVPTS_SUPER_MAGIC) - || (__statfs (_PATH_DEV, &fsbuf) == 0 - && fsbuf.f_type == DEVFS_SUPER_MAGIC)) - { - /* Everything is ok. */ - devpts_mounted = 1; - return fd; - } - - /* If /dev/pts is not mounted then the UNIX98 pseudo terminals - are not usable. */ - __close (fd); - have_no_dev_ptmx = 1; - __set_errno (ENOENT); - } - else - { - if (errno == ENOENT || errno == ENODEV) - have_no_dev_ptmx = 1; - else - return -1; - } - } - else - __set_errno (ENOENT); - - return -1; + return __open (_PATH_DEVPTMX, oflag); } weak_alias (__posix_openpt, posix_openpt) @@ -86,16 +35,6 @@ weak_alias (__posix_openpt, posix_openpt) int __getpt (void) { - int fd = __posix_openpt (O_RDWR); - if (fd == -1) - fd = __bsd_getpt (); - return fd; + return __posix_openpt (O_RDWR); } - - -#define PTYNAME1 "pqrstuvwxyzabcde"; -#define PTYNAME2 "0123456789abcdef"; - -#define __getpt __bsd_getpt -#define HAVE_POSIX_OPENPT -#include <sysdeps/unix/bsd/getpt.c> +weak_alias (__getpt, getpt) diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c index 2030e07fa6..43122f9a76 100644 --- a/sysdeps/unix/sysv/linux/grantpt.c +++ b/sysdeps/unix/sysv/linux/grantpt.c @@ -1,44 +1,41 @@ -#include <assert.h> -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <paths.h> -#include <stdlib.h> -#include <unistd.h> +/* grantpt implementation for Linux. + Copyright (C) 1998-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. -#include <not-cancel.h> + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. -#include "pty-private.h" + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. -#if HAVE_PT_CHOWN -/* 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_nocancel_nostatus (fd); - } + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <termios.h> - __closedir (dir); +int +grantpt (int fd) +{ + /* Without pt_chown on Linux, we have delegated the creation of the + pty node with the right group and permission mode to the kernel, and + non-root users are unlikely to be able to change it. Therefore let's + consider that POSIX enforcement is the responsibility of the whole + system and not only the GNU libc. */ - int nullfd = __open_nocancel (_PATH_DEVNULL, O_RDONLY); - assert (nullfd == STDIN_FILENO); - nullfd = __open_nocancel (_PATH_DEVNULL, O_WRONLY); - assert (nullfd == STDOUT_FILENO); - __dup2 (STDOUT_FILENO, STDERR_FILENO); - } + /* Verify that fd refers to a ptmx descriptor. */ + unsigned int ptyno; + int ret = __ioctl (fd, TIOCGPTN, &ptyno); + if (ret != 0 && errno == ENOTTY) + /* POSIX requires EINVAL instead of ENOTTY provided by the kernel. */ + __set_errno (EINVAL); + return ret; } -# define CLOSE_ALL_FDS() close_all_fds() -#endif - -#include <sysdeps/unix/grantpt.c> diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c index 81d9d26f1e..3e9be3f0d4 100644 --- a/sysdeps/unix/sysv/linux/ptsname.c +++ b/sysdeps/unix/sysv/linux/ptsname.c @@ -21,39 +21,14 @@ #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> #include <termios.h> #include <unistd.h> #include <_itoa.h> -/* Check if DEV corresponds to a master pseudo terminal device. */ -#define MASTER_P(Dev) \ - (__gnu_dev_major ((Dev)) == 2 \ - || (__gnu_dev_major ((Dev)) == 4 \ - && __gnu_dev_minor ((Dev)) >= 128 && __gnu_dev_minor ((Dev)) < 192) \ - || (__gnu_dev_major ((Dev)) >= 128 && __gnu_dev_major ((Dev)) < 136)) - -/* Check if DEV corresponds to a slave pseudo terminal device. */ -#define SLAVE_P(Dev) \ - (__gnu_dev_major ((Dev)) == 3 \ - || (__gnu_dev_major ((Dev)) == 4 \ - && __gnu_dev_minor ((Dev)) >= 192 && __gnu_dev_minor ((Dev)) < 256) \ - || (__gnu_dev_major ((Dev)) >= 136 && __gnu_dev_major ((Dev)) < 144)) - -/* Note that major number 4 corresponds to the old BSD style pseudo - terminal devices. As of Linux 2.1.115 these are no longer - supported. They have been replaced by major numbers 2 (masters) - and 3 (slaves). */ - /* Directory where we can find the slave pty nodes. */ #define _PATH_DEVPTS "/dev/pts/" -/* The are declared in getpt.c. */ -extern const char __libc_ptyname1[] attribute_hidden; -extern const char __libc_ptyname2[] attribute_hidden; - /* Static buffer for `ptsname'. */ static char buffer[sizeof (_PATH_DEVPTS) + 20]; @@ -68,19 +43,15 @@ 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_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) +__ptsname_r (int fd, char *buf, size_t buflen) { int save_errno = errno; unsigned int ptyno; - if (!__isatty (fd)) - { - __set_errno (ENOTTY); - return ENOTTY; - } - -#ifdef TIOCGPTN if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { /* Buffer we use to print the number in. For a maximum size for @@ -101,67 +72,11 @@ __ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) memcpy (__stpcpy (buf, devpts), p, &numbuf[sizeof (numbuf)] - p); } - else if (errno != EINVAL) - return errno; else -#endif - { - char *p; - - if (buflen < strlen (_PATH_TTY) + 3) - { - __set_errno (ERANGE); - return ERANGE; - } - - if (__fxstat64 (_STAT_VER, fd, stp) < 0) - return errno; - - /* Check if FD really is a master pseudo terminal. */ - if (! MASTER_P (stp->st_rdev)) - { - __set_errno (ENOTTY); - return ENOTTY; - } - - ptyno = __gnu_dev_minor (stp->st_rdev); - - if (ptyno / 16 >= strlen (__libc_ptyname1)) - { - __set_errno (ENOTTY); - return ENOTTY; - } - - p = __stpcpy (buf, _PATH_TTY); - p[0] = __libc_ptyname1[ptyno / 16]; - p[1] = __libc_ptyname2[ptyno % 16]; - p[2] = '\0'; - } - - if (__xstat64 (_STAT_VER, buf, stp) < 0) + /* Bad file descriptor, or not a ptmx descriptor. */ return errno; - /* Check if the name we're about to return really corresponds to a - slave pseudo terminal. */ - if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev)) - { - /* This really is a configuration problem. */ - __set_errno (ENOTTY); - return ENOTTY; - } - __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)