diff mbox series

login: Remove the pt_chown program

Message ID 87sgy4h7ap.fsf@oldenburg2.str.redhat.com
State New
Headers show
Series login: Remove the pt_chown program | expand

Commit Message

Florian Weimer Jan. 7, 2019, 2:27 p.m. UTC
The program is not safe to install in a container environment.
It was last installed by default in glibc 2.17.

(This is probably something for 2.30 at this point.)

2019-01-07  Florian Weimer  <fweimer@redhat.com>

	login: Remove the pt_chown program.
	* configure.ac (--enable-pt_chown): Remove option.
	* login/Makefile (others, others-pie, install-others-programs): Do
	not add pt_chown.
	(pt_chown-cflags, libcap, CFLAGS-pt_chown.c, LDLIBS-pt_chown)
	(LDFLAGS-pt_chown): Remove variables.
	(pt_chown): Remove target.
	* sysdeps/unix/grantpt.c (grantpt): Remove code to call the helper
	program.
	* manual/install.texi (Configuring and compiling): Remove
	description of --enable-pt_chown.
	(Running make install): Remove description of pt_chown.
	* manual/terminal.texi (Allocation): Update comment.
	* sysdeps/generic/pty-private.h (_PATH_PT_CHOWN): Remove.
	* login/programs/pt_chown.c: Remove file.
	* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
	* configure, INSTALL: Regenerate.

Comments

Florian Weimer Jan. 7, 2019, 3:10 p.m. UTC | #1
* Florian Weimer:

> The program is not safe to install in a container environment.
> It was last installed by default in glibc 2.17.
>
> (This is probably something for 2.30 at this point.)

Hmph.  I forgot to update config.make.in and config.h.in.

2019-01-07  Florian Weimer  <fweimer@redhat.com>

	login: Remove the pt_chown program.
	* configure.ac (--enable-pt_chown): Remove option.
	* config.h.in: Remove HAVE_PT_CHOWN.
	* config.make.in (build-pt-chown): Remove variable.
	* login/Makefile (others, others-pie, install-others-programs): Do
	not add pt_chown.
	(pt_chown-cflags, libcap, CFLAGS-pt_chown.c, LDLIBS-pt_chown)
	(LDFLAGS-pt_chown): Remove variables.
	(pt_chown): Remove target.
	* sysdeps/unix/grantpt.c (grantpt): Remove code to call the helper
	program.
	* manual/install.texi (Configuring and compiling): Remove
	description of --enable-pt_chown.
	(Running make install): Remove description of pt_chown.
	* manual/terminal.texi (Allocation): Update comment.
	* sysdeps/generic/pty-private.h (_PATH_PT_CHOWN): Remove.
	* login/programs/pt_chown.c: Remove file.
	* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
	* configure, INSTALL: Regenerate.

diff --git a/INSTALL b/INSTALL
index 672eb40640..c47d510748 100644
--- a/INSTALL
+++ b/INSTALL
@@ -181,18 +181,6 @@ if 'CFLAGS' is specified it must enable optimization.  For example:
      read-only global offset table (GOT), at the cost of slightly
      increased program load times.
 
-'--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.
-
 '--disable-werror'
      By default, the GNU C Library is built with '-Werror'.  If you wish
      to build without this option (for example, if building with a newer
@@ -404,13 +392,6 @@ may not want to run.  'nscd' caches name service lookups; it can
 dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-   One auxiliary program, '/usr/libexec/pt_chown', is installed setuid
-'root' if the '--enable-pt_chown' configuration option is used.  This
-program is invoked by the 'grantpt' function; it sets the permissions on
-a pseudoterminal so it can be used by the calling process.  If you are
-using a Linux kernel with the 'devpts' filesystem enabled and mounted at
-'/dev/pts', you don't need this program.
-
    After installation you should configure the timezone and install
 locales for your system.  The time zone configuration ensures that your
 system time matches the time for your current timezone.  The locales
diff --git a/NEWS b/NEWS
index cc20102fda..58f2c12cb8 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,10 @@ Deprecated and removed features, and other changes affecting compatibility:
   as all functions that call vscanf, vfscanf, or vsscanf are annotated with
   __attribute__ ((format (scanf, ...))).
 
+* The pt_chown program has been removed.  (It has not been installed by
+  default since glibc 2.18.)  Changing ownership of PTYs cannot be made safe
+  in userspace in a container environment.
+
 Changes to build and runtime requirements:
 
 * Python 3.4 or later is required to build the GNU C Library.
diff --git a/config.h.in b/config.h.in
index f059ec0435..43fc7a9041 100644
--- a/config.h.in
+++ b/config.h.in
@@ -229,9 +229,6 @@
 /* The ARM movw/movt instructions using PC-relative relocs work right.  */
 #define ARM_PCREL_MOVW_OK 0
 
-/* The pt_chown binary is being built and used by grantpt.  */
-#define HAVE_PT_CHOWN 0
-
 /* Define if the compiler supports __builtin_trap without
    any external dependencies such as making a function call.  */
 #define HAVE_BUILTIN_TRAP 0
diff --git a/config.make.in b/config.make.in
index f46bfc29bb..2506e317d1 100644
--- a/config.make.in
+++ b/config.make.in
@@ -101,7 +101,6 @@ build-crypt = @build_crypt@
 build-nscd = @build_nscd@
 use-nscd = @use_nscd@
 build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
-build-pt-chown = @build_pt_chown@
 have-tunables = @have_tunables@
 
 # Build tools.
diff --git a/configure b/configure
index 101dfddf37..c5afaef4b2 100755
--- a/configure
+++ b/configure
@@ -671,7 +671,6 @@ libc_cv_ssp
 libc_cv_with_fp
 base_machine
 have_tunables
-build_pt_chown
 build_nscd
 build_obsolete_nsl
 link_obsolete_rpc
@@ -790,7 +789,6 @@ enable_obsolete_nsl
 enable_systemtap
 enable_build_nscd
 enable_nscd
-enable_pt_chown
 enable_tunables
 enable_mathvec
 enable_cet
@@ -1464,7 +1462,6 @@ Optional Features:
   --enable-systemtap      enable systemtap static probe points [default=no]
   --disable-build-nscd    disable building and installing the nscd daemon
   --disable-nscd          library functions will not contact the nscd daemon
-  --enable-pt_chown       Enable building and installing pt_chown
   --enable-tunables       Enable tunables support. Known values are 'yes',
                           'no' and 'valstring'
   --enable-mathvec        Enable building and installing mathvec [default
@@ -3731,19 +3728,6 @@ else
 fi
 
 
-# Check whether --enable-pt_chown was given.
-if test "${enable_pt_chown+set}" = set; then :
-  enableval=$enable_pt_chown; build_pt_chown=$enableval
-else
-  build_pt_chown=no
-fi
-
-
-if test "$build_pt_chown" = yes; then
-  $as_echo "#define HAVE_PT_CHOWN 1" >>confdefs.h
-
-fi
-
 # Check whether --enable-tunables was given.
 if test "${enable_tunables+set}" = set; then :
   enableval=$enable_tunables; have_tunables=$enableval
diff --git a/configure.ac b/configure.ac
index 46a74687a6..5369fae7b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,16 +434,6 @@ AC_ARG_ENABLE([nscd],
 	      [use_nscd=$enableval],
 	      [use_nscd=yes])
 
-AC_ARG_ENABLE([pt_chown],
-	      [AS_HELP_STRING([--enable-pt_chown],
-	       [Enable building and installing pt_chown])],
-	      [build_pt_chown=$enableval],
-	      [build_pt_chown=no])
-AC_SUBST(build_pt_chown)
-if test "$build_pt_chown" = yes; then
-  AC_DEFINE(HAVE_PT_CHOWN)
-fi
-
 AC_ARG_ENABLE([tunables],
 	      [AS_HELP_STRING([--enable-tunables],
 	       [Enable tunables support. Known values are 'yes', 'no' and 'valstring'])],
diff --git a/login/Makefile b/login/Makefile
index 92535f0aec..5c78b491f3 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -34,12 +34,6 @@ CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
 
 others = utmpdump
 
-ifeq (yes,$(build-pt-chown))
-others += pt_chown
-others-pie = pt_chown
-install-others-programs = $(inst_libexecdir)/pt_chown
-endif
-
 subdir-dirs = programs
 vpath %.c programs
 
@@ -54,20 +48,3 @@ libutil-routines:= login login_tty logout logwtmp openpty forkpty
 include ../Rules
 
 CFLAGS-getpt.c += -fexceptions
-
-ifeq (yesyes,$(have-fpie)$(build-shared))
-pt_chown-cflags += $(pie-ccflag)
-endif
-ifeq (yes,$(have-libcap))
-libcap = -lcap
-endif
-CFLAGS-pt_chown.c += $(pt_chown-cflags)
-LDLIBS-pt_chown = $(libcap)
-ifeq (yesyes,$(have-fpie)$(build-shared))
-LDFLAGS-pt_chown = -Wl,-z,now
-endif
-
-# pt_chown needs to be setuid root.
-$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
-	$(make-target-directory)
-	-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
deleted file mode 100644
index d44e4bf6ed..0000000000
--- a/login/programs/pt_chown.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* pt_chmod - helper program for `grantpt'.
-   Copyright (C) 1998-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
-
-   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.
-
-   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.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <argp.h>
-#include <errno.h>
-#include <error.h>
-#include <grp.h>
-#include <libintl.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_LIBCAP
-# include <sys/capability.h>
-# include <sys/prctl.h>
-#endif
-
-#include "pty-private.h"
-
-/* Get libc version number.  */
-#include "../version.h"
-
-#define PACKAGE _libc_intl_domainname
-
-/* Name and version of program.  */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-/* Function to print some extra text in the help message.  */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions.  */
-static struct argp argp =
-{
-  NULL, NULL, NULL, NULL, NULL, more_help
-};
-
-
-/* Print the version information.  */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
-  fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION);
-  fprintf (stream, gettext ("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2019");
-}
-
-static char *
-more_help (int key, const char *text, void *input)
-{
-  char *cp;
-  char *tp;
-
-  switch (key)
-    {
-    case ARGP_KEY_HELP_PRE_DOC:
-      asprintf (&cp, gettext ("\
-Set the owner, group and access permission of the slave pseudo\
- terminal corresponding to the master pseudo terminal passed on\
- file descriptor `%d'.  This is the helper program for the\
- `grantpt' function.  It is not intended to be run directly from\
- the command line.\n"),
-		PTY_FILENO);
-      return cp;
-    case ARGP_KEY_HELP_EXTRA:
-      /* We print some extra information.  */
-      if (asprintf (&tp, gettext ("\
-For bug reporting instructions, please see:\n\
-%s.\n"), REPORT_BUGS_TO) < 0)
-	return NULL;
-      if (asprintf (&cp, gettext ("\
-The owner is set to the current user, the group is set to `%s',\
- and the access permission is set to `%o'.\n\n\
-%s"),
-		    TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, tp) < 0)
-	{
-	  free (tp);
-	  return NULL;
-	}
-      return cp;
-    default:
-      break;
-    }
-  return (char *) text;
-}
-
-static int
-do_pt_chown (void)
-{
-  char *pty;
-  struct stat64 st;
-  struct group *p;
-  gid_t gid;
-
-  /* Check that PTY_FILENO is a valid master pseudo terminal.  */
-  pty = ptsname (PTY_FILENO);
-  if (pty == NULL)
-    return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
-
-  /* Check that the returned slave pseudo terminal is a
-     character device.  */
-  if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode))
-    return FAIL_EINVAL;
-
-  /* Get the group ID of the special `tty' group.  */
-  p = getgrnam (TTY_GROUP);
-  gid = p ? p->gr_gid : getgid ();
-
-  /* Set the owner to the real user ID, and the group to that special
-     group ID.  */
-  if (chown (pty, getuid (), gid) < 0)
-    return FAIL_EACCES;
-
-  /* Set the permission mode to readable and writable by the owner,
-     and writable by the group.  */
-  if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)
-      && chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
-    return FAIL_EACCES;
-
-  return 0;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  uid_t euid = geteuid ();
-  uid_t uid = getuid ();
-  int remaining;
-  sigset_t signalset;
-
-  /* Clear any signal mask from the parent process.  */
-  sigemptyset (&signalset);
-  sigprocmask (SIG_SETMASK, &signalset, NULL);
-
-  if (argc == 1 && euid == 0)
-    {
-#ifdef HAVE_LIBCAP
-  /* Drop privileges.  */
-      if (uid != euid)
-	{
-	  static const cap_value_t cap_list[] =
-	    { CAP_CHOWN, CAP_FOWNER	};
-# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
-	  cap_t caps = cap_init ();
-	  if (caps == NULL)
-	    return FAIL_ENOMEM;
-
-	  /* 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_EFFECTIVE, ncap_list, cap_list, CAP_SET);
-
-	  int res = cap_set_proc (caps);
-
-	  cap_free (caps);
-
-	  if (__glibc_unlikely (res != 0))
-	    return FAIL_EXEC;
-	}
-#endif
-
-      /* Normal invocation of this program is with no arguments and
-	 with privileges.  */
-      return do_pt_chown ();
-    }
-
-  /* We aren't going to be using privileges, so drop them right now. */
-  setuid (uid);
-
-  /* Set locale via LC_ALL.  */
-  setlocale (LC_ALL, "");
-
-  /* Set the text message domain.  */
-  textdomain (PACKAGE);
-
-  /* parse and process arguments.  */
-  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
-  if (remaining < argc)
-    {
-      /* We should not be called with any non-option parameters.  */
-      error (0, 0, gettext ("too many arguments"));
-      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
-		 program_invocation_short_name);
-      return EXIT_FAILURE;
-    }
-
-  /* Check if we are properly installed.  */
-  if (euid != 0)
-    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
-
-  return EXIT_SUCCESS;
-}
diff --git a/manual/install.texi b/manual/install.texi
index 2a87a2725a..49fcc7ac95 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -209,20 +209,6 @@ additional security hardening because it enables full RELRO and a
 read-only global offset table (GOT), at the cost of slightly increased
 program load times.
 
-@pindex pt_chown
-@findex grantpt
-@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.
-
 @item --disable-werror
 By default, @theglibc{} is built with @option{-Werror}.  If you wish
 to build without this option (for example, if building with a newer
@@ -442,13 +428,6 @@ may or may not want to run.  @code{nscd} caches name service lookups; it
 can dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-One auxiliary program, @file{/usr/libexec/pt_chown}, is installed setuid
-@code{root} if the @samp{--enable-pt_chown} configuration option is used.
-This program is invoked by the @code{grantpt} function; it sets the
-permissions on a pseudoterminal so it can be used by the calling process.
-If you are using a Linux kernel with the @code{devpts} filesystem enabled
-and mounted at @file{/dev/pts}, you don't need this program.
-
 After installation you should configure the timezone and install locales
 for your system.  The time zone configuration ensures that your system
 time matches the time for your current timezone.  The locales ensure that
diff --git a/manual/terminal.texi b/manual/terminal.texi
index d830baacd7..7bb974e018 100644
--- a/manual/terminal.texi
+++ b/manual/terminal.texi
@@ -1989,16 +1989,6 @@ This function is a GNU extension.
 @c  getgrnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem
 @c  getgid dup ok
 @c  chmod dup ok
-@c  fork dup @aculock
-@c  [child]
-@c   setrlimit
-@c   dup2
-@c   CLOSE_ALL_FDS
-@c   execle
-@c   _exit
-@c  waitpid dup ok
-@c  WIFEXITED dup ok
-@c  WEXITSTATUS dup ok
 @c  free dup @ascuheap @acsmem
 The @code{grantpt} function changes the ownership and access permission
 of the slave pseudo-terminal device corresponding to the master
diff --git a/sysdeps/generic/pty-private.h b/sysdeps/generic/pty-private.h
index 1315c01af9..7470ca0c6a 100644
--- a/sysdeps/generic/pty-private.h
+++ b/sysdeps/generic/pty-private.h
@@ -26,9 +26,6 @@
 /* The file descriptor connected to the master pseudo terminal.  */
 #define PTY_FILENO 3
 
-/* Path to the helper program that implements `grantpt' in user space.  */
-#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
-
 /* Test whether given TTY is really a Unix98 pseudo terminal.  */
 /* #define unix98_pseudo_p(Dev) ... */
 
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index e2e6df14c9..7143f54605 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -99,7 +99,6 @@ pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp)
 int
 grantpt (int fd)
 {
-  int retval = -1;
 #ifdef PATH_MAX
   char _buf[PATH_MAX];
 #else
@@ -132,7 +131,7 @@ grantpt (int fd)
   if (st.st_uid != uid)
     {
       if (__chown (buf, uid, st.st_gid) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   static int tty_gid = -1;
@@ -155,103 +154,21 @@ grantpt (int fd)
     }
   gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;
 
-#if HAVE_PT_CHOWN
-  /* Make sure the group of the device is that special group.  */
-  if (st.st_gid != gid)
-    {
-      if (__chown (buf, uid, gid) < 0)
-	goto helper;
-    }
-
-  /* Make sure the permission mode is set to readable and writable by
-     the owner, and writable by the group.  */
-  mode_t mode = S_IRUSR|S_IWUSR|S_IWGRP;
-#else
-  /* When built without pt_chown, 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. Thus accept different group or
-     permission mode.  */
-
   /* Make sure the permission is set to readable and writable by the
      owner.  For security reasons, make it writable by the group only
      when originally writable and when the group of the device is that
      special group.  */
   mode_t mode = S_IRUSR|S_IWUSR|
 	        ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0);
-#endif
 
+  int retval = 0;
   if ((st.st_mode & ACCESSPERMS) != mode)
     {
       if (__chmod (buf, mode) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   retval = 0;
-  goto cleanup;
-
-  /* We have to use the helper program if it is available.  */
- helper:;
-
-#if HAVE_PT_CHOWN
-  pid_t pid = __fork ();
-  if (pid == -1)
-    goto cleanup;
-  else if (pid == 0)
-    {
-      /* Disable core dumps.  */
-      struct rlimit rl = { 0, 0 };
-      __setrlimit (RLIMIT_CORE, &rl);
-
-      /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
-      if (fd != PTY_FILENO)
-	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);
-    }
-  else
-    {
-      int w;
-
-      if (__waitpid (pid, &w, 0) == -1)
-	goto cleanup;
-      if (!WIFEXITED (w))
-	__set_errno (ENOEXEC);
-      else
-	switch (WEXITSTATUS (w))
-	  {
-	  case 0:
-	    retval = 0;
-	    break;
-	  case FAIL_EBADF:
-	    __set_errno (EBADF);
-	    break;
-	  case FAIL_EINVAL:
-	    __set_errno (EINVAL);
-	    break;
-	  case FAIL_EACCES:
-	    __set_errno (EACCES);
-	    break;
-	  case FAIL_EXEC:
-	    __set_errno (ENOEXEC);
-	    break;
-	  case FAIL_ENOMEM:
-	    __set_errno (ENOMEM);
-	    break;
-
-	  default:
-	    assert(! "grantpt: internal error: invalid exit code from pt_chown");
-	  }
-    }
-#endif
-
  cleanup:
   if (buf != _buf)
     free (buf);
diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
deleted file mode 100644
index 2030e07fa6..0000000000
--- a/sysdeps/unix/sysv/linux/grantpt.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#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"
-
-#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);
-	  }
-
-      __closedir (dir);
-
-      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);
-    }
-}
-# define CLOSE_ALL_FDS() close_all_fds()
-#endif
-
-#include <sysdeps/unix/grantpt.c>
Carlos O'Donell Jan. 7, 2019, 7:40 p.m. UTC | #2
On 1/7/19 10:10 AM, Florian Weimer wrote:
> * Florian Weimer:
> 
>> The program is not safe to install in a container environment.
>> It was last installed by default in glibc 2.17.
>>
>> (This is probably something for 2.30 at this point.)

