From 31d0cfaeda4a72ae7809950d2dc872bf267005de 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. (cherry picked from commit e6ec15bfe4c391a51eab7c51c38307c7e009768f) --- pdns/pdns_recursor.cc | 8 +++--- pdns/rec-lua-conf.cc | 54 ++++++++++++++++++----------------------- pdns/rec-lua-conf.hh | 9 ++++++- pdns/rec_channel_rec.cc | 4 ++- 4 files changed, 40 insertions(+), 35 deletions(-) diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 30449b33a7..43601c2f3f 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -2960,9 +2960,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) { L<, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t> > rpzMasterThreads; - auto luaconfsLocal = g_luaconfs.getLocal(); // pdnslog here is compatible with pdnslog in lua-base4.cc. @@ -153,7 +151,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) } }); - Lua.writeFunction("rpzMaster", [&lci, &rpzMasterThreads, checkOnly](const string& master_, const string& zoneName, const boost::optional>>& options) { + Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const string& master_, const string& zoneName, const boost::optional>>& options) { boost::optional defpol; std::shared_ptr zone = std::make_shared(); @@ -213,7 +211,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) exit(1); // FIXME proper exit code? } - rpzMasterThreads.push_back(std::make_tuple(master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout)); + delayedThreads.rpzMasterThreads.push_back(std::make_tuple(master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout)); }); typedef vector > > > > argvec_t; @@ -280,13 +278,11 @@ 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.protobufServer) { - if (!checkOnly) { - lci.protobufServer = std::make_shared(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false); - } + lci.protobufServer = std::make_shared(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false); if (maskV4) { lci.protobufMaskV4 = *maskV4; @@ -310,13 +306,11 @@ 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.outgoingProtobufServer) { - if (!checkOnly) { - lci.outgoingProtobufServer = std::make_shared(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false); - } + lci.outgoingProtobufServer = std::make_shared(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false); } else { theL()<toString()<(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)); - t.detach(); - } - catch(const std::exception& e) { - L<(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)); + t.detach(); + } + catch(const std::exception& e) { + L< g_luaconfs; -void loadRecursorLuaConfig(const std::string& fname, bool checkOnly); + +struct luaConfigDelayedThreads +{ + std::vector, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t> > rpzMasterThreads; +}; + +void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads); +void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads); diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index 17dddd0ee9..177b0863a4 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -1304,7 +1304,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); L<