From e6ec15bfe4c391a51eab7c51c38307c7e009768f Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 13 Jul 2018 11:19:04 +0200 Subject: [PATCH] rec: Delay the creation of RPZ threads until we have dropped privileges On Linux/glibc, calling `set*id()` from a thread results in the other threads being sent the `SIGRT_1` signal so they are aware that they should switch credentials too, because `POSIX` requires that all threads use the same credentials but Linux actually handles it per thread. The reception of the signal interrupts the current `syscall` with `EINTR`, causing the loading of the `RPZ` zone to fail. --- pdns/pdns_recursor.cc | 8 ++-- pdns/rec-lua-conf.cc | 98 +++++++++++++++++++---------------------- pdns/rec-lua-conf.hh | 9 +++- pdns/rec_channel_rec.cc | 4 +- 4 files changed, 62 insertions(+), 57 deletions(-) diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index cefafcf40..5a0bc9386 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -3189,9 +3189,10 @@ static int serviceMain(int argc, char*argv[]) g_maxCacheEntries = ::arg().asNum("max-cache-entries"); g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries"); - + + luaConfigDelayedThreads delayedLuaThreads; try { - loadRecursorLuaConfig(::arg()["lua-config-file"], ::arg().mustDo("daemon")); + loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads); } catch (PDNSException &e) { g_log<, boost::optional, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, std::shared_ptr, std::string> > rpzMasterThreads; - auto luaconfsLocal = g_luaconfs.getLocal(); lci.generation = luaconfsLocal->generation + 1; @@ -139,7 +137,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) } }); - Lua.writeFunction("rpzMaster", [&lci, &rpzMasterThreads](const boost::variant > >& masters_, const string& zoneName, const boost::optional>>& options) { + Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant > >& masters_, const string& zoneName, const boost::optional>>& options) { boost::optional defpol; std::shared_ptr zone = std::make_shared(); @@ -249,7 +247,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) exit(1); // FIXME proper exit code? } - rpzMasterThreads.push_back(std::make_tuple(masters, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile)); + delayedThreads.rpzMasterThreads.push_back(std::make_tuple(masters, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile)); }); typedef vector > > > > argvec_t; @@ -316,31 +314,29 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) }); #if HAVE_PROTOBUF - Lua.writeFunction("protobufServer", [&lci, checkOnly](const string& server_, const boost::optional timeout, const boost::optional maxQueuedEntries, const boost::optional reconnectWaitTime, const boost::optional maskV4, boost::optional maskV6, boost::optional asyncConnect, boost::optional taggedOnly) { + Lua.writeFunction("protobufServer", [&lci](const string& server_, const boost::optional timeout, const boost::optional maxQueuedEntries, const boost::optional reconnectWaitTime, const boost::optional maskV4, boost::optional maskV6, boost::optional asyncConnect, boost::optional taggedOnly) { try { ComboAddress server(server_); if (!lci.protobufExportConfig.enabled) { lci.protobufExportConfig.enabled = true; - if (!checkOnly) { - lci.protobufExportConfig.server = server; + lci.protobufExportConfig.server = server; - if (timeout) { - lci.protobufExportConfig.timeout = *timeout; - } + if (timeout) { + lci.protobufExportConfig.timeout = *timeout; + } - if (maxQueuedEntries) { - lci.protobufExportConfig.maxQueuedEntries = *maxQueuedEntries; - } + if (maxQueuedEntries) { + lci.protobufExportConfig.maxQueuedEntries = *maxQueuedEntries; + } - if (reconnectWaitTime) { - lci.protobufExportConfig.reconnectWaitTime = *reconnectWaitTime; - } + if (reconnectWaitTime) { + lci.protobufExportConfig.reconnectWaitTime = *reconnectWaitTime; + } - if (asyncConnect) { - lci.protobufExportConfig.asyncConnect = *asyncConnect; - } + if (asyncConnect) { + lci.protobufExportConfig.asyncConnect = *asyncConnect; } if (maskV4) { @@ -365,31 +361,29 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) } }); - Lua.writeFunction("outgoingProtobufServer", [&lci, checkOnly](const string& server_, const boost::optional timeout, const boost::optional maxQueuedEntries, const boost::optional reconnectWaitTime, boost::optional asyncConnect) { + Lua.writeFunction("outgoingProtobufServer", [&lci](const string& server_, const boost::optional timeout, const boost::optional maxQueuedEntries, const boost::optional reconnectWaitTime, boost::optional asyncConnect) { try { ComboAddress server(server_); if (!lci.outgoingProtobufExportConfig.enabled) { lci.outgoingProtobufExportConfig.enabled = true; - if (!checkOnly) { - lci.outgoingProtobufExportConfig.server = server; + lci.outgoingProtobufExportConfig.server = server; - if (timeout) { - lci.outgoingProtobufExportConfig.timeout = *timeout; - } + if (timeout) { + lci.outgoingProtobufExportConfig.timeout = *timeout; + } - if (maxQueuedEntries) { - lci.outgoingProtobufExportConfig.maxQueuedEntries = *maxQueuedEntries; - } + if (maxQueuedEntries) { + lci.outgoingProtobufExportConfig.maxQueuedEntries = *maxQueuedEntries; + } - if (reconnectWaitTime) { - lci.outgoingProtobufExportConfig.reconnectWaitTime = *reconnectWaitTime; - } + if (reconnectWaitTime) { + lci.outgoingProtobufExportConfig.reconnectWaitTime = *reconnectWaitTime; + } - if (asyncConnect) { - lci.outgoingProtobufExportConfig.asyncConnect = *asyncConnect; - } + if (asyncConnect) { + lci.outgoingProtobufExportConfig.asyncConnect = *asyncConnect; } } else { @@ -408,23 +402,6 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) try { Lua.executeCode(ifs); g_luaconfs.setState(lci); - - if (!checkOnly) { - for (const auto& rpzMaster : rpzMasterThreads) { - try { - std::thread t(RPZIXFRTracker, std::get<0>(rpzMaster), std::get<1>(rpzMaster), std::get<2>(rpzMaster), std::get<3>(rpzMaster), std::get<4>(rpzMaster), std::get<5>(rpzMaster) * 1024 * 1024, std::get<6>(rpzMaster), std::get<7>(rpzMaster), std::get<8>(rpzMaster), std::get<9>(rpzMaster), lci.generation); - t.detach(); - } - catch(const std::exception& e) { - g_log<(rpzMaster), std::get<1>(rpzMaster), std::get<2>(rpzMaster), std::get<3>(rpzMaster), std::get<4>(rpzMaster), std::get<5>(rpzMaster) * 1024 * 1024, std::get<6>(rpzMaster), std::get<7>(rpzMaster), std::get<8>(rpzMaster), std::get<9>(rpzMaster), generation); + t.detach(); + } + catch(const std::exception& e) { + g_log< g_luaconfs; -void loadRecursorLuaConfig(const std::string& fname, bool checkOnly); + +struct luaConfigDelayedThreads +{ + std::vector, boost::optional, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, std::shared_ptr, std::string> > rpzMasterThreads; +}; + +void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads); +void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation); diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index c46d62da8..ad3cfdfdf 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -1332,7 +1332,9 @@ string RecursorControlParser::getAnswer(const string& question, RecursorControlP ::arg().set("lua-config-file") = *begin; try { - loadRecursorLuaConfig(::arg()["lua-config-file"], false); + luaConfigDelayedThreads delayedLuaThreads; + loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads); + startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation); g_log<