OK for 2.30 if you fixup the retval issue.

I agree that it's time we removed the ability to use pt_chown, this has
to always be handled by the kernel.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
 
> Hmph.  I forgot to update config.make.in and config.h.in.
> 
> 2019-01-07  Florian Weimer  <fweimer@redhat.com>
> 
> 	login: Remove the pt_chown program.
> 	* configure.ac (--enable-pt_chown): Remove option.
> 	* config.h.in: Remove HAVE_PT_CHOWN.
> 	* config.make.in (build-pt-chown): Remove variable.
> 	* login/Makefile (others, others-pie, install-others-programs): Do
> 	not add pt_chown.
> 	(pt_chown-cflags, libcap, CFLAGS-pt_chown.c, LDLIBS-pt_chown)
> 	(LDFLAGS-pt_chown): Remove variables.
> 	(pt_chown): Remove target.
> 	* sysdeps/unix/grantpt.c (grantpt): Remove code to call the helper
> 	program.
> 	* manual/install.texi (Configuring and compiling): Remove
> 	description of --enable-pt_chown.
> 	(Running make install): Remove description of pt_chown.
> 	* manual/terminal.texi (Allocation): Update comment.
> 	* sysdeps/generic/pty-private.h (_PATH_PT_CHOWN): Remove.
> 	* login/programs/pt_chown.c: Remove file.
> 	* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
> 	* configure, INSTALL: Regenerate.
> 
> diff --git a/NEWS b/NEWS
> index cc20102fda..58f2c12cb8 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -85,6 +85,10 @@ Deprecated and removed features, and other changes affecting compatibility:
>    as all functions that call vscanf, vfscanf, or vsscanf are annotated with
>    __attribute__ ((format (scanf, ...))).
>  
> +* The pt_chown program has been removed.  (It has not been installed by
> +  default since glibc 2.18.)  Changing ownership of PTYs cannot be made safe
> +  in userspace in a container environment.
> +

OK.

>  Changes to build and runtime requirements:
>  
>  * Python 3.4 or later is required to build the GNU C Library.
> diff --git a/config.h.in b/config.h.in
> index f059ec0435..43fc7a9041 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -229,9 +229,6 @@
>  /* The ARM movw/movt instructions using PC-relative relocs work right.  */
>  #define ARM_PCREL_MOVW_OK 0
>  
> -/* The pt_chown binary is being built and used by grantpt.  */
> -#define HAVE_PT_CHOWN 0
> -

OK.

>  /* Define if the compiler supports __builtin_trap without
>     any external dependencies such as making a function call.  */
>  #define HAVE_BUILTIN_TRAP 0
> diff --git a/config.make.in b/config.make.in
> index f46bfc29bb..2506e317d1 100644
> --- a/config.make.in
> +++ b/config.make.in
> @@ -101,7 +101,6 @@ build-crypt = @build_crypt@
>  build-nscd = @build_nscd@
>  use-nscd = @use_nscd@
>  build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
> -build-pt-chown = @build_pt_chown@

OK.

>  have-tunables = @have_tunables@
>  
>  # Build tools.
> diff --git a/login/Makefile b/login/Makefile
> index 92535f0aec..5c78b491f3 100644
> --- a/login/Makefile
> +++ b/login/Makefile
> @@ -34,12 +34,6 @@ CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
>  
>  others = utmpdump
>  
> -ifeq (yes,$(build-pt-chown))
> -others += pt_chown
> -others-pie = pt_chown
> -install-others-programs = $(inst_libexecdir)/pt_chown
> -endif
> -

OK.

>  subdir-dirs = programs
>  vpath %.c programs
>  
> @@ -54,20 +48,3 @@ libutil-routines:= login login_tty logout logwtmp openpty forkpty
>  include ../Rules
>  
>  CFLAGS-getpt.c += -fexceptions
> -
> -ifeq (yesyes,$(have-fpie)$(build-shared))
> -pt_chown-cflags += $(pie-ccflag)
> -endif
> -ifeq (yes,$(have-libcap))
> -libcap = -lcap
> -endif
> -CFLAGS-pt_chown.c += $(pt_chown-cflags)
> -LDLIBS-pt_chown = $(libcap)

Is this the only user of libcap in glibc?

I'm curious because if it is we should notify downstream distributions
to remove it from their libc dependencies when building packages.

I see we still have libcap-devel in Fedora Rawhide.

> -ifeq (yesyes,$(have-fpie)$(build-shared))
> -LDFLAGS-pt_chown = -Wl,-z,now
> -endif
> -
> -# pt_chown needs to be setuid root.
> -$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
> -	$(make-target-directory)
> -	-$(INSTALL_PROGRAM) -m 4755 -o root $< $@

OK.

> diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
> deleted file mode 100644
> index d44e4bf6ed..0000000000
> --- a/login/programs/pt_chown.c
> +++ /dev/null
> @@ -1,215 +0,0 @@
> -/* pt_chmod - helper program for `grantpt'.
> -   Copyright (C) 1998-2019 Free Software Foundation, Inc.
> -   This file is part of the GNU C Library.
> -   Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
> -
> -   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.
> -
> -   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.
> -
> -   You should have received a copy of the GNU Lesser General Public
> -   License along with the GNU C Library; if not, see
> -   <http://www.gnu.org/licenses/>.  */
> -
> -#include <argp.h>
> -#include <errno.h>
> -#include <error.h>
> -#include <grp.h>
> -#include <libintl.h>
> -#include <locale.h>
> -#include <signal.h>
> -#include <stdio.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <sys/stat.h>
> -#include <unistd.h>
> -#ifdef HAVE_LIBCAP
> -# include <sys/capability.h>
> -# include <sys/prctl.h>
> -#endif
> -
> -#include "pty-private.h"
> -
> -/* Get libc version number.  */
> -#include "../version.h"
> -
> -#define PACKAGE _libc_intl_domainname
> -
> -/* Name and version of program.  */
> -static void print_version (FILE *stream, struct argp_state *state);
> -void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
> -
> -/* Function to print some extra text in the help message.  */
> -static char *more_help (int key, const char *text, void *input);
> -
> -/* Data structure to communicate with argp functions.  */
> -static struct argp argp =
> -{
> -  NULL, NULL, NULL, NULL, NULL, more_help
> -};
> -
> -
> -/* Print the version information.  */
> -static void
> -print_version (FILE *stream, struct argp_state *state)
> -{
> -  fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION);
> -  fprintf (stream, gettext ("\
> -Copyright (C) %s Free Software Foundation, Inc.\n\
> -This is free software; see the source for copying conditions.  There is NO\n\
> -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
> -"), "2019");
> -}
> -
> -static char *
> -more_help (int key, const char *text, void *input)
> -{
> -  char *cp;
> -  char *tp;
> -
> -  switch (key)
> -    {
> -    case ARGP_KEY_HELP_PRE_DOC:
> -      asprintf (&cp, gettext ("\
> -Set the owner, group and access permission of the slave pseudo\
> - terminal corresponding to the master pseudo terminal passed on\
> - file descriptor `%d'.  This is the helper program for the\
> - `grantpt' function.  It is not intended to be run directly from\
> - the command line.\n"),
> -		PTY_FILENO);
> -      return cp;
> -    case ARGP_KEY_HELP_EXTRA:
> -      /* We print some extra information.  */
> -      if (asprintf (&tp, gettext ("\
> -For bug reporting instructions, please see:\n\
> -%s.\n"), REPORT_BUGS_TO) < 0)
> -	return NULL;
> -      if (asprintf (&cp, gettext ("\
> -The owner is set to the current user, the group is set to `%s',\
> - and the access permission is set to `%o'.\n\n\
> -%s"),
> -		    TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, tp) < 0)
> -	{
> -	  free (tp);
> -	  return NULL;
> -	}
> -      return cp;
> -    default:
> -      break;
> -    }
> -  return (char *) text;
> -}
> -
> -static int
> -do_pt_chown (void)
> -{
> -  char *pty;
> -  struct stat64 st;
> -  struct group *p;
> -  gid_t gid;
> -
> -  /* Check that PTY_FILENO is a valid master pseudo terminal.  */
> -  pty = ptsname (PTY_FILENO);
> -  if (pty == NULL)
> -    return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
> -
> -  /* Check that the returned slave pseudo terminal is a
> -     character device.  */
> -  if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode))
> -    return FAIL_EINVAL;
> -
> -  /* Get the group ID of the special `tty' group.  */
> -  p = getgrnam (TTY_GROUP);
> -  gid = p ? p->gr_gid : getgid ();
> -
> -  /* Set the owner to the real user ID, and the group to that special
> -     group ID.  */
> -  if (chown (pty, getuid (), gid) < 0)
> -    return FAIL_EACCES;
> -
> -  /* Set the permission mode to readable and writable by the owner,
> -     and writable by the group.  */
> -  if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)
> -      && chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
> -    return FAIL_EACCES;
> -
> -  return 0;
> -}
> -
> -
> -int
> -main (int argc, char *argv[])
> -{
> -  uid_t euid = geteuid ();
> -  uid_t uid = getuid ();
> -  int remaining;
> -  sigset_t signalset;
> -
> -  /* Clear any signal mask from the parent process.  */
> -  sigemptyset (&signalset);
> -  sigprocmask (SIG_SETMASK, &signalset, NULL);
> -
> -  if (argc == 1 && euid == 0)
> -    {
> -#ifdef HAVE_LIBCAP
> -  /* Drop privileges.  */
> -      if (uid != euid)
> -	{
> -	  static const cap_value_t cap_list[] =
> -	    { CAP_CHOWN, CAP_FOWNER	};
> -# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
> -	  cap_t caps = cap_init ();
> -	  if (caps == NULL)
> -	    return FAIL_ENOMEM;
> -
> -	  /* 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_EFFECTIVE, ncap_list, cap_list, CAP_SET);
> -
> -	  int res = cap_set_proc (caps);
> -
> -	  cap_free (caps);
> -
> -	  if (__glibc_unlikely (res != 0))
> -	    return FAIL_EXEC;
> -	}
> -#endif
> -
> -      /* Normal invocation of this program is with no arguments and
> -	 with privileges.  */
> -      return do_pt_chown ();
> -    }
> -
> -  /* We aren't going to be using privileges, so drop them right now. */
> -  setuid (uid);
> -
> -  /* Set locale via LC_ALL.  */
> -  setlocale (LC_ALL, "");
> -
> -  /* Set the text message domain.  */
> -  textdomain (PACKAGE);
> -
> -  /* parse and process arguments.  */
> -  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
> -
> -  if (remaining < argc)
> -    {
> -      /* We should not be called with any non-option parameters.  */
> -      error (0, 0, gettext ("too many arguments"));
> -      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
> -		 program_invocation_short_name);
> -      return EXIT_FAILURE;
> -    }
> -
> -  /* Check if we are properly installed.  */
> -  if (euid != 0)
> -    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
> -
> -  return EXIT_SUCCESS;
> -}

