Blame SOURCES/0011-Drop-unnecessary-capabilities.patch

f9ed25
From 3b37f4b7bb3a17f8bd655be919915a1912062ea6 Mon Sep 17 00:00:00 2001
f9ed25
From: Pavel Zhukov <pzhukov@redhat.com>
f9ed25
Date: Thu, 21 Feb 2019 10:30:28 +0100
f9ed25
Subject: [PATCH 11/26] Drop unnecessary capabilities
f9ed25
Cc: pzhukov@redhat.com
f9ed25
f9ed25
dhclient (#517649, #546765), dhcpd/dhcrelay (#699713)
f9ed25
---
f9ed25
 client/Makefile.am       |  3 ++-
f9ed25
 client/dhclient-script.8 | 10 ++++++++++
f9ed25
 client/dhclient.8        | 29 +++++++++++++++++++++++++++++
f9ed25
 client/dhclient.c        | 24 ++++++++++++++++++++++++
f9ed25
 configure.ac             | 35 +++++++++++++++++++++++++++++++++++
f9ed25
 relay/Makefile.am        |  3 ++-
f9ed25
 relay/dhcrelay.c         | 29 +++++++++++++++++++++++++++++
f9ed25
 7 files changed, 131 insertions(+), 2 deletions(-)
f9ed25
f9ed25
diff --git a/client/Makefile.am b/client/Makefile.am
f9ed25
index d177159..0689185 100644
f9ed25
--- a/client/Makefile.am
f9ed25
+++ b/client/Makefile.am
f9ed25
@@ -17,6 +17,7 @@ dhclient_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
f9ed25
 		 @BINDLIBIRSDIR@/libirs.@A@ \
f9ed25
 		 @BINDLIBDNSDIR@/libdns.@A@ \
f9ed25
 		 @BINDLIBISCCFGDIR@/libisccfg.@A@ \
f9ed25
-		 @BINDLIBISCDIR@/libisc.@A@
f9ed25
+		 @BINDLIBISCDIR@/libisc.@A@ \
f9ed25
+		 $(CAPNG_LDADD)
f9ed25
 man_MANS = dhclient.8 dhclient-script.8 dhclient.conf.5 dhclient.leases.5
f9ed25
 EXTRA_DIST = $(man_MANS)
f9ed25
diff --git a/client/dhclient-script.8 b/client/dhclient-script.8
f9ed25
index 0db5516..2eddb8f 100644
f9ed25
--- a/client/dhclient-script.8
f9ed25
+++ b/client/dhclient-script.8
f9ed25
@@ -243,6 +243,16 @@ repeatedly initialized to the values provided by one server, and then
f9ed25
 the other.   Assuming the information provided by both servers is
f9ed25
 valid, this shouldn't cause any real problems, but it could be
f9ed25
 confusing.
f9ed25
+.PP
f9ed25
+Normally, if dhclient was compiled with libcap-ng support,
f9ed25
+dhclient drops most capabilities immediately upon startup.
f9ed25
+While more secure, this greatly restricts the additional actions that
f9ed25
+hooks in dhclient-script can take. For example, any daemons that
f9ed25
+dhclient-script starts or restarts will inherit the restricted
f9ed25
+capabilities as well, which may interfere with their correct operation.
f9ed25
+Thus, the
f9ed25
+.BI \-nc
f9ed25
+option can be used to prevent dhclient from dropping capabilities.
f9ed25
 .SH SEE ALSO
f9ed25
 dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
f9ed25
 dhclient.leases(5).
f9ed25
diff --git a/client/dhclient.8 b/client/dhclient.8
f9ed25
index 6d7fbdb..0145b9f 100644
f9ed25
--- a/client/dhclient.8
f9ed25
+++ b/client/dhclient.8
f9ed25
@@ -134,6 +134,9 @@ dhclient - Dynamic Host Configuration Protocol Client
f9ed25
 .B -w
f9ed25
 ]
f9ed25
 [
f9ed25
+.B -nc
f9ed25
+]
f9ed25
+[
f9ed25
 .B -B
f9ed25
 ]
