From: Remi Gacogne Date: Thu, 3 Oct 2019 15:06:44 +0000 (+0200) Subject: dnsdist: Keep CAP_NET_RAW around when SO_BINDTODEVICE is in use X-Git-Tag: dnsdist-1.4.0-rc4~27^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83fe2c55f47555d8d4b0992407ea16dc78421b95;p=pdns dnsdist: Keep CAP_NET_RAW around when SO_BINDTODEVICE is in use --- diff --git a/pdns/capabilities.cc b/pdns/capabilities.cc index 74a20fa89..534d66554 100644 --- a/pdns/capabilities.cc +++ b/pdns/capabilities.cc @@ -32,13 +32,38 @@ #include "capabilities.hh" #include "misc.hh" -void dropCapabilities() +void dropCapabilities(std::set capabilitiesToKeep) { #ifdef HAVE_LIBCAP cap_t caps = cap_get_proc(); if (caps != nullptr) { cap_clear(caps); + if (!capabilitiesToKeep.empty()) { + std::vector 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()); diff --git a/pdns/capabilities.hh b/pdns/capabilities.hh index e9499f5a8..4d0b0ded3 100644 --- a/pdns/capabilities.hh +++ b/pdns/capabilities.hh @@ -21,4 +21,6 @@ */ #pragma once -void dropCapabilities(); +#include + +void dropCapabilities(std::set capabilitiesToKeep = {}); diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 186f889b3..275e6859b 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -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 { diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index de8f284a4..ba9760548 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -144,6 +144,8 @@ bool g_fixupCase{false}; bool g_preserveTrailingData{false}; bool g_roundrobinFailOnNoServer{false}; +std::set 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()); diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index fa7349a19..6ccc3ae84 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -1233,6 +1233,8 @@ extern bool g_snmpTrapsEnabled; extern DNSDistSNMPAgent* g_snmpAgent; extern bool g_addEDNSToSelfGeneratedResponses; +extern std::set g_capabilitiesToRetain; + static const size_t s_udpIncomingBufferSize{1500}; enum class ProcessQueryResult { Drop, SendAnswer, PassToBackend };