OK.

> diff --git a/manual/install.texi b/manual/install.texi
> index 2a87a2725a..49fcc7ac95 100644
> --- a/manual/install.texi
> +++ b/manual/install.texi
> @@ -209,20 +209,6 @@ additional security hardening because it enables full RELRO and a
>  read-only global offset table (GOT), at the cost of slightly increased
>  program load times.
>  
> -@pindex pt_chown
> -@findex grantpt
> -@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.
> -

OK.

>  @item --disable-werror
>  By default, @theglibc{} is built with @option{-Werror}.  If you wish
>  to build without this option (for example, if building with a newer
> @@ -442,13 +428,6 @@ may or may not want to run.  @code{nscd} caches name service lookups; it
>  can dramatically improve performance with NIS+, and may help with DNS as
>  well.
>  
> -One auxiliary program, @file{/usr/libexec/pt_chown}, is installed setuid
> -@code{root} if the @samp{--enable-pt_chown} configuration option is used.
> -This program is invoked by the @code{grantpt} function; it sets the
> -permissions on a pseudoterminal so it can be used by the calling process.
> -If you are using a Linux kernel with the @code{devpts} filesystem enabled
> -and mounted at @file{/dev/pts}, you don't need this program.
> -

OK.

>  Afer installation you should configure the timezone and install locales
>  for your system.  The time zone configuration ensures that your system
>  time matches the time for your current timezone.  The locales ensure that
> diff --git a/manual/terminal.texi b/manual/terminal.texi
> index d830baacd7..7bb974e018 100644
> --- a/manual/terminal.texi
> +++ b/manual/terminal.texi
> @@ -1989,16 +1989,6 @@ This function is a GNU extension.
>  @c  getgrnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem
>  @c  getgid dup ok
>  @c  chmod dup ok
> -@c  fork dup @aculock
> -@c  [child]
> -@c   setrlimit
> -@c   dup2
> -@c   CLOSE_ALL_FDS
> -@c   execle
> -@c   _exit
> -@c  waitpid dup ok
> -@c  WIFEXITED dup ok
> -@c  WEXITSTATUS dup ok

OK. Thanks.

>  @c  free dup @ascuheap @acsmem
>  The @code{grantpt} function changes the ownership and access permission
>  of the slave pseudo-terminal device corresponding to the master
> diff --git a/sysdeps/generic/pty-private.h b/sysdeps/generic/pty-private.h
> index 1315c01af9..7470ca0c6a 100644
> --- a/sysdeps/generic/pty-private.h
> +++ b/sysdeps/generic/pty-private.h
> @@ -26,9 +26,6 @@
>  /* The file descriptor connected to the master pseudo terminal.  */
>  #define PTY_FILENO 3
>  
> -/* Path to the helper program that implements `grantpt' in user space.  */
> -#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
> -

OK.

>  /* Test whether given TTY is really a Unix98 pseudo terminal.  */
>  /* #define unix98_pseudo_p(Dev) ... */
>  
> diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
> index e2e6df14c9..7143f54605 100644
> --- a/sysdeps/unix/grantpt.c
> +++ b/sysdeps/unix/grantpt.c
> @@ -99,7 +99,6 @@ pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp)
>  int
>  grantpt (int fd)
>  {
> -  int retval = -1;

OK.

>  #ifdef PATH_MAX
>    char _buf[PATH_MAX];
>  #else
> @@ -132,7 +131,7 @@ grantpt (int fd)
>    if (st.st_uid != uid)
>      {
>        if (__chown (buf, uid, st.st_gid) < 0)
> -	goto helper;
> +	goto cleanup;

OK.

>      }
>  
>    static int tty_gid = -1;
> @@ -155,103 +154,21 @@ grantpt (int fd)
>      }
>    gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;
>  
> -#if HAVE_PT_CHOWN
> -  /* Make sure the group of the device is that special group.  */
> -  if (st.st_gid != gid)
> -    {
> -      if (__chown (buf, uid, gid) < 0)
> -	goto helper;
> -    }
> -
> -  /* Make sure the permission mode is set to readable and writable by
> -     the owner, and writable by the group.  */
> -  mode_t mode = S_IRUSR|S_IWUSR|S_IWGRP;
> -#else
> -  /* When built without pt_chown, 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. Thus accept different group or
> -     permission mode.  */
> -

OK.

>    /* Make sure the permission is set to readable and writable by the
>       owner.  For security reasons, make it writable by the group only
>       when originally writable and when the group of the device is that
>       special group.  */
>    mode_t mode = S_IRUSR|S_IWUSR|
>  	        ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0);
> -#endif
>  
> +  int retval = 0;
^^^^^^^^^^^^^^^^^^^^ Remove.


>    if ((st.st_mode & ACCESSPERMS) != mode)
>      {
>        if (__chmod (buf, mode) < 0)
> -	goto helper;
> +	goto cleanup;
>      }
>  
>    retval = 0;
^^^^^^^^^^^^^^^^^ Remove.

> -  goto cleanup;
> -
> -  /* We have to use the helper program if it is available.  */
> - helper:;
> -
> -#if HAVE_PT_CHOWN
> -  pid_t pid = __fork ();
> -  if (pid == -1)
> -    goto cleanup;
> -  else if (pid == 0)
> -    {
> -      /* Disable core dumps.  */
> -      struct rlimit rl = { 0, 0 };
> -      __setrlimit (RLIMIT_CORE, &rl);
> -
> -      /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
> -      if (fd != PTY_FILENO)
> -	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);
> -    }
> -  else
> -    {
> -      int w;
> -
> -      if (__waitpid (pid, &w, 0) == -1)
> -	goto cleanup;
> -      if (!WIFEXITED (w))
> -	__set_errno (ENOEXEC);
> -      else
> -	switch (WEXITSTATUS (w))
> -	  {
> -	  case 0:
> -	    retval = 0;
> -	    break;
> -	  case FAIL_EBADF:
> -	    __set_errno (EBADF);
> -	    break;
> -	  case FAIL_EINVAL:
> -	    __set_errno (EINVAL);
> -	    break;
> -	  case FAIL_EACCES:
> -	    __set_errno (EACCES);
> -	    break;
> -	  case FAIL_EXEC:
> -	    __set_errno (ENOEXEC);
> -	    break;
> -	  case FAIL_ENOMEM:
> -	    __set_errno (ENOMEM);
> -	    break;
> -
> -	  default:
> -	    assert(! "grantpt: internal error: invalid exit code from pt_chown");
> -	  }
> -    }
> -#endif
> -
>   cleanup:
>    if (buf != _buf)
>      free (buf);

This ends with 'return retval;'

Should we not just make that:

/* This can never fail because the OS kernel is responsible.  */
return 0;

> diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
> deleted file mode 100644
> index 2030e07fa6..0000000000
> --- a/sysdeps/unix/sysv/linux/grantpt.c
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -#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"
> -
> -#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);
> -	  }
> -
> -      __closedir (dir);
> -
> -      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);
> -    }
> -}
> -# define CLOSE_ALL_FDS() close_all_fds()
> -#endif
> -
> -#include <sysdeps/unix/grantpt.c>
> 

OK.
Florian Weimer Jan. 7, 2019, 8:26 p.m. UTC | #3
* Carlos O'Donell:

>> @@ -54,20 +48,3 @@ libutil-routines:= login login_tty logout logwtmp openpty forkpty
>>  include ../Rules
>>  
>>  CFLAGS-getpt.c += -fexceptions
>> -
>> -ifeq (yesyes,$(have-fpie)$(build-shared))
>> -pt_chown-cflags += $(pie-ccflag)
>> -endif
>> -ifeq (yes,$(have-libcap))
>> -libcap = -lcap
>> -endif
>> -CFLAGS-pt_chown.c += $(pt_chown-cflags)
>> -LDLIBS-pt_chown = $(libcap)
>
> Is this the only user of libcap in glibc?

No, nscd needs it as well.  This part I checked. 8-/

>>    /* Make sure the permission is set to readable and writable by the
>>       owner.  For security reasons, make it writable by the group only
>>       when originally writable and when the group of the device is that
>>       special group.  */
>>    mode_t mode = S_IRUSR|S_IWUSR|
>>  	        ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0);
>> -#endif
>>  
>> +  int retval = 0;
> ^^^^^^^^^^^^^^^^^^^^ Remove.
>
>
>>    if ((st.st_mode & ACCESSPERMS) != mode)
>>      {
>>        if (__chmod (buf, mode) < 0)
>> -	goto helper;
>> +	goto cleanup;
>>      }
>>  
>>    retval = 0;
> ^^^^^^^^^^^^^^^^^ Remove.

Huh.  Did I botch this?  Yes I did.  (I tried to eliminate retval at
first, but then reconsidered.)  Thanks for catching it.  Updated patch
attached.  I'm queuing it for 2.30.

