]> granicus.if.org Git - pdns/commitdiff
dnsdist: Drop remaining capabilities after startup
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 2 Nov 2018 13:01:15 +0000 (14:01 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 5 Dec 2018 11:24:30 +0000 (12:24 +0100)
m4/pdns_with_libcap.m4 [new file with mode: 0644]
pdns/dnsdist.cc
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/configure.ac
pdns/dnsdistdist/m4/pdns_with_libcap.m4 [new symlink]
pdns/misc.cc
pdns/misc.hh

diff --git a/m4/pdns_with_libcap.m4 b/m4/pdns_with_libcap.m4
new file mode 100644 (file)
index 0000000..0dba5da
--- /dev/null
@@ -0,0 +1,25 @@
+AC_DEFUN([PDNS_WITH_LIBCAP], [
+  AC_MSG_CHECKING([whether we will be linking in libcap])
+  HAVE_LIBCAPS=0
+  AC_ARG_WITH([libcap],
+    AS_HELP_STRING([--with-libcap],[use libcap @<:@default=auto@:>@]),
+    [with_libcap=$withval],
+    [with_libcap=auto],
+  )
+  AC_MSG_RESULT([$with_libcap])
+
+  AS_IF([test "x$with_libcap" != "xno"], [
+    AS_IF([test "x$with_libcap" = "xyes" -o "x$with_libcap" = "xauto"], [
+      PKG_CHECK_MODULES([LIBCAP], [libcap] , [
+        [HAVE_LIBCAP=1]
+        AC_DEFINE([HAVE_LIBCAP], [1], [Define to 1 if you have libcap])
+      ], [ : ])
+    ])
+  ])
+  AM_CONDITIONAL([HAVE_LIBCAP], [test "x$LIBCAP_LIBS" != "x"])
+  AS_IF([test "x$with_libcap" = "xyes"], [
+    AS_IF([test x"$LIBCAP_LIBS" = "x"], [
+      AC_MSG_ERROR([libcap requested but libraries were not found])
+    ])
+  ])
+])
index 915d90484fbcbae9e5f0e96f1e26d7376f25ec42..7ada5929ed33a08a5b9611549af8db6cd57ad111 100644 (file)
@@ -2701,6 +2701,18 @@ try
 
   dropGroupPrivs(newgid);
   dropUserPrivs(newuid);
+  try {
+    /* we might still have capabilities remaining,
+       for example if we have been started as root
+       without --uid or --gid (please don't do that)
+       or as an unprivileged user with ambient
+       capabilities like CAP_NET_BIND_SERVICE.
+    */
+    dropCapabilities();
+  }
+  catch(const std::exception& e) {
+    warnlog("%s", e.what());
+  }
 
   /* this need to be done _after_ dropping privileges */
   g_delay = new DelayPipe<DelayedPacket>();
index 92c8632ce89c6653679cd3982c483d69b64688fb..50354ece18e622d6a4d9b479d8c4df07c5563d28 100644 (file)
@@ -1,4 +1,4 @@
-AM_CPPFLAGS += $(SYSTEMD_CFLAGS) $(LUA_CFLAGS) $(LIBEDIT_CFLAGS) $(LIBSODIUM_CFLAGS) $(FSTRM_CFLAGS) $(YAHTTP_CFLAGS) $(SANITIZER_FLAGS) $(NET_SNMP_CFLAGS) -DSYSCONFDIR=\"${sysconfdir}\"
+AM_CPPFLAGS += $(SYSTEMD_CFLAGS) $(LUA_CFLAGS) $(LIBEDIT_CFLAGS) $(LIBSODIUM_CFLAGS) $(FSTRM_CFLAGS) $(YAHTTP_CFLAGS) $(SANITIZER_FLAGS) $(NET_SNMP_CFLAGS) $(LIBCAP_CFLAGS) -DSYSCONFDIR=\"${sysconfdir}\"
 
 ACLOCAL_AMFLAGS = -I m4
 
@@ -162,7 +162,8 @@ dnsdist_LDADD = \
        $(FSTRM_LIBS) \
        $(SANITIZER_FLAGS) \
        $(SYSTEMD_LIBS) \
-       $(NET_SNMP_LIBS)
+       $(NET_SNMP_LIBS) \
+       $(LIBCAP_LIBS)
 
 if HAVE_RE2
 dnsdist_LDADD += $(RE2_LIBS)
@@ -266,7 +267,8 @@ testrunner_LDADD = \
        $(LIBSODIUM_LIBS) \
        $(FSTRM_LIBS) \
        $(RT_LIBS) \
-       $(SANITIZER_FLAGS)
+       $(SANITIZER_FLAGS) \
+       $(LIBCAP_LIBS)
 
 MANPAGES=dnsdist.1
 
index a1b41989cff632799882b3f48f5289a6f9e5fa16..6ee328f24ddc3043cd55c7402fb4690c9a94d94b 100644 (file)
@@ -40,6 +40,7 @@ PDNS_WITH_RE2
 DNSDIST_ENABLE_DNSCRYPT
 PDNS_WITH_EBPF
 PDNS_WITH_NET_SNMP
+PDNS_WITH_LIBCAP
 
 AX_AVAILABLE_SYSTEMD
 AM_CONDITIONAL([HAVE_SYSTEMD], [ test x"$systemd" = "xy" ])
diff --git a/pdns/dnsdistdist/m4/pdns_with_libcap.m4 b/pdns/dnsdistdist/m4/pdns_with_libcap.m4
new file mode 120000 (symlink)
index 0000000..bf9aef7
--- /dev/null
@@ -0,0 +1 @@
+../../../m4/pdns_with_libcap.m4
\ No newline at end of file
index 196a4bcf4822bd309f069cc0ccb5c49108647503..cd8842ed5d70d2e2f7bd68b58561907f63baee01 100644 (file)
 #  include <sched.h>
 #endif
 
+#ifdef HAVE_LIBCAP
+#include <sys/capability.h>
+#endif
+
 bool g_singleThreaded;
 
 size_t writen2(int fd, const void *buf, size_t count)
@@ -1449,3 +1453,20 @@ std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath)
 
   return results;
 }
+
+void dropCapabilities()
+{
+#ifdef HAVE_LIBCAP
+   cap_t caps = cap_get_proc();
+   if (caps != nullptr) {
+     cap_clear(caps);
+
+     if (cap_set_proc(caps) != 0) {
+       cap_free(caps);
+       throw std::runtime_error("Unable to drop capabilities: " + std::string(strerror(errno)));
+     }
+
+     cap_free(caps);
+   }
+#endif /* HAVE_LIBCAP */
+}
index fcf3c6a51dabe77557ee3b6a8fce01febac1f6e2..d4420dfa84682064346f33ddf54754629a231780 100644 (file)
@@ -593,6 +593,7 @@ double DiffTime(const struct timespec& first, const struct timespec& second);
 double DiffTime(const struct timeval& first, const struct timeval& second);
 uid_t strToUID(const string &str);
 gid_t strToGID(const string &str);
+void dropCapabilities();
 
 unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10);