From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from hall.aurel32.net (hall.aurel32.net [IPv6:2001:bc8:30d7:100::1]) by sourceware.org (Postfix) with ESMTPS id EA8853858C52 for ; Fri, 19 Aug 2022 13:25:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EA8853858C52 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=aurel32.net Authentication-Results: sourceware.org; spf=none smtp.mailfrom=aurel32.net DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=aurel32.net ; s=202004.hall; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date: Subject:Cc:To:From:Content-Type:From:Reply-To:Subject:Content-ID: Content-Description:In-Reply-To:References:X-Debbugs-Cc; bh=IJqAWUzZuspZzaPCOL//1pyEs7XLQGeccLyFc2wk2Ew=; b=zam8FOnIdW+tSZcENSGUKit0yA uJ+WWHORkl//B76ioc6HWuElA/yPnD5FlOzUlD9hTk2uXCoKN4YFKZ2VBdGyGXd1W2DCF9fufp3Ah lQ9KiWYC83ER4QdC28W1nyo5OAheUC+2Z+PJym1FCR70CxaVypH6ty/pe3wMT++qSJeeNiZ7A9LXy 8baoCvM2bFSGabv/HReXa+t26FhnD2QBJ7kpoc4S77cu6Rs0cqH9heGG+Kx2jjkOOU7nei18SaHmM zSlWlWOhYRwVNolQd8Pz5R9E+9qq6T+YTeUxVnwkzFAA4ido2uiaajpIzpTIdseHkMDorOGgv3UJq qCeKqh8Q==; Received: from [2a01:e0a:406:7381:3e0e:d27:becd:e47b] (helo=ohm.aurel32.net) by hall.aurel32.net with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1oP207-00BkU0-TG; Fri, 19 Aug 2022 15:25:28 +0200 Received: from aurel32 by ohm.aurel32.net with local (Exim 4.96) (envelope-from ) id 1oP1zz-000104-2H; Fri, 19 Aug 2022 15:25:19 +0200 From: Aurelien Jarno To: libc-stable@sourceware.org Cc: Aurelien Jarno , Adhemerval Zanella Subject: [COMMITTED 2.31] Linux: Require properly configured /dev/pts for PTYs Date: Fri, 19 Aug 2022 15:25:18 +0200 Message-Id: <20220819132518.3830-1-aurelien@aurel32.net> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-stable@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-stable mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Aug 2022 13:25:33 -0000 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. Reviewed-by: Adhemerval Zanella --- INSTALL | 11 +--- NEWS | 12 ++++ manual/install.texi | 11 +--- sysdeps/unix/sysv/linux/getpt.c | 67 +--------------------- sysdeps/unix/sysv/linux/grantpt.c | 73 ++++++++++++------------ sysdeps/unix/sysv/linux/ptsname.c | 95 ++----------------------------- 6 files changed, 61 insertions(+), 208 deletions(-) diff --git a/INSTALL b/INSTALL index 242cb06f91..b487e18634 100644 --- a/INSTALL +++ b/INSTALL @@ -184,14 +184,9 @@ if 'CFLAGS' is specified it must enable optimization. For example: '--enable-pt_chown' The file 'pt_chown' is a helper binary for 'grantpt' (*note Pseudo-Terminals: Allocation.) that is installed setuid root to fix - up pseudo-terminal ownership. It is not built by default because - systems using the Linux kernel are commonly built with the 'devpts' - filesystem enabled and mounted at '/dev/pts', which manages - pseudo-terminal ownership automatically. By using - '--enable-pt_chown', you may build 'pt_chown' and install it setuid - and owned by 'root'. The use of 'pt_chown' introduces additional - security risks to the system and you should enable it only if you - understand and accept those risks. + up pseudo-terminal ownership on GNU/Hurd. It is not required on + GNU/Linux, and the GNU C Library will not use the installed + 'pt_chown' program when configured with '--enable-pt_chown'. '--disable-werror' By default, the GNU C Library is built with '-Werror'. If you wish diff --git a/NEWS b/NEWS index de7bf22aa4..a3278be684 100644 --- a/NEWS +++ b/NEWS @@ -225,6 +225,18 @@ Changes to build and runtime requirements: source tree. ChangeLog files are located in the ChangeLog.old directory as ChangeLog.N where the highest N has the latest entries. +* 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-2019-19126: ld.so failed to ignore the LD_PREFER_MAP_32BIT_EXEC diff --git a/manual/install.texi b/manual/install.texi index 71bf47cac6..153ec99adc 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -214,14 +214,9 @@ increased program load times. @item --enable-pt_chown The file @file{pt_chown} is a helper binary for @code{grantpt} (@pxref{Allocation, Pseudo-Terminals}) that is installed setuid root to -fix up pseudo-terminal ownership. It is not built by default because -systems using the Linux kernel are commonly built with the @code{devpts} -filesystem enabled and mounted at @file{/dev/pts}, which manages -pseudo-terminal ownership automatically. By using -@samp{--enable-pt_chown}, you may build @file{pt_chown} and install it -setuid and owned by @code{root}. The use of @file{pt_chown} introduces -additional security risks to the system and you should enable it only if -you understand and accept those risks. +fix up pseudo-terminal ownership on GNU/Hurd. It is not required on +GNU/Linux, and @theglibc{} will not use the installed @file{pt_chown} +program when configured with @option{--enable-pt_chown}. @item --disable-werror By default, @theglibc{} is built with @option{-Werror}. If you wish 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 . */ -#include #include -#include #include #include -#include - -#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 +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 -#include -#include -#include -#include -#include -#include -#include +/* 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 , 1998. -#include + 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 + . */ + +#include +#include +#include +#include - __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 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 #include #include -#include -#include #include #include #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) -- 2.35.1