Florian

2019-01-07  Florian Weimer  <fweimer@redhat.com>

	login: Remove the pt_chown program.
	* configure.ac (--enable-pt_chown): Remove option.
	* config.h.in: Remove HAVE_PT_CHOWN.
	* config.make.in (build-pt-chown): Remove variable.
	* login/Makefile (others, others-pie, install-others-programs): Do
	not add pt_chown.
	(pt_chown-cflags, libcap, CFLAGS-pt_chown.c, LDLIBS-pt_chown)
	(LDFLAGS-pt_chown): Remove variables.
	(pt_chown): Remove target.
	* sysdeps/unix/grantpt.c (grantpt): Remove code to call the helper
	program.
	* manual/install.texi (Configuring and compiling): Remove
	description of --enable-pt_chown.
	(Running make install): Remove description of pt_chown.
	* manual/terminal.texi (Allocation): Update comment.
	* sysdeps/generic/pty-private.h (_PATH_PT_CHOWN): Remove.
	* login/programs/pt_chown.c: Remove file.
	* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
	* configure, INSTALL: Regenerate.

diff --git a/INSTALL b/INSTALL
index 672eb40640..c47d510748 100644
--- a/INSTALL
+++ b/INSTALL
@@ -181,18 +181,6 @@ if 'CFLAGS' is specified it must enable optimization.  For example:
      read-only global offset table (GOT), at the cost of slightly
      increased program load times.
 
-'--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.
-
 '--disable-werror'
      By default, the GNU C Library is built with '-Werror'.  If you wish
      to build without this option (for example, if building with a newer
@@ -404,13 +392,6 @@ may not want to run.  'nscd' caches name service lookups; it can
 dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-   One auxiliary program, '/usr/libexec/pt_chown', is installed setuid
-'root' if the '--enable-pt_chown' configuration option is used.  This
-program is invoked by the 'grantpt' function; it sets the permissions on
-a pseudoterminal so it can be used by the calling process.  If you are
-using a Linux kernel with the 'devpts' filesystem enabled and mounted at
-'/dev/pts', you don't need this program.
-
    After installation you should configure the timezone and install
 locales for your system.  The time zone configuration ensures that your
 system time matches the time for your current timezone.  The locales
diff --git a/NEWS b/NEWS
index cc20102fda..58f2c12cb8 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,10 @@ Deprecated and removed features, and other changes affecting compatibility:
   as all functions that call vscanf, vfscanf, or vsscanf are annotated with
   __attribute__ ((format (scanf, ...))).
 
+* The pt_chown program has been removed.  (It has not been installed by
+  default since glibc 2.18.)  Changing ownership of PTYs cannot be made safe
+  in userspace in a container environment.
+
 Changes to build and runtime requirements:
 
 * Python 3.4 or later is required to build the GNU C Library.
diff --git a/config.h.in b/config.h.in
index f059ec0435..43fc7a9041 100644
--- a/config.h.in
+++ b/config.h.in
@@ -229,9 +229,6 @@
 /* The ARM movw/movt instructions using PC-relative relocs work right.  */
 #define ARM_PCREL_MOVW_OK 0
 
-/* The pt_chown binary is being built and used by grantpt.  */
-#define HAVE_PT_CHOWN 0
-
 /* Define if the compiler supports __builtin_trap without
    any external dependencies such as making a function call.  */
 #define HAVE_BUILTIN_TRAP 0
diff --git a/config.make.in b/config.make.in
index f46bfc29bb..2506e317d1 100644
--- a/config.make.in
+++ b/config.make.in
@@ -101,7 +101,6 @@ build-crypt = @build_crypt@
 build-nscd = @build_nscd@
 use-nscd = @use_nscd@
 build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
-build-pt-chown = @build_pt_chown@
 have-tunables = @have_tunables@
 
 # Build tools.
diff --git a/configure b/configure
index 101dfddf37..c5afaef4b2 100755
--- a/configure
+++ b/configure
@@ -671,7 +671,6 @@ libc_cv_ssp
 libc_cv_with_fp
 base_machine
 have_tunables
-build_pt_chown
 build_nscd
 build_obsolete_nsl
 link_obsolete_rpc
@@ -790,7 +789,6 @@ enable_obsolete_nsl
 enable_systemtap
 enable_build_nscd
 enable_nscd
-enable_pt_chown
 enable_tunables
 enable_mathvec
 enable_cet
@@ -1464,7 +1462,6 @@ Optional Features:
   --enable-systemtap      enable systemtap static probe points [default=no]
   --disable-build-nscd    disable building and installing the nscd daemon
   --disable-nscd          library functions will not contact the nscd daemon
-  --enable-pt_chown       Enable building and installing pt_chown
   --enable-tunables       Enable tunables support. Known values are 'yes',
                           'no' and 'valstring'
   --enable-mathvec        Enable building and installing mathvec [default
@@ -3731,19 +3728,6 @@ else
 fi
 
 
-# Check whether --enable-pt_chown was given.
-if test "${enable_pt_chown+set}" = set; then :
-  enableval=$enable_pt_chown; build_pt_chown=$enableval
-else
-  build_pt_chown=no
-fi
-
-
-if test "$build_pt_chown" = yes; then
-  $as_echo "#define HAVE_PT_CHOWN 1" >>confdefs.h
-
-fi
-
 # Check whether --enable-tunables was given.
 if test "${enable_tunables+set}" = set; then :
   enableval=$enable_tunables; have_tunables=$enableval
diff --git a/configure.ac b/configure.ac
index 46a74687a6..5369fae7b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,16 +434,6 @@ AC_ARG_ENABLE([nscd],
 	      [use_nscd=$enableval],
 	      [use_nscd=yes])
 
-AC_ARG_ENABLE([pt_chown],
-	      [AS_HELP_STRING([--enable-pt_chown],
-	       [Enable building and installing pt_chown])],
-	      [build_pt_chown=$enableval],
-	      [build_pt_chown=no])
-AC_SUBST(build_pt_chown)
-if test "$build_pt_chown" = yes; then
-  AC_DEFINE(HAVE_PT_CHOWN)
-fi
-
 AC_ARG_ENABLE([tunables],
 	      [AS_HELP_STRING([--enable-tunables],
 	       [Enable tunables support. Known values are 'yes', 'no' and 'valstring'])],
diff --git a/login/Makefile b/login/Makefile
index 92535f0aec..5c78b491f3 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -34,12 +34,6 @@ CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
 
 others = utmpdump
 
-ifeq (yes,$(build-pt-chown))
-others += pt_chown
-others-pie = pt_chown
-install-others-programs = $(inst_libexecdir)/pt_chown
-endif
-
 subdir-dirs = programs
 vpath %.c programs
 
@@ -54,20 +48,3 @@ libutil-routines:= login login_tty logout logwtmp openpty forkpty
 include ../Rules
 
 CFLAGS-getpt.c += -fexceptions
-
-ifeq (yesyes,$(have-fpie)$(build-shared))
-pt_chown-cflags += $(pie-ccflag)
-endif
-ifeq (yes,$(have-libcap))
-libcap = -lcap
-endif
-CFLAGS-pt_chown.c += $(pt_chown-cflags)
-LDLIBS-pt_chown = $(libcap)
-ifeq (yesyes,$(have-fpie)$(build-shared))
-LDFLAGS-pt_chown = -Wl,-z,now
-endif
-
-# pt_chown needs to be setuid root.
-$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
-	$(make-target-directory)
-	-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
deleted file mode 100644
index d44e4bf6ed..0000000000
--- a/login/programs/pt_chown.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* pt_chmod - helper program for `grantpt'.
-   Copyright (C) 1998-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
-
-   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.
-
-   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.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <argp.h>
-#include <errno.h>
-#include <error.h>
-#include <grp.h>
-#include <libintl.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_LIBCAP
-# include <sys/capability.h>
-# include <sys/prctl.h>
-#endif
-
-#include "pty-private.h"
-
-/* Get libc version number.  */
-#include "../version.h"
-
-#define PACKAGE _libc_intl_domainname
-
-/* Name and version of program.  */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-/* Function to print some extra text in the help message.  */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions.  */
-static struct argp argp =
-{
-  NULL, NULL, NULL, NULL, NULL, more_help
-};
-
-
-/* Print the version information.  */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
-  fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION);
-  fprintf (stream, gettext ("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2019");
-}
-
-static char *
-more_help (int key, const char *text, void *input)
-{
-  char *cp;
-  char *tp;
-
-  switch (key)
-    {
-    case ARGP_KEY_HELP_PRE_DOC:
-      asprintf (&cp, gettext ("\
-Set the owner, group and access permission of the slave pseudo\
- terminal corresponding to the master pseudo terminal passed on\
- file descriptor `%d'.  This is the helper program for the\
- `grantpt' function.  It is not intended to be run directly from\
- the command line.\n"),
-		PTY_FILENO);
-      return cp;
-    case ARGP_KEY_HELP_EXTRA:
-      /* We print some extra information.  */
-      if (asprintf (&tp, gettext ("\
-For bug reporting instructions, please see:\n\
-%s.\n"), REPORT_BUGS_TO) < 0)
-	return NULL;
-      if (asprintf (&cp, gettext ("\
-The owner is set to the current user, the group is set to `%s',\
- and the access permission is set to `%o'.\n\n\
-%s"),
-		    TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, tp) < 0)
-	{
-	  free (tp);
-	  return NULL;
-	}
-      return cp;
-    default:
-      break;
-    }
-  return (char *) text;
-}
-
-static int
-do_pt_chown (void)
-{
-  char *pty;
-  struct stat64 st;
-  struct group *p;
-  gid_t gid;
-
-  /* Check that PTY_FILENO is a valid master pseudo terminal.  */
-  pty = ptsname (PTY_FILENO);
-  if (pty == NULL)
-    return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
-
-  /* Check that the returned slave pseudo terminal is a
-     character device.  */
-  if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode))
-    return FAIL_EINVAL;
-
-  /* Get the group ID of the special `tty' group.  */
-  p = getgrnam (TTY_GROUP);
-  gid = p ? p->gr_gid : getgid ();
-
-  /* Set the owner to the real user ID, and the group to that special
-     group ID.  */
-  if (chown (pty, getuid (), gid) < 0)
-    return FAIL_EACCES;
-
-  /* Set the permission mode to readable and writable by the owner,
-     and writable by the group.  */
-  if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)
-      && chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
-    return FAIL_EACCES;
-
-  return 0;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  uid_t euid = geteuid ();
-  uid_t uid = getuid ();
-  int remaining;
-  sigset_t signalset;
-
-  /* Clear any signal mask from the parent process.  */
-  sigemptyset (&signalset);
-  sigprocmask (SIG_SETMASK, &signalset, NULL);
-
-  if (argc == 1 && euid == 0)
-    {
-#ifdef HAVE_LIBCAP
-  /* Drop privileges.  */
-      if (uid != euid)
-	{
-	  static const cap_value_t cap_list[] =
-	    { CAP_CHOWN, CAP_FOWNER	};
-# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
-	  cap_t caps = cap_init ();
-	  if (caps == NULL)
-	    return FAIL_ENOMEM;
-
-	  /* 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_EFFECTIVE, ncap_list, cap_list, CAP_SET);
-
-	  int res = cap_set_proc (caps);
-
-	  cap_free (caps);
-
-	  if (__glibc_unlikely (res != 0))
-	    return FAIL_EXEC;
-	}
-#endif
-
-      /* Normal invocation of this program is with no arguments and
-	 with privileges.  */
-      return do_pt_chown ();
-    }
-
-  /* We aren't going to be using privileges, so drop them right now. */
-  setuid (uid);
-
-  /* Set locale via LC_ALL.  */
-  setlocale (LC_ALL, "");
-
-  /* Set the text message domain.  */
-  textdomain (PACKAGE);
-
-  /* parse and process arguments.  */
-  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
-  if (remaining < argc)
-    {
-      /* We should not be called with any non-option parameters.  */
-      error (0, 0, gettext ("too many arguments"));
-      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
-		 program_invocation_short_name);
-      return EXIT_FAILURE;
-    }
-
-  /* Check if we are properly installed.  */
-  if (euid != 0)
-    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
-
-  return EXIT_SUCCESS;
-}
diff --git a/manual/install.texi b/manual/install.texi
index 2a87a2725a..49fcc7ac95 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -209,20 +209,6 @@ additional security hardening because it enables full RELRO and a
 read-only global offset table (GOT), at the cost of slightly increased
 program load times.
 
