Debian Bug report logs - #517235
s-s-d: Add support for capability dropping

version graph

Package: dpkg; Maintainer for dpkg is Dpkg Developers <debian-dpkg@lists.debian.org>; Source for dpkg is src:dpkg.

Reported by: Nicolas Bareil <nico@chdir.org>

Date: Thu, 26 Feb 2009 15:42:01 UTC

Severity: normal

Tags: patch

Found in version dpkg/1.14.24

Reply or subscribe to this bug.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Dpkg Developers <debian-dpkg@lists.debian.org>:
Bug#517235; Package dpkg. (Thu, 26 Feb 2009 15:42:04 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nicolas Bareil <nico@chdir.org>:
New Bug report received and forwarded. Copy sent to Dpkg Developers <debian-dpkg@lists.debian.org>. (Thu, 26 Feb 2009 15:42:06 GMT) Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Nicolas Bareil <nico@chdir.org>
To: submit@bugs.debian.org
Subject: [PATCH] Wishlist: Support of capability dropping.
Date: Thu, 26 Feb 2009 16:33:50 +0100
Package: dpkg
Version: 1.14.24

Capabilities allow the administrator to split "root" user's power into
a set of privileges. For instance, most network daemons start as root because
they need to bind a port < 1024 when they in fact just need the
CAP_NET_BIND_SERVICE capacity.

The patch below provides the ability to remove some capabilities.

As it seems difficult to assess the specific capabilities needed by each
daemon (w/o maintainers' help), the patch just gives the option to do
so, but does not change anything by default. It is hence 100% backward
compatible with current packages.

Nonetheless, the set of "default" capabilities used by most Debian
daemons could be limited: most of those do not need CAP_SYS_PTRACE,
CAP_NET_RAW, etc. In fact, most daemons would work just fine when
launched w/o the following capabilities:

 - cap_sys_module    - cap_mknod            - cap_sys_tty_config
 - cap_sys_ptrace    - cap_net_admin        - cap_ipc_owner
 - cap_net_raw       - cap_mac_admin        - cap_sys_resource
 - cap_sys_boot      - cap_sys_rawio        - cap_mac_override
 - cap_sys_chroot    - cap_kill             - cap_audit_control
 - cap_sys_time      - cap_linux_immutable
 - cap_sys_pacct     - cap_sys_admin

However, some daemons will require some tuning like OpenSSH which
requires cap_sys_chroot and cap_net_admin (if using layer 2 tunnel).

My patch (against git tree) is trivial but I have most probably screwed
up the autoconf/automake stuff :)

It introduces a new command line option (--dropcap/-D) which takes a list of
capabilities to be removed (separated by commas).

The capabilities requested for removal are suppressed by modifying the "capability
bouding set" and the "inherited capability set" in order to be sure that the
daemon will never get it (even by exec*() a SUID binary).

---
 configure.ac              |    2 +-
 m4/libs.m4                |    1 +
 man/start-stop-daemon.8   |   12 ++++++++
 utils/start-stop-daemon.c |   64 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3d3b607..e11b462 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,7 @@ fi
 # Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS([stddef.h error.h locale.h libintl.h kvm.h \
-                  sys/cdefs.h sys/syscall.h])
+                  sys/cdefs.h sys/syscall.h sys/capability.h])
 DPKG_CHECK_DEFINE(TIOCNOTTY, [sys/ioctl.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
diff --git a/m4/libs.m4 b/m4/libs.m4
index 1b3cb24..3af9775 100644
--- a/m4/libs.m4
+++ b/m4/libs.m4
@@ -108,4 +108,5 @@ AC_CHECK_LIB([ihash], [ihash_create], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lihash"
 AC_CHECK_LIB([ps], [proc_stat_list_create], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lps"])
 AC_CHECK_LIB([shouldbeinlibc], [fmt_past_time], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lshouldbeinlibc"])
 AC_CHECK_LIB([kvm], [kvm_openfiles], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lkvm"])
+AC_CHECK_LIB([cap], [cap_from_name], [SSD_LIBS="${SSD_LIBS:+$SSD_LIBS }-lcap"])
 ])# DPKG_LIB_SSD
diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8
index 1e6c00f..4cfc1c7 100644
--- a/man/start-stop-daemon.8
+++ b/man/start-stop-daemon.8
@@ -196,6 +196,9 @@ Chdir and chroot to
 before starting the process. Please note that the pidfile is also written
 after the chroot.
 .TP
+.BR \-D ", " \-\-dropcap " \fIcapabilities1,capabilities2\fP"
+Drop theses capabilities separated by commas.
+.TP
 .BR \-d ", " \-\-chdir " \fIpath\fP"
 Chdir to
 .I path
@@ -290,6 +293,15 @@ Demonstration of a custom schedule for stopping \fBfood\fP:
 start\-stop\-daemon \-\-stop \-\-oknodo \-\-user food \-\-name food \-\-pidfile /var/run/food.pid \-\-retry=TERM/30/KILL/5
 .fi
 .PP
+Start the \fBfood\fP daemon without two \fBcapabilities\fP:
+.IP
+.nf
+start\-stop\-daemon \-\-dropcap CAP_NET_RAW,cap_sys_module \-\-start \-\-exec /usr/sbin/food
+.fi
+.PP
+.
+.SH SEE ALSO
+\fBcapabilities\fP(7),
 .
 .SH AUTHORS
 Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> based on
diff --git a/utils/start-stop-daemon.c b/utils/start-stop-daemon.c
index 34ee022..5c35a89 100644
--- a/utils/start-stop-daemon.c
+++ b/utils/start-stop-daemon.c
@@ -59,6 +59,11 @@
 #include <limits.h>
 #endif
 
+#if HAVE_SYS_CAPABILITY_H
+# include <sys/prctl.h>
+# include <sys/capability.h>
+#endif
+
 #ifdef HAVE_KVM_H
 #include <kvm.h>
 #include <sys/sysctl.h>
@@ -156,6 +161,7 @@ static char what_stop[1024];
 static const char *progname = "";
 static int nicelevel = 0;
 static int umask_value = -1;
+static char *caplist = NULL;
 
 #define IOPRIO_CLASS_SHIFT 13
 #define IOPRIO_PRIO_VALUE(class, prio) (((class) << IOPRIO_CLASS_SHIFT) | (prio))
@@ -361,6 +367,7 @@ do_help(void)
 "  -s|--signal <signal>          signal to send (default TERM)\n"
 "  -a|--startas <pathname>       program to start (default is <executable>)\n"
 "  -r|--chroot <directory>       chroot to <directory> before starting\n"
+"  -D|--dropcap <capbilities>    drop theses capabilities\n"
 "  -d|--chdir <directory>        change to <directory> (default is /)\n"
 "  -N|--nicelevel <incr>         add incr to the process's nice level\n"
 "  -P|--procsched <policy[:prio]>\n"
@@ -667,6 +674,46 @@ parse_schedule(const char *schedule_str)
 	}
 }
 
+#ifdef HAVE_SYS_CAPABILITY_H
+static void
+remove_capabilities(char *capstr) {
+	cap_value_t capval;
+	char *savedptr, *ptr;
+	cap_t caps;
+
+	caps = cap_get_proc();
+	if (caps == NULL) {
+		fatal("Unable to retrieve my capabilities");
+	}
+
+	ptr = strtok_r(capstr, ",", &savedptr);
+	while (ptr) {
+		if (cap_from_name(ptr, &capval) != 0) {
+			errno = EINVAL;
+			fatal("Unable to parse this capability : \"%s\"", ptr);
+		}
+
+		if (prctl(PR_CAPBSET_DROP, capval, 0, 0) != 0) {
+			fatal("Unable to drop this capability: %s", ptr);
+		}
+
+		if (cap_set_flag(caps, CAP_INHERITABLE, 1, (cap_value_t *)&capval, CAP_CLEAR) != 0) {
+			fatal("Unable to clear the capability %s", ptr);
+		}
+
+		ptr = strtok_r(NULL, ",", &savedptr);
+	}
+
+	if (cap_set_proc(caps) != 0) {
+		fatal("Unable to remove theses capabilities from the inherited set\n");
+	}
+
+	if (cap_free(caps) == -1) {
+		fatal("Cannot free the capability");
+	}
+}
+#endif
+
 static void
 parse_options(int argc, char * const *argv)
 {
@@ -685,6 +732,7 @@ parse_options(int argc, char * const *argv)
 		{ "user",	  1, NULL, 'u'},
 		{ "group",	  1, NULL, 'g'},
 		{ "chroot",	  1, NULL, 'r'},
+		{ "dropcap",      1, NULL, 'D'},
 		{ "verbose",	  0, NULL, 'v'},
 		{ "exec",	  1, NULL, 'x'},
 		{ "chuid",	  1, NULL, 'c'},
@@ -707,7 +755,7 @@ parse_options(int argc, char * const *argv)
 
 	for (;;) {
 		c = getopt_long(argc, argv,
-		                "HKSVa:n:op:qr:s:tu:vx:c:N:P:I:k:bmR:g:d:",
+		                "HKSVa:n:op:qr:s:tu:vx:c:N:P:I:k:bmR:g:d:D:",
 		                longopts, NULL);
 		if (c == -1)
 			break;
@@ -767,6 +815,13 @@ parse_options(int argc, char * const *argv)
 		case 'r':  /* --chroot /new/root */
 			changeroot = optarg;
 			break;
+		case 'D':  /* --dropcap cap_net_raw,cap_mac_admin */
+#ifdef HAVE_SYS_CAPABILITY_H
+			caplist = optarg;
+#else
+			badusage("Capabilities are not supported on your OS");
+#endif
+			break;
 		case 'N':  /* --nice */
 			nicelevel = atoi(optarg);
 			break;
@@ -1589,6 +1644,13 @@ main(int argc, char **argv)
 		for (i = get_open_fd_max() - 1; i >= 3; --i)
 			close(i);
 	}
+
+#ifdef HAVE_SYS_CAPABILITY_H
+	if (caplist) {
+		remove_capabilities(caplist);
+	}
+#endif
+
 	execv(startas, argv);
 	fatal("Unable to start %s: %s", startas, strerror(errno));
 }

-- 
Nicolas Bareil                                  http://chdir.org/~nico/
OpenPGP=0xAE4F7057 Fingerprint=34DB22091049FB2F33E6B71580F314DAAE4F7057




Tags added: patch Request was from Raphael Hertzog <hertzog@debian.org> to control@bugs.debian.org. (Sun, 10 May 2009 20:36:05 GMT) Full text and rfc822 format available.

Information forwarded to debian-bugs-dist@lists.debian.org, Dpkg Developers <debian-dpkg@lists.debian.org>:
Bug#517235; Package dpkg. (Thu, 03 Dec 2009 09:33:07 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nicolas Bareil <nico@chdir.org>:
Extra info received and forwarded to list. Copy sent to Dpkg Developers <debian-dpkg@lists.debian.org>. (Thu, 03 Dec 2009 09:33:07 GMT) Full text and rfc822 format available.

Message #12 received at 517235@bugs.debian.org (full text, mbox):

From: Nicolas Bareil <nico@chdir.org>
To: 517235@bugs.debian.org
Subject: capability support: patch status?
Date: Thu, 03 Dec 2009 09:56:07 +0100
Hello,

Is there a status for this patch? Should it be resubmitted?

Chrome OS has implemented an equivalent feature thanks to their minijail[1]
tool : they implement capabilities and namespaces among other things.


Footnotes: 
[1]  http://www.chromium.org/chromium-os/chromiumos-design-docs/system-hardening#Phase_1_026564505184363374_762





Changed Bug title to 's-s-d: Add support for capability dropping' from '[PATCH] Wishlist: Support of capability dropping.' Request was from Guillem Jover <guillem@debian.org> to control@bugs.debian.org. (Wed, 26 Jan 2011 04:24:03 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Fri Apr 18 20:51:48 2014; Machine Name: beach.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.