f9ed25
 [
f9ed25
@@ -328,6 +331,32 @@ not to exit when it doesn't find any such interfaces.  The
f9ed25
 program can then be used to notify the client when a network interface
f9ed25
 has been added or removed, so that the client can attempt to configure an IP
f9ed25
 address on that interface.
f9ed25
+.TP
f9ed25
+.BI \-nc
f9ed25
+Do not drop capabilities.
f9ed25
+
f9ed25
+Normally, if
f9ed25
+.B dhclient
f9ed25
+was compiled with libcap-ng support,
f9ed25
+.B dhclient
f9ed25
+drops most capabilities immediately upon startup.  While more secure,
f9ed25
+this greatly restricts the additional actions that hooks in
f9ed25
+.B dhclient-script (8)
f9ed25
+can take.  (For example, any daemons that 
f9ed25
+.B dhclient-script (8)
f9ed25
+starts or restarts will inherit the restricted capabilities as well,
f9ed25
+which may interfere with their correct operation.)  Thus, the
f9ed25
+.BI \-nc
f9ed25
+option can be used to prevent
f9ed25
+.B dhclient
f9ed25
+from dropping capabilities.
f9ed25
+
f9ed25
+The
f9ed25
+.BI \-nc
f9ed25
+option is ignored if
f9ed25
+.B dhclient
f9ed25
+was not compiled with libcap-ng support.
f9ed25
+
f9ed25
 .TP
f9ed25
 .BI \-n
f9ed25
 Do not configure any interfaces.  This is most likely to be useful in
f9ed25
diff --git a/client/dhclient.c b/client/dhclient.c
f9ed25
index a86ab9e..5d3f5bc 100644
f9ed25
--- a/client/dhclient.c
f9ed25
+++ b/client/dhclient.c
f9ed25
@@ -41,6 +41,10 @@
f9ed25
 #include <sys/wait.h>
f9ed25
 #include <limits.h>
f9ed25
 
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+#include <cap-ng.h>
f9ed25
+#endif
f9ed25
+
f9ed25
 /*
f9ed25
  * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define
f9ed25
  * that when building ISC code.
f9ed25
@@ -266,6 +270,9 @@ main(int argc, char **argv) {
f9ed25
 	int timeout_arg = 0;
f9ed25
 	char *arg_conf = NULL;
f9ed25
 	int arg_conf_len = 0;
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+	int keep_capabilities = 0;
f9ed25
+#endif
f9ed25
 
f9ed25
 	/* Initialize client globals. */
f9ed25
 	memset(&default_duid, 0, sizeof(default_duid));
f9ed25
@@ -665,6 +672,10 @@ main(int argc, char **argv) {
f9ed25
 
f9ed25
 			dhclient_request_options = argv[i];
f9ed25
 
f9ed25
+		} else if (!strcmp(argv[i], "-nc")) {
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+                  keep_capabilities = 1;
f9ed25
+#endif
f9ed25
 		} else if (argv[i][0] == '-') {
f9ed25
 			usage("Unknown command: %s", argv[i]);
f9ed25
 		} else if (interfaces_requested < 0) {
f9ed25
@@ -725,6 +736,19 @@ main(int argc, char **argv) {
f9ed25
 		path_dhclient_script = s;
f9ed25
 	}
f9ed25
 
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+	/* Drop capabilities */
f9ed25
+	if (!keep_capabilities) {
f9ed25
+		capng_clear(CAPNG_SELECT_CAPS);
f9ed25
+		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
f9ed25
+				CAP_DAC_OVERRIDE); // Drop this someday
f9ed25
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
f9ed25
+				CAP_NET_ADMIN, CAP_NET_RAW,
f9ed25
+				CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
f9ed25
+		capng_apply(CAPNG_SELECT_CAPS);
f9ed25
+	}
f9ed25
+#endif
f9ed25
+
f9ed25
 	/* Set up the initial dhcp option universe. */
f9ed25
 	initialize_common_option_spaces();
f9ed25
 
f9ed25
diff --git a/configure.ac b/configure.ac
f9ed25
index a797438..15fc0d7 100644
f9ed25
--- a/configure.ac
f9ed25
+++ b/configure.ac
f9ed25
@@ -612,6 +612,41 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[void foo() __attribute__((noreturn));
f9ed25
 # Look for optional headers.
f9ed25
 AC_CHECK_HEADERS(sys/socket.h net/if_dl.h net/if6.h regex.h)
f9ed25
 
f9ed25
+# look for capabilities library
f9ed25
+AC_ARG_WITH(libcap-ng,
f9ed25
+    [  --with-libcap-ng=[auto/yes/no]  Add Libcap-ng support [default=auto]],,
f9ed25
+    with_libcap_ng=auto)
f9ed25
+
f9ed25
+# Check for Libcap-ng API
f9ed25
+#
f9ed25
+# libcap-ng detection
f9ed25
+if test x$with_libcap_ng = xno ; then
f9ed25
+    have_libcap_ng=no;
f9ed25
+else
f9ed25
+    # Start by checking for header file
f9ed25
+    AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no)
f9ed25
+
f9ed25
+    # See if we have libcap-ng library
f9ed25
+    AC_CHECK_LIB(cap-ng, capng_clear,
f9ed25
+                 CAPNG_LDADD=-lcap-ng,)
f9ed25
+
f9ed25
+    # Check results are usable
f9ed25
+    if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then
f9ed25
+       AC_MSG_ERROR(libcap-ng support was requested and the library was not found)
f9ed25
+    fi
f9ed25
+    if test x$CAPNG_LDADD != x -a $capng_headers = no ; then
f9ed25
+       AC_MSG_ERROR(libcap-ng libraries found but headers are missing)
f9ed25
+    fi
f9ed25
+fi
f9ed25
+AC_SUBST(CAPNG_LDADD)
f9ed25
+AC_MSG_CHECKING(whether to use libcap-ng)
f9ed25
+if test x$CAPNG_LDADD != x ; then
f9ed25
+    AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])
f9ed25
+    AC_MSG_RESULT(yes)
f9ed25
+else
f9ed25
+    AC_MSG_RESULT(no)
f9ed25
+fi
f9ed25
+
f9ed25
 # Solaris needs some libraries for functions