-@pindex pt_chown
-@findex grantpt
-@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.
-
 @item --disable-werror
 By default, @theglibc{} is built with @option{-Werror}.  If you wish
 to build without this option (for example, if building with a newer
@@ -442,13 +428,6 @@ may or may not want to run.  @code{nscd} caches name service lookups; it
 can dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-One auxiliary program, @file{/usr/libexec/pt_chown}, is installed setuid
-@code{root} if the @samp{--enable-pt_chown} configuration option is used.
-This program is invoked by the @code{grantpt} function; it sets the
-permissions on a pseudoterminal so it can be used by the calling process.
-If you are using a Linux kernel with the @code{devpts} filesystem enabled
-and mounted at @file{/dev/pts}, you don't need this program.
-
 After installation you should configure the timezone and install locales
 for your system.  The time zone configuration ensures that your system
 time matches the time for your current timezone.  The locales ensure that
diff --git a/manual/terminal.texi b/manual/terminal.texi
index d830baacd7..7bb974e018 100644
--- a/manual/terminal.texi
+++ b/manual/terminal.texi
@@ -1989,16 +1989,6 @@ This function is a GNU extension.
 @c  getgrnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem
 @c  getgid dup ok
 @c  chmod dup ok
-@c  fork dup @aculock
-@c  [child]
-@c   setrlimit
-@c   dup2
-@c   CLOSE_ALL_FDS
-@c   execle
-@c   _exit
-@c  waitpid dup ok
-@c  WIFEXITED dup ok
-@c  WEXITSTATUS dup ok
 @c  free dup @ascuheap @acsmem
 The @code{grantpt} function changes the ownership and access permission
 of the slave pseudo-terminal device corresponding to the master
diff --git a/sysdeps/generic/pty-private.h b/sysdeps/generic/pty-private.h
index 1315c01af9..7470ca0c6a 100644
--- a/sysdeps/generic/pty-private.h
+++ b/sysdeps/generic/pty-private.h
@@ -26,9 +26,6 @@
 /* The file descriptor connected to the master pseudo terminal.  */
 #define PTY_FILENO 3
 
-/* Path to the helper program that implements `grantpt' in user space.  */
-#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
-
 /* Test whether given TTY is really a Unix98 pseudo terminal.  */
 /* #define unix98_pseudo_p(Dev) ... */
 
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index e2e6df14c9..6af6a07ce1 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -132,7 +132,7 @@ grantpt (int fd)
   if (st.st_uid != uid)
     {
       if (__chown (buf, uid, st.st_gid) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   static int tty_gid = -1;
@@ -155,102 +155,20 @@ grantpt (int fd)
     }
   gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;
 
-#if HAVE_PT_CHOWN
-  /* Make sure the group of the device is that special group.  */
-  if (st.st_gid != gid)
-    {
-      if (__chown (buf, uid, gid) < 0)
-	goto helper;
-    }
-
-  /* Make sure the permission mode is set to readable and writable by
-     the owner, and writable by the group.  */
-  mode_t mode = S_IRUSR|S_IWUSR|S_IWGRP;
-#else
-  /* When built without pt_chown, 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. Thus accept different group or
-     permission mode.  */
-
   /* Make sure the permission is set to readable and writable by the
      owner.  For security reasons, make it writable by the group only
      when originally writable and when the group of the device is that
      special group.  */
   mode_t mode = S_IRUSR|S_IWUSR|
 	        ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0);
-#endif
 
   if ((st.st_mode & ACCESSPERMS) != mode)
     {
       if (__chmod (buf, mode) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   retval = 0;
-  goto cleanup;
-
-  /* We have to use the helper program if it is available.  */
- helper:;
-
-#if HAVE_PT_CHOWN
-  pid_t pid = __fork ();
-  if (pid == -1)
-    goto cleanup;
-  else if (pid == 0)
-    {
-      /* Disable core dumps.  */
-      struct rlimit rl = { 0, 0 };
-      __setrlimit (RLIMIT_CORE, &rl);
-
-      /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
-      if (fd != PTY_FILENO)
-	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);
-    }
-  else
-    {
-      int w;
-
-      if (__waitpid (pid, &w, 0) == -1)
-	goto cleanup;
-      if (!WIFEXITED (w))
-	__set_errno (ENOEXEC);
-      else
-	switch (WEXITSTATUS (w))
-	  {
-	  case 0:
-	    retval = 0;
-	    break;
-	  case FAIL_EBADF:
-	    __set_errno (EBADF);
-	    break;
-	  case FAIL_EINVAL:
-	    __set_errno (EINVAL);
-	    break;
-	  case FAIL_EACCES:
-	    __set_errno (EACCES);
-	    break;
-	  case FAIL_EXEC:
-	    __set_errno (ENOEXEC);
-	    break;
-	  case FAIL_ENOMEM:
-	    __set_errno (ENOMEM);
-	    break;
-
-	  default:
-	    assert(! "grantpt: internal error: invalid exit code from pt_chown");
-	  }
-    }
-#endif
 
  cleanup:
   if (buf != _buf)
diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
deleted file mode 100644
index 2030e07fa6..0000000000
--- a/sysdeps/unix/sysv/linux/grantpt.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#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"
-
-#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);
-	  }
-
-      __closedir (dir);
-
-      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);
-    }
-}
-# define CLOSE_ALL_FDS() close_all_fds()
-#endif
-
-#include <sysdeps/unix/grantpt.c>
Samuel Thibault Jan. 7, 2019, 10:05 p.m. UTC | #4
Hello,

Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
implemented unix98 pts yet).

Samuel
Carlos O'Donell Jan. 8, 2019, 1:38 a.m. UTC | #5
On 1/7/19 5:05 PM, Samuel Thibault wrote:
> Hello,
> 
> Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
> implemented unix98 pts yet).
> 
> Samuel
> 

OK, if GNU/Hurd still needs it then we need a big comment about this and
why it can't yet be removed.

Perhaps Florian's patch should be to remove the Linux support, and only
allow the --enable flag to work for GNU/Hurd. Basically disabling this
for any GNU/Linux configuration.
Siddhesh Poyarekar Jan. 8, 2019, 2:02 a.m. UTC | #6
On 08/01/19 7:08 AM, Carlos O'Donell wrote:
> OK, if GNU/Hurd still needs it then we need a big comment about this and
> why it can't yet be removed.
> 
> Perhaps Florian's patch should be to remove the Linux support, and only
> allow the --enable flag to work for GNU/Hurd. Basically disabling this
> for any GNU/Linux configuration.

The --enable option could be removed too, given that GNU/Hurd always 
needs it.  That way, we always build pt_chown for GNU/Hurd but never for 
anything else.

Siddhesh
Florian Weimer Jan. 14, 2019, 10:01 a.m. UTC | #7
* Samuel Thibault:

> Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
> implemented unix98 pts yet).

Are you sure about the need for pt_chown?  It's specifically for Unix98
PTYs.  The references in glibc are under sysdeps/unix, which is not
implied by GNU/Hurd.  grantpt on GNU/Hurd should return ENOSYS.

Any use of pt_chown on GNU/Hurd would have to come from the outside of
glibc.

Thanks,
Florian
Samuel Thibault Jan. 14, 2019, 10:45 a.m. UTC | #8
Florian Weimer, le lun. 14 janv. 2019 11:01:39 +0100, a ecrit:
> * Samuel Thibault:
> > Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
> > implemented unix98 pts yet).
> 
> Are you sure about the need for pt_chown?

