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.
This commit is contained in:
Ulrich Drepper 2009-06-16 15:58:07 -07:00
parent fab8238de6
commit f793b62438
5 changed files with 55 additions and 11 deletions

View File

@ -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

View 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)

View File

@ -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. */
@ -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, "");

View 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 */

View 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");