diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-06-16 15:58:07 -0700 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2009-08-04 10:57:56 +0200 |
commit | a7800930627c2ee5d4d3b373f62c897e0c321c19 (patch) | |
tree | 0706ba10078a6836b166464e3ee181c82f922f2e | |
parent | a584fc6a6b81183ed6ce1724237c6744cdd6559e (diff) |
Extend pt_chown to drop privileges.
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.
(cherry picked from commit f793b62438a3cfdbcc5ba453eebee1db3f315bea)
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | login/Makefile | 7 | ||||
-rw-r--r-- | login/programs/pt_chown.c | 45 | ||||
-rw-r--r-- | sysdeps/generic/pty-private.h | 5 | ||||
-rw-r--r-- | sysdeps/unix/grantpt.c | 5 |
5 files changed, 55 insertions, 11 deletions
@@ -1,3 +1,7 @@ +2009-06-16 Ulrich Drepper <drepper@redhat.com> + + * login/Makefile: If necessary link pt_chown with -lcap. + 2009-06-02 H.J. Lu <hongjiu.lu@intel.com> * Makeconfig (+link-pie): Define. diff --git a/login/Makefile b/login/Makefile index b02d385b66..427c050a89 100644 --- a/login/Makefile +++ b/login/Makefile @@ -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) diff --git a/login/programs/pt_chown.c b/login/programs/pt_chown.c index 485eddabc9..9544653693 100644 --- a/login/programs/pt_chown.c +++ b/login/programs/pt_chown.c @@ -29,6 +29,10 @@ #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. */ @@ -135,16 +139,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, ""); diff --git a/sysdeps/generic/pty-private.h b/sysdeps/generic/pty-private.h index d6ec2cee68..493f40551d 100644 --- a/sysdeps/generic/pty-private.h +++ b/sysdeps/generic/pty-private.h @@ -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 */ diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c index bdedbacec8..39797841c5 100644 --- a/sysdeps/unix/grantpt.c +++ b/sysdeps/unix/grantpt.c @@ -185,7 +185,7 @@ grantpt (int fd) if (!WIFEXITED (w)) __set_errno (ENOEXEC); else - switch (WEXITSTATUS(w)) + switch (WEXITSTATUS (w)) { case 0: retval = 0; @@ -202,6 +202,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"); |