Yes, I tested renaming the binary, ptys don't work without it.

Samuel
Florian Weimer Jan. 14, 2019, 11:03 a.m. UTC | #9
* Samuel Thibault:

> Florian Weimer, le lun. 14 janv. 2019 11:01:39 +0100, a ecrit:
>> * Samuel Thibault:
>> > Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
>> > implemented unix98 pts yet).
>> 
>> Are you sure about the need for pt_chown?
>
> Yes, I tested renaming the binary, ptys don't work without it.

Interesting.  How is the binary called?  I'd like to know so that I can
spot similar GNU/Hurd dependencies in the future.

Thanks,
Florian
Samuel Thibault Jan. 15, 2019, 9:38 p.m. UTC | #10
Florian Weimer, le lun. 14 janv. 2019 11:01:39 +0100, a ecrit:
> * Samuel Thibault:
> 
> > Err, the GNU/Hurd port still needs the pt_chown helper (yes we haven't
> > implemented unix98 pts yet).
> 
> Are you sure about the need for pt_chown?  It's specifically for Unix98
> PTYs.  The references in glibc are under sysdeps/unix, which is not
> implied by GNU/Hurd.  grantpt on GNU/Hurd should return ENOSYS.

https://buildd.debian.org/status/fetch.php?pkg=glibc&arch=hurd-i386&ver=2.28-5&stamp=1547344226&raw=0

i686-gnu-gcc-8 -no-pie -fno-PIE ../sysdeps/unix/grantpt.c -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Wundef -Wwrite-strings [...]

seems to be saying that sysdeps/unix is somehow implied by GNU/Hurd :)

Samuel
Andreas Schwab Jan. 15, 2019, 9:58 p.m. UTC | #11
On Jan 15 2019, Samuel Thibault <samuel.thibault@ens-lyon.org> wrote:

> seems to be saying that sysdeps/unix is somehow implied by GNU/Hurd :)

It's coming from sysdeps/mach/hurd/Implies.

Andreas.
Florian Weimer Jan. 15, 2019, 10:19 p.m. UTC | #12
* Andreas Schwab:

> On Jan 15 2019, Samuel Thibault <samuel.thibault@ens-lyon.org> wrote:
>
>> seems to be saying that sysdeps/unix is somehow implied by GNU/Hurd :)
>
> It's coming from sysdeps/mach/hurd/Implies.

So an Implies line for a subdirectory covers all its parent directories?

Thanks,
Florian
Andreas Schwab Jan. 15, 2019, 11:21 p.m. UTC | #13
On Jan 15 2019, Florian Weimer <fweimer@redhat.com> wrote:

> So an Implies line for a subdirectory covers all its parent directories?

Every sysdep subdirectory also implies its parent.

Andreas.
diff mbox series

Patch

diff --git a/INSTALL b/INSTALL
index 672eb40640..c47d510748 100644
--- a/INSTALL
+++ b/INSTALL
@@ -181,18 +181,6 @@  if 'CFLAGS' is specified it must enable optimization.  For example:
      read-only global offset table (GOT), at the cost of slightly
      increased program load times.
 
