[gnome-keyring] - Use file system based capabilities instead of suid bit (#668831)

Tomas Bzatek tbzatek at fedoraproject.org
Mon Jan 17 15:02:23 UTC 2011


commit e41c396c8901bc8e3746e12d878fccc0dc584303
Author: Tomas Bzatek <tbzatek at redhat.com>
Date:   Mon Jan 17 16:02:15 2011 +0100

    - Use file system based capabilities instead of suid bit (#668831)

 file-caps.patch    |  186 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gnome-keyring.spec |   14 ++++-
 2 files changed, 198 insertions(+), 2 deletions(-)
---
diff --git a/file-caps.patch b/file-caps.patch
new file mode 100644
index 0000000..de99c34
--- /dev/null
+++ b/file-caps.patch
@@ -0,0 +1,186 @@
+diff -urp gnome-keyring-2.91.4.orig/configure.in gnome-keyring-2.91.4/configure.in
+--- gnome-keyring-2.91.4.orig/configure.in	2011-01-13 08:24:04.000000000 -0500
++++ gnome-keyring-2.91.4/configure.in	2011-01-13 09:29:54.000000000 -0500
+@@ -447,19 +447,19 @@ if test "$ASN1PARSER" = "no" ; then
+ fi
+ 
+ # -------------------------------------------------------------------
+-# libcap2
++# libcap-ng
+ #
+ 
+-AC_CHECK_LIB([cap], [cap_get_proc], have_libcap="yes", have_libcap="no")
++AC_CHECK_LIB([cap-ng], [capng_clear], have_libcapng="yes", have_libcapng="no")
+ 
+-if test $have_libcap = yes; then
+-   AC_DEFINE(HAVE_LIBCAP, 1, [Have libcap2 package, libcap library])
+-   DAEMON_LIBS="$DAEMON_LIBS -lcap"
++if test $have_libcapng = yes; then
++   AC_DEFINE(HAVE_LIBCAPNG, 1, [Have libcap-ng package, libcap-ng library])
++   DAEMON_LIBS="$DAEMON_LIBS -lcap-ng"
+ else
+-   AC_MSG_WARN([libcap2 (or development headers) is not installed])
++   AC_MSG_WARN([libcap-ng (or development headers) is not installed])
+ fi
+ 
+-libcap_status=$have_libcap
++libcapng_status=$have_libcapng
+ 
+ # --------------------------------------------------------------------
+ # Debug mode
+@@ -748,7 +748,7 @@ ui/tests/Makefile
+ echo
+ echo "OPTIONAL DEPENDENCIES"
+ echo "  PAM:                  $pam_status"
+-echo "  Linux capabilities:   $libcap_status"
++echo "  Linux capabilities:   $libcapng_status"
+ echo
+ echo "CONFIGURATION"
+ echo "  SSH Agent:            $ssh_status"
+diff -urp gnome-keyring-2.91.4.orig/daemon/gkd-capability.c gnome-keyring-2.91.4/daemon/gkd-capability.c
+--- gnome-keyring-2.91.4.orig/daemon/gkd-capability.c	2011-01-13 08:24:04.000000000 -0500
++++ gnome-keyring-2.91.4/daemon/gkd-capability.c	2011-01-13 09:30:12.000000000 -0500
+@@ -1,7 +1,7 @@
+ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ /* gkd-capability.c - the security-critical initial phase of the daemon
+  *
+- * Copyright (C) 2010 Yaron Sheffer
++ * Copyright (C) 2011 Steve Grubb
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU Lesser General Public License as
+@@ -18,102 +18,62 @@
+  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+  * 02111-1307, USA.
+  *
+- * Author: Yaron Sheffer <yaronf at gmx.com>
+- * Author: Stef Walter <stef at thewalter.net>
++ * Author: Steve Grubb <sgrubb at redhat.com>
+  */
+ 
+ #include "config.h"
+ 
+ #include "gkd-capability.h"
+ 
+-#ifdef HAVE_LIBCAP
+-#include <sys/capability.h>
++#ifdef HAVE_LIBCAPNG
++#include <cap-ng.h>
+ #endif
+ 
+ #include <stdio.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+ #include <stdlib.h>
+ 
+-/* Security note: this portion of the code is extremely sensitive.
+- * DO NOT add any other include files.
+- */
+-
+ /*
+  * No logging, no gettext
+  */
+ static void
+ early_error (const char *err_string)
+ {
+-	fprintf (stderr, "gnome-keyring-daemon: %s\n", err_string);
+-}
+-
+-static void
+-drop_privileges (void)
+-{
+-	uid_t orig_uid;
+-	gid_t orig_gid;
+-
+-	orig_uid = getuid ();
+-	orig_gid = getgid ();
+-
+-	/* This is permanent, you cannot go back to root */
+-	setgid (orig_gid);
+-	setuid (orig_uid);
+-
+-	/*
+-	 * Check that the switch was ok
+-	 * We do not allow programs to run without the drop being
+-	 * successful as this would possibly run the program
+-	 * using root-privs, when that is not what we want
+-	 */
+-	if ((getegid () != orig_gid) || (geteuid () != orig_uid)) {
+-		early_error ("failed to drop privileges, aborting");
+-		exit (1);
+-	}
++	fprintf (stderr, "gnome-keyring-daemon: %s, aborting\n", err_string);
++	exit (1);
+ }
+ 
+ /*
+- * Try to obtain the CAP_IPC_LOCK Linux capability.
+- * Then, whether or not this is successful, drop root
+- * privileges to run as the invoking user. The application is aborted
+- * if for any reason we are unable to drop privileges. Note: even gettext
+- * is unavailable!
++ * This program needs the CAP_IPC_LOCK posix capability.
++ * We want to allow either setuid root or file system based capabilies
++ * to work. If file system based capabilities, this is a no-op unless
++ * the root user is running the program. In that case we just drop
++ * capabilities down to IPC_LOCK. If we are setuid root, then change to the
++ * invoking user retaining just the IPC_LOCK capability. The application
++ * is aborted if for any reason we are unable to drop privileges.
++ * Note: even gettext is unavailable!
+  */
+ void
+ gkd_capability_obtain_capability_and_drop_privileges (void)
+ {
+-#ifdef HAVE_LIBCAP
+-	cap_t caps;
+-	cap_value_t cap_list[1];
+-
+-	caps = cap_get_proc ();
+-	if (caps == NULL) {
+-		early_error ("capability state cannot be allocated");
+-		goto drop;
+-	}
+-
+-	cap_list[0] = CAP_IPC_LOCK;
+-	if (cap_set_flag (caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1) {
+-		early_error ("error when manipulating capability sets");
+-		goto drop;
+-	}
+-
+-	if (cap_set_proc (caps) == -1) {
+-		/* Only warn when it's root that's running */
+-		if (getuid () == 0)
+-			early_error ("cannot apply capabilities to process");
+-		goto drop;
+-	}
+-
+-	if (cap_free (caps) == -1) {
+-		early_error ("failed to free capability structure");
+-		goto drop;
++#ifdef HAVE_LIBCAPNG
++	capng_get_caps_process ();
++	switch (capng_have_capabilities (CAPNG_SELECT_CAPS))
++	{
++		case CAPNG_FULL:
++			/* We are either setuid root or the root user */
++			capng_clear (CAPNG_SELECT_CAPS);
++			capng_update (CAPNG_ADD,
++					CAPNG_EFFECTIVE|CAPNG_PERMITTED,
++					CAP_IPC_LOCK);
++			if (capng_change_id (getuid (), getgid (), 0)) 
++				early_error ("failed dropping capabilities");
++			break;
++		case CAPNG_FAIL:
++		case CAPNG_NONE:
++			early_error ("error getting process capabilities");
++			break;
++		case CAPNG_PARTIAL: /* File system based capabilities */
++                        break;
+ 	}
+-drop:
+-
+ #endif
+-	/* Now finally drop the suid by becoming the invoking user */
+-	if (geteuid () != getuid() || getegid () != getgid ())
+-		drop_privileges ();
+ }
diff --git a/gnome-keyring.spec b/gnome-keyring.spec
index 3124e50..f96e49b 100644
--- a/gnome-keyring.spec
+++ b/gnome-keyring.spec
@@ -7,7 +7,7 @@
 Summary: Framework for managing passwords and other secrets
 Name: gnome-keyring
 Version: 2.91.4
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: GPLv2+ and LGPLv2+
 Group: System Environment/Libraries
 #VCS: git:git://git.gnome.org/gnome-keyring
@@ -18,6 +18,9 @@ URL: http://www.gnome.org
 # http://bugs.gnome.org/598494
 Patch3: gnome-keyring-2.28.1-nopass.patch
 
+# why is gnome-keyring-daemon setuid root?
+# https://bugzilla.redhat.com/show_bug.cgi?id=668831
+Patch4: file-caps.patch
 
 BuildRequires: glib2-devel >= %{glib2_version}
 BuildRequires: gtk3-devel >= %{gtk3_version}
@@ -31,6 +34,7 @@ BuildRequires: intltool
 BuildRequires: libtasn1-tools
 BuildRequires: libgnome-keyring-devel
 BuildRequires: gtk-doc
+BuildRequires: libcap-ng-devel
 # for smooth transition since the core was split
 Requires: libgnome-keyring
 
@@ -68,6 +72,7 @@ automatically unlock the "login" keyring when the user logs in.
 %prep
 %setup -q -n gnome-keyring-%{version}
 %patch3 -p1 -b .no-pass
+%patch4 -p1 -b .file-caps
 
 # Enable daemon autostart in XFCE
 for i in daemon/*.desktop.in.in; do
@@ -121,7 +126,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas
 %{_libdir}/pkcs11/*.so
 %{_libdir}/gnome-keyring/devel/*.so
 # GPL
-%{_bindir}/*
+%attr(0755,root,root) %caps(cap_ipc_lock=ep) %{_bindir}/gnome-keyring-daemon
+%{_bindir}/gnome-keyring
+%{_bindir}/gnome-keyring-3
 %{_libexecdir}/*
 %{_datadir}/dbus-1/services/*.service
 %{_datadir}/gcr-3
@@ -145,6 +152,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas
 
 
 %changelog
+* Mon Jan 17 2011 Tomas Bzatek <tbzatek at redhat.com> - 2.91.4-3
+- Use file system based capabilities instead of suid bit (#668831)
+
 * Fri Jan  7 2011 Matthias Clasen <mclasen at redhat.com> - 2.91.4-2
 - Rebuild against new gtk
 


More information about the scm-commits mailing list