Skip to content

Commit

Permalink
Extend pt_chown to drop privileges.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ulrich Drepper committed Jun 16, 2009
1 parent fab8238 commit f793b62
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 11 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
7 changes: 6 additions & 1 deletion login/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand Down
45 changes: 38 additions & 7 deletions login/programs/pt_chown.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -99,7 +103,7 @@ static int
do_pt_chown (void)
{
char *pty;
struct stat st;
struct stat64 st;
struct group *p;
gid_t gid;

Expand All @@ -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. */
Expand All @@ -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, "");
Expand Down
5 changes: 3 additions & 2 deletions sysdeps/generic/pty-private.h
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -39,7 +39,8 @@ enum /* failure modes */
FAIL_EBADF = 1,
FAIL_EINVAL,
FAIL_EACCES,
FAIL_EXEC
FAIL_EXEC,
FAIL_ENOMEM
};

#endif /* pty-private.h */
5 changes: 4 additions & 1 deletion sysdeps/unix/grantpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ grantpt (int fd)
if (!WIFEXITED (w))
__set_errno (ENOEXEC);
else
switch (WEXITSTATUS(w))
switch (WEXITSTATUS (w))
{
case 0:
retval = 0;
Expand All @@ -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");
Expand Down

0 comments on commit f793b62

Please sign in to comment.