-'--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.
-
 '--disable-werror'
      By default, the GNU C Library is built with '-Werror'.  If you wish
      to build without this option (for example, if building with a newer
@@ -404,13 +392,6 @@  may not want to run.  'nscd' caches name service lookups; it can
 dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-   One auxiliary program, '/usr/libexec/pt_chown', is installed setuid
-'root' if the '--enable-pt_chown' configuration option is used.  This
-program is invoked by the 'grantpt' function; it sets the permissions on
-a pseudoterminal so it can be used by the calling process.  If you are
-using a Linux kernel with the 'devpts' filesystem enabled and mounted at
-'/dev/pts', you don't need this program.
-
    After installation you should configure the timezone and install
 locales for your system.  The time zone configuration ensures that your
 system time matches the time for your current timezone.  The locales
diff --git a/NEWS b/NEWS
index cc20102fda..58f2c12cb8 100644
--- a/NEWS
+++ b/NEWS
@@ -85,6 +85,10 @@  Deprecated and removed features, and other changes affecting compatibility:
   as all functions that call vscanf, vfscanf, or vsscanf are annotated with
   __attribute__ ((format (scanf, ...))).
 
+* The pt_chown program has been removed.  (It has not been installed by
+  default since glibc 2.18.)  Changing ownership of PTYs cannot be made safe
+  in userspace in a container environment.
+
 Changes to build and runtime requirements:
 
 * Python 3.4 or later is required to build the GNU C Library.
diff --git a/configure b/configure
index 101dfddf37..c5afaef4b2 100755
--- a/configure
+++ b/configure
@@ -671,7 +671,6 @@  libc_cv_ssp
 libc_cv_with_fp
 base_machine
 have_tunables
-build_pt_chown
 build_nscd
 build_obsolete_nsl
 link_obsolete_rpc
@@ -790,7 +789,6 @@  enable_obsolete_nsl
 enable_systemtap
 enable_build_nscd
 enable_nscd
-enable_pt_chown
 enable_tunables
 enable_mathvec
 enable_cet
@@ -1464,7 +1462,6 @@  Optional Features:
   --enable-systemtap      enable systemtap static probe points [default=no]
   --disable-build-nscd    disable building and installing the nscd daemon
   --disable-nscd          library functions will not contact the nscd daemon
-  --enable-pt_chown       Enable building and installing pt_chown
   --enable-tunables       Enable tunables support. Known values are 'yes',
                           'no' and 'valstring'
   --enable-mathvec        Enable building and installing mathvec [default
@@ -3731,19 +3728,6 @@  else
 fi
 
 
-# Check whether --enable-pt_chown was given.
-if test "${enable_pt_chown+set}" = set; then :
-  enableval=$enable_pt_chown; build_pt_chown=$enableval
-else
-  build_pt_chown=no
-fi
-
-
-if test "$build_pt_chown" = yes; then
-  $as_echo "#define HAVE_PT_CHOWN 1" >>confdefs.h
-
-fi
-
 # Check whether --enable-tunables was given.
 if test "${enable_tunables+set}" = set; then :
   enableval=$enable_tunables; have_tunables=$enableval
diff --git a/configure.ac b/configure.ac
index 46a74687a6..5369fae7b2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,16 +434,6 @@  AC_ARG_ENABLE([nscd],
 	      [use_nscd=$enableval],
 	      [use_nscd=yes])
 
-AC_ARG_ENABLE([pt_chown],
-	      [AS_HELP_STRING([--enable-pt_chown],
-	       [Enable building and installing pt_chown])],
-	      [build_pt_chown=$enableval],
-	      [build_pt_chown=no])
-AC_SUBST(build_pt_chown)
-if test "$build_pt_chown" = yes; then
-  AC_DEFINE(HAVE_PT_CHOWN)
-fi
-
 AC_ARG_ENABLE([tunables],
 	      [AS_HELP_STRING([--enable-tunables],
 	       [Enable tunables support. Known values are 'yes', 'no' and 'valstring'])],
diff --git a/login/Makefile b/login/Makefile
index 92535f0aec..5c78b491f3 100644
--- a/login/Makefile
+++ b/login/Makefile
@@ -34,12 +34,6 @@  CFLAGS-grantpt.c += -DLIBEXECDIR='"$(libexecdir)"'
 
 others = utmpdump
 
-ifeq (yes,$(build-pt-chown))
-others += pt_chown
-others-pie = pt_chown
-install-others-programs = $(inst_libexecdir)/pt_chown
-endif
-
 subdir-dirs = programs
 vpath %.c programs
 
@@ -54,20 +48,3 @@  libutil-routines:= login login_tty logout logwtmp openpty forkpty
 include ../Rules
 
 CFLAGS-getpt.c += -fexceptions
-
-ifeq (yesyes,$(have-fpie)$(build-shared))
-pt_chown-cflags += $(pie-ccflag)
-endif
-ifeq (yes,$(have-libcap))
-libcap = -lcap
-endif
-CFLAGS-pt_chown.c += $(pt_chown-cflags)
-LDLIBS-pt_chown = $(libcap)
-ifeq (yesyes,$(have-fpie)$(build-shared))
-LDFLAGS-pt_chown = -Wl,-z,now
-endif
-
-# pt_chown needs to be setuid root.
-$(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
-	$(make-target-directory)
-	-$(INSTALL_PROGRAM) -m 4755 -o root $< $@
diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c
deleted file mode 100644
index d44e4bf6ed..0000000000
--- a/login/programs/pt_chown.c
+++ /dev/null
@@ -1,215 +0,0 @@ 
-/* pt_chmod - helper program for `grantpt'.
-   Copyright (C) 1998-2019 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
-
-   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.
-
-   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.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <argp.h>
-#include <errno.h>
-#include <error.h>
-#include <grp.h>
-#include <libintl.h>
-#include <locale.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#ifdef HAVE_LIBCAP
-# include <sys/capability.h>
-# include <sys/prctl.h>
-#endif
-
-#include "pty-private.h"
-
-/* Get libc version number.  */
-#include "../version.h"
-
-#define PACKAGE _libc_intl_domainname
-
-/* Name and version of program.  */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-/* Function to print some extra text in the help message.  */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions.  */
-static struct argp argp =
-{
-  NULL, NULL, NULL, NULL, NULL, more_help
-};
-
-
-/* Print the version information.  */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
-  fprintf (stream, "pt_chown %s%s\n", PKGVERSION, VERSION);
-  fprintf (stream, gettext ("\
-Copyright (C) %s Free Software Foundation, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2019");
-}
-
-static char *
-more_help (int key, const char *text, void *input)
-{
-  char *cp;
-  char *tp;
-
-  switch (key)
-    {
-    case ARGP_KEY_HELP_PRE_DOC:
-      asprintf (&cp, gettext ("\
-Set the owner, group and access permission of the slave pseudo\
- terminal corresponding to the master pseudo terminal passed on\
- file descriptor `%d'.  This is the helper program for the\
- `grantpt' function.  It is not intended to be run directly from\
- the command line.\n"),
-		PTY_FILENO);
-      return cp;
-    case ARGP_KEY_HELP_EXTRA:
-      /* We print some extra information.  */
-      if (asprintf (&tp, gettext ("\
-For bug reporting instructions, please see:\n\
-%s.\n"), REPORT_BUGS_TO) < 0)
-	return NULL;
-      if (asprintf (&cp, gettext ("\
-The owner is set to the current user, the group is set to `%s',\
- and the access permission is set to `%o'.\n\n\
-%s"),
-		    TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, tp) < 0)
-	{
-	  free (tp);
-	  return NULL;
-	}
-      return cp;
-    default:
-      break;
-    }
-  return (char *) text;
-}
-
-static int
-do_pt_chown (void)
-{
-  char *pty;
-  struct stat64 st;
-  struct group *p;
-  gid_t gid;
-
-  /* Check that PTY_FILENO is a valid master pseudo terminal.  */
-  pty = ptsname (PTY_FILENO);
-  if (pty == NULL)
-    return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
-
-  /* Check that the returned slave pseudo terminal is a
-     character device.  */
-  if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode))
-    return FAIL_EINVAL;
-
-  /* Get the group ID of the special `tty' group.  */
-  p = getgrnam (TTY_GROUP);
-  gid = p ? p->gr_gid : getgid ();
-
-  /* Set the owner to the real user ID, and the group to that special
-     group ID.  */
-  if (chown (pty, getuid (), gid) < 0)
-    return FAIL_EACCES;
-
-  /* Set the permission mode to readable and writable by the owner,
-     and writable by the group.  */
-  if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)
-      && chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
-    return FAIL_EACCES;
-
-  return 0;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  uid_t euid = geteuid ();
-  uid_t uid = getuid ();
-  int remaining;
-  sigset_t signalset;
-
-  /* Clear any signal mask from the parent process.  */
-  sigemptyset (&signalset);
-  sigprocmask (SIG_SETMASK, &signalset, NULL);
-
-  if (argc == 1 && euid == 0)
-    {
-#ifdef HAVE_LIBCAP
-  /* Drop privileges.  */
-      if (uid != euid)
-	{
-	  static const cap_value_t cap_list[] =
-	    { CAP_CHOWN, CAP_FOWNER	};
-# define ncap_list (sizeof (cap_list) / sizeof (cap_list[0]))
-	  cap_t caps = cap_init ();
-	  if (caps == NULL)
-	    return FAIL_ENOMEM;
-
-	  /* 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_EFFECTIVE, ncap_list, cap_list, CAP_SET);
-
-	  int res = cap_set_proc (caps);
-
-	  cap_free (caps);
-
-	  if (__glibc_unlikely (res != 0))
-	    return FAIL_EXEC;
-	}
-#endif
-
-      /* Normal invocation of this program is with no arguments and
-	 with privileges.  */
-      return do_pt_chown ();
-    }
-
-  /* We aren't going to be using privileges, so drop them right now. */
-  setuid (uid);
-
-  /* Set locale via LC_ALL.  */
-  setlocale (LC_ALL, "");
-
-  /* Set the text message domain.  */
-  textdomain (PACKAGE);
-
-  /* parse and process arguments.  */
-  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
-  if (remaining < argc)
-    {
-      /* We should not be called with any non-option parameters.  */
-      error (0, 0, gettext ("too many arguments"));
-      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
-		 program_invocation_short_name);
-      return EXIT_FAILURE;
-    }
-
-  /* Check if we are properly installed.  */
-  if (euid != 0)
-    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
-
-  return EXIT_SUCCESS;
-}
diff --git a/manual/install.texi b/manual/install.texi
index 2a87a2725a..49fcc7ac95 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -209,20 +209,6 @@  additional security hardening because it enables full RELRO and a
 read-only global offset table (GOT), at the cost of slightly increased
 program load times.
 
-@pindex pt_chown
-@findex grantpt
-@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.
-
 @item --disable-werror
 By default, @theglibc{} is built with @option{-Werror}.  If you wish
 to build without this option (for example, if building with a newer
@@ -442,13 +428,6 @@  may or may not want to run.  @code{nscd} caches name service lookups; it
 can dramatically improve performance with NIS+, and may help with DNS as
 well.
 
-One auxiliary program, @file{/usr/libexec/pt_chown}, is installed setuid
-@code{root} if the @samp{--enable-pt_chown} configuration option is used.
-This program is invoked by the @code{grantpt} function; it sets the
-permissions on a pseudoterminal so it can be used by the calling process.
-If you are using a Linux kernel with the @code{devpts} filesystem enabled
-and mounted at @file{/dev/pts}, you don't need this program.
-
 After installation you should configure the timezone and install locales
 for your system.  The time zone configuration ensures that your system
 time matches the time for your current timezone.  The locales ensure that
diff --git a/manual/terminal.texi b/manual/terminal.texi
index d830baacd7..7bb974e018 100644
--- a/manual/terminal.texi
+++ b/manual/terminal.texi
@@ -1989,16 +1989,6 @@  This function is a GNU extension.
 @c  getgrnam_r @mtslocale @ascudlopen @ascuplugin @ascuheap @asulock @acucorrupt @aculock @acsfd @acsmem
 @c  getgid dup ok
 @c  chmod dup ok
-@c  fork dup @aculock
-@c  [child]
-@c   setrlimit
-@c   dup2
-@c   CLOSE_ALL_FDS
-@c   execle
-@c   _exit
-@c  waitpid dup ok
-@c  WIFEXITED dup ok
-@c  WEXITSTATUS dup ok
 @c  free dup @ascuheap @acsmem
 The @code{grantpt} function changes the ownership and access permission
 of the slave pseudo-terminal device corresponding to the master
diff --git a/sysdeps/generic/pty-private.h b/sysdeps/generic/pty-private.h
index 1315c01af9..7470ca0c6a 100644
--- a/sysdeps/generic/pty-private.h
+++ b/sysdeps/generic/pty-private.h
@@ -26,9 +26,6 @@ 
 /* The file descriptor connected to the master pseudo terminal.  */
 #define PTY_FILENO 3
 
-/* Path to the helper program that implements `grantpt' in user space.  */
-#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
-
 /* Test whether given TTY is really a Unix98 pseudo terminal.  */
 /* #define unix98_pseudo_p(Dev) ... */
 
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c
index e2e6df14c9..7143f54605 100644
--- a/sysdeps/unix/grantpt.c
+++ b/sysdeps/unix/grantpt.c
@@ -99,7 +99,6 @@  pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp)
 int
 grantpt (int fd)
 {
-  int retval = -1;
 #ifdef PATH_MAX
   char _buf[PATH_MAX];
 #else
@@ -132,7 +131,7 @@  grantpt (int fd)
   if (st.st_uid != uid)
     {
       if (__chown (buf, uid, st.st_gid) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   static int tty_gid = -1;
@@ -155,103 +154,21 @@  grantpt (int fd)
     }
   gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;
 
-#if HAVE_PT_CHOWN
-  /* Make sure the group of the device is that special group.  */
-  if (st.st_gid != gid)
-    {
-      if (__chown (buf, uid, gid) < 0)
-	goto helper;
-    }
-
-  /* Make sure the permission mode is set to readable and writable by
-     the owner, and writable by the group.  */
-  mode_t mode = S_IRUSR|S_IWUSR|S_IWGRP;
-#else
-  /* When built without pt_chown, 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. Thus accept different group or
-     permission mode.  */
-
   /* Make sure the permission is set to readable and writable by the
      owner.  For security reasons, make it writable by the group only
      when originally writable and when the group of the device is that
      special group.  */
   mode_t mode = S_IRUSR|S_IWUSR|
 	        ((st.st_gid == gid) ? (st.st_mode & S_IWGRP) : 0);
-#endif
 
+  int retval = 0;
   if ((st.st_mode & ACCESSPERMS) != mode)
     {
       if (__chmod (buf, mode) < 0)
-	goto helper;
+	goto cleanup;
     }
 
   retval = 0;
-  goto cleanup;
-
-  /* We have to use the helper program if it is available.  */
- helper:;
-
-#if HAVE_PT_CHOWN
-  pid_t pid = __fork ();
-  if (pid == -1)
-    goto cleanup;
-  else if (pid == 0)
-    {
-      /* Disable core dumps.  */
-      struct rlimit rl = { 0, 0 };
-      __setrlimit (RLIMIT_CORE, &rl);
-
-      /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
-      if (fd != PTY_FILENO)
-	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);
-    }
-  else
-    {
-      int w;
-
-      if (__waitpid (pid, &w, 0) == -1)
-	goto cleanup;
-      if (!WIFEXITED (w))
-	__set_errno (ENOEXEC);
-      else
-	switch (WEXITSTATUS (w))
-	  {
-	  case 0:
-	    retval = 0;
-	    break;
-	  case FAIL_EBADF:
-	    __set_errno (EBADF);
-	    break;
-	  case FAIL_EINVAL:
-	    __set_errno (EINVAL);
-	    break;
-	  case FAIL_EACCES:
-	    __set_errno (EACCES);
-	    break;
-	  case FAIL_EXEC:
-	    __set_errno (ENOEXEC);
-	    break;
-	  case FAIL_ENOMEM:
-	    __set_errno (ENOMEM);
-	    break;
-
-	  default:
-	    assert(! "grantpt: internal error: invalid exit code from pt_chown");
-	  }
-    }
-#endif
-
  cleanup:
   if (buf != _buf)
     free (buf);
diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
deleted file mode 100644
index 2030e07fa6..0000000000
--- a/sysdeps/unix/sysv/linux/grantpt.c
+++ /dev/null
@@ -1,44 +0,0 @@ 
-#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"
-
-#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);
-	  }
-
-      __closedir (dir);
-
-      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);
-    }
-}
-# define CLOSE_ALL_FDS() close_all_fds()
-#endif
-
-#include <sysdeps/unix/grantpt.c>