f9ed25
 AC_SEARCH_LIBS(socket, [socket])
f9ed25
 AC_SEARCH_LIBS(inet_ntoa, [nsl])
f9ed25
diff --git a/relay/Makefile.am b/relay/Makefile.am
f9ed25
index 2ba5979..8900e0b 100644
f9ed25
--- a/relay/Makefile.am
f9ed25
+++ b/relay/Makefile.am
f9ed25
@@ -6,7 +6,8 @@ dhcrelay_LDADD = ../common/libdhcp.@A@ ../omapip/libomapi.@A@ \
f9ed25
 		 @BINDLIBIRSDIR@/libirs.@A@ \
f9ed25
 		 @BINDLIBDNSDIR@/libdns.@A@ \
f9ed25
 		 @BINDLIBISCCFGDIR@/libisccfg.@A@ \
f9ed25
-		 @BINDLIBISCDIR@/libisc.@A@
f9ed25
+		 @BINDLIBISCDIR@/libisc.@A@ \
f9ed25
+		 $(CAPNG_LDADD)
f9ed25
 man_MANS = dhcrelay.8
f9ed25
 EXTRA_DIST = $(man_MANS)
f9ed25
 
f9ed25
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
f9ed25
index ea1be18..7b4f4f1 100644
f9ed25
--- a/relay/dhcrelay.c
f9ed25
+++ b/relay/dhcrelay.c
f9ed25
@@ -32,6 +32,11 @@
f9ed25
 #include <sys/time.h>
f9ed25
 #include <isc/file.h>
f9ed25
 
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+#  include <cap-ng.h>
f9ed25
+   int keep_capabilities = 0;
f9ed25
+#endif
f9ed25
+
f9ed25
 TIME default_lease_time = 43200; /* 12 hours... */
f9ed25
 TIME max_lease_time = 86400; /* 24 hours... */
f9ed25
 struct tree_cache *global_options[256];
f9ed25
@@ -590,6 +595,10 @@ main(int argc, char **argv) {
f9ed25
 			if (++i == argc)
f9ed25
 				usage(use_noarg, argv[i-1]);
f9ed25
 			dhcrelay_sub_id = argv[i];
f9ed25
+#endif
f9ed25
+		} else if (!strcmp(argv[i], "-nc")) {
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+			keep_capabilities = 1;
f9ed25
 #endif
f9ed25
 		} else if (!strcmp(argv[i], "-pf")) {
f9ed25
 			if (++i == argc)
f9ed25
@@ -660,6 +669,17 @@ main(int argc, char **argv) {
f9ed25
 #endif
f9ed25
 	}
f9ed25
 
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+	/* Drop capabilities */
f9ed25
+	if (!keep_capabilities) {
f9ed25
+		capng_clear(CAPNG_SELECT_BOTH);
f9ed25
+		capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
f9ed25
+				CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
f9ed25
+		capng_apply(CAPNG_SELECT_BOTH);
f9ed25
+		log_info ("Dropped all unnecessary capabilities.");
f9ed25
+	}
f9ed25
+#endif
f9ed25
+
f9ed25
 	if (!quiet) {
f9ed25
 		log_info("%s %s", message, PACKAGE_VERSION);
f9ed25
 		log_info(copyright);
f9ed25
@@ -816,6 +836,15 @@ main(int argc, char **argv) {
f9ed25
 	signal(SIGTERM, dhcp_signal_handler);  /* kill */
f9ed25
 #endif
f9ed25
 
f9ed25
+#ifdef HAVE_LIBCAP_NG
f9ed25
+	/* Drop all capabilities */
f9ed25
+	if (!keep_capabilities) {
f9ed25
+		capng_clear(CAPNG_SELECT_BOTH);
f9ed25
+		capng_apply(CAPNG_SELECT_BOTH);
f9ed25
+		log_info ("Dropped all capabilities.");
f9ed25
+	}
f9ed25
+#endif
f9ed25
+
f9ed25
 	/* Start dispatching packets and timeouts... */
f9ed25
 	dispatch();
f9ed25
 
f9ed25
-- 
f9ed25
2.14.5
f9ed25