]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Keep CAP_NET_RAW around when SO_BINDTODEVICE is in use
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 3 Oct 2019 15:06:44 +0000 (17:06 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 3 Oct 2019 15:06:44 +0000 (17:06 +0200)
pdns/capabilities.cc
pdns/capabilities.hh
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh

index 74a20fa8949dbb833471a30bd5446196fc3be84e..534d66554229bc51f94764b8c81d070e319ce677 100644 (file)
 #include "capabilities.hh"
 #include "misc.hh"
 
-void dropCapabilities()
+void dropCapabilities(std::set<std::string> capabilitiesToKeep)
 {
 #ifdef HAVE_LIBCAP
    cap_t caps = cap_get_proc();
    if (caps != nullptr) {
      cap_clear(caps);
 
+     if (!capabilitiesToKeep.empty()) {
+       std::vector<cap_value_t> toKeep;
+       toKeep.reserve(capabilitiesToKeep.size());
+
+       for (const auto& capToKeep : capabilitiesToKeep) {
+         cap_value_t value;
+         int res = cap_from_name(capToKeep.c_str(), &value);
+         if (res != 0) {
+           cap_free(caps);
+           throw std::runtime_error("Unable to convert capability name '" + capToKeep + "': " + stringerror());
+         }
+         toKeep.push_back(value);
+       }
+
+       if (cap_set_flag(caps, CAP_EFFECTIVE, toKeep.size(), toKeep.data(), CAP_SET) != 0) {
+         cap_free(caps);
+         throw std::runtime_error("Unable to set effective flag capabilities: " + stringerror());
+       }
+
+       if (cap_set_flag(caps, CAP_PERMITTED, toKeep.size(), toKeep.data(), CAP_SET) != 0) {
+         cap_free(caps);
+         throw std::runtime_error("Unable to set permitted flag capabilities: " + stringerror());
+       }
+     }
+
      if (cap_set_proc(caps) != 0) {
        cap_free(caps);
        throw std::runtime_error("Unable to drop capabilities: " + stringerror());
index e9499f5a8ddde9a5d38268ce9ad767077df324d4..4d0b0ded3c2619afd338ed1d329c0e339ef44d9d 100644 (file)
@@ -21,4 +21,6 @@
  */
 #pragma once
 
-void dropCapabilities();
+#include <set>
+
+void dropCapabilities(std::set<std::string> capabilitiesToKeep = {});
index 186f889b33b8d927fcf7277fa348f5d1538b3b6a..275e6859b37a1afd07852e0223570f4041cb30df 100644 (file)
@@ -238,6 +238,10 @@ void setupLuaConfig(bool client)
                                sourceAddr = ComboAddress(source.substr(0, pos));
                                sourceItf = itfIdx;
                              }
+#ifdef SO_BINDTODEVICE
+                              /* we need to retain CAP_NET_RAW to be able to set SO_BINDTODEVICE in the health checks */
+                              g_capabilitiesToRetain.insert("CAP_NET_RAW");
+#endif
                            }
                            else
                            {
index de8f284a45e9a5b242a0ed1e7075dc83966b5328..ba9760548668c3386c06be0a8d9c8285e514490d 100644 (file)
@@ -144,6 +144,8 @@ bool g_fixupCase{false};
 bool g_preserveTrailingData{false};
 bool g_roundrobinFailOnNoServer{false};
 
+std::set<std::string> g_capabilitiesToRetain;
+
 static void truncateTC(char* packet, uint16_t* len, size_t responseSize, unsigned int consumed)
 try
 {
@@ -2744,7 +2746,7 @@ try
        or as an unprivileged user with ambient
        capabilities like CAP_NET_BIND_SERVICE.
     */
-    dropCapabilities();
+    dropCapabilities(g_capabilitiesToRetain);
   }
   catch(const std::exception& e) {
     warnlog("%s", e.what());
index fa7349a19deaa860a69c70c4300e6143406c09c2..6ccc3ae84b052cb128b7e8fd67c3a9bc5a54d921 100644 (file)
@@ -1233,6 +1233,8 @@ extern bool g_snmpTrapsEnabled;
 extern DNSDistSNMPAgent* g_snmpAgent;
 extern bool g_addEDNSToSelfGeneratedResponses;
 
+extern std::set<std::string> g_capabilitiesToRetain;
+
 static const size_t s_udpIncomingBufferSize{1500};
 
 enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };