]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Extend pt_chown to drop privileges.
authorUlrich Drepper <drepper@redhat.com>
Tue, 16 Jun 2009 22:58:07 +0000 (15:58 -0700)
committerUlrich Drepper <drepper@redhat.com>
Tue, 16 Jun 2009 22:58:07 +0000 (15:58 -0700)
If libcap is available, use it to drop privileges in pt_chown before
starting the work to change the permissions and ownership of the
slave device.

ChangeLog
login/Makefile
login/programs/pt_chown.c
sysdeps/generic/pty-private.h
sysdeps/unix/grantpt.c

index 85ab3dab50f545b44cfb90dbd972529ffe617627..4d7f002a4fc86ea5944dc8bc1f90e2b6e79f2a7e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-06-16  Ulrich Drepper  <drepper@redhat.com>
+
+       * login/Makefile: If necessary link pt_chown with -lcap.
+
 2009-06-16  Jakub Jelinek  <jakub@redhat.com>
 
        * sysdeps/x86_64/memchr.S (memchr): Use unsigned instead of signed
index b02d385b667fbba482805a342fc503b272edc6d0..427c050a8984d62c88c3c24dc549aa55049c287b 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 1996-1998,2000-2002,2003,2007 Free Software Foundation, Inc.
+# Copyright (C) 1996-1998,2000-2003,2007, 2009 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -54,6 +54,11 @@ otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \
             $(resolvobjdir)/libresolv.a $(common-objpfx)libc.a
 endif
 
+ifeq (yes,$(have-libcap))
+libcap = -lcap
+endif
+LDLIBS-pt_chown = $(libcap)
+
 # pt_chown needs to be setuid root.
 $(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force)
        $(make-target-directory)
index 5167b292256bbb1815646f22c5d58ffa6d67ff65..7e279a5f3b6848170146d5964e8e7f07f34392c6 100644 (file)
 #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"
 
@@ -99,7 +103,7 @@ static int
 do_pt_chown (void)
 {
   char *pty;
-  struct stat st;
+  struct stat64 st;
   struct group *p;
   gid_t gid;
 
@@ -110,7 +114,7 @@ do_pt_chown (void)
 
   /* Check that the returned slave pseudo terminal is a
      character device.  */
-  if (stat (pty, &st) < 0 || !S_ISCHR(st.st_mode))
+  if (stat64 (pty, &st) < 0 || !S_ISCHR (st.st_mode))
     return FAIL_EINVAL;
 
   /* Get the group ID of the special `tty' group.  */
@@ -136,16 +140,43 @@ int
 main (int argc, char *argv[])
 {
   uid_t euid = geteuid ();
+  uid_t uid = getuid ();
   int remaining;
 
-  /* Normal invocation of this program is with no arguments and
-     with privileges.
-     FIXME: Should use capable (CAP_CHOWN|CAP_FOWNER).  */
   if (argc == 1 && euid == 0)
-    return do_pt_chown ();
+    {
+#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)
+           error (FAIL_ENOMEM, errno,
+                  _("Failed to initialize drop of capabilities"));
+
+         /* 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 (__builtin_expect (res != 0, 0))
+           error (FAIL_EXEC, errno, _("cap_set_proc failed"));
+       }
+#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 (getuid ());
+  setuid (uid);
 
   /* Set locale via LC_ALL.  */
   setlocale (LC_ALL, "");
index d6ec2cee68c76dc0aa72e35ce60f73aee0438bfc..493f40551deebe5a2f203acee6be7f30c4ae53d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Internal defenitions and declarations for pseudo terminal functions.
-   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
 
@@ -39,7 +39,8 @@ enum  /* failure modes */
   FAIL_EBADF = 1,
   FAIL_EINVAL,
   FAIL_EACCES,
-  FAIL_EXEC
+  FAIL_EXEC,
+  FAIL_ENOMEM
 };
 
 #endif /* pty-private.h  */
index f664b9eb1beddbe97c52b67786d8345a83f4eb97..8c299e91478a2b610c59a84b797ac601f361edc9 100644 (file)
@@ -202,7 +202,7 @@ grantpt (int fd)
       if (!WIFEXITED (w))
        __set_errno (ENOEXEC);
       else
-       switch (WEXITSTATUS(w))
+       switch (WEXITSTATUS (w))
          {
          case 0:
            retval = 0;
@@ -219,6 +219,9 @@ grantpt (int fd)
          case FAIL_EXEC:
            __set_errno (ENOEXEC);
            break;
+         case FAIL_ENOMEM:
+           __set_errno (ENOMEM);
+           break;
 
          default:
            assert(! "getpt: internal error: invalid exit code from pt_chown");