]> granicus.if.org Git - pdns/commitdiff
rec: Delay the creation of RPZ threads until we have dropped privileges
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 13 Jul 2018 09:19:04 +0000 (11:19 +0200)
committerPeter van Dijk <peter.van.dijk@powerdns.com>
Fri, 21 Sep 2018 18:20:42 +0000 (20:20 +0200)
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
pdns/rec-lua-conf.cc
pdns/rec-lua-conf.hh
pdns/rec_channel_rec.cc

index 30449b33a7f8200f6b321821d1dbb40354b16402..43601c2f3f30c2394164f1a96429519a371650c2 100644 (file)
@@ -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<<Logger::Error<<"Cannot load Lua configuration: "<<e.reason<<endl;
@@ -3126,7 +3127,6 @@ static int serviceMain(int argc, char*argv[])
     L<<Logger::Warning<<"Calling daemonize, going to background"<<endl;
     L.toConsole(Logger::Critical);
     daemonize();
-    loadRecursorLuaConfig(::arg()["lua-config-file"], false);
   }
   signal(SIGUSR1,usr1Handler);
   signal(SIGUSR2,usr2Handler);
@@ -3179,6 +3179,8 @@ static int serviceMain(int argc, char*argv[])
 
   Utility::dropUserPrivs(newuid);
 
+  startLuaConfigDelayedThreads(delayedLuaThreads);
+
   makeThreadPipes();
 
   g_tcpTimeout=::arg().asNum("client-tcp-timeout");
index d25f0e9878943fca443716a953f5dddbfecf131f..c48eddd9f2830d50ba6df8195d7f293baa91df55 100644 (file)
@@ -81,7 +81,7 @@ static void parseRPZParameters(const std::unordered_map<string,boost::variant<ui
   }
 }
 
-void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
+void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads)
 {
   LuaConfigItems lci;
 
@@ -92,8 +92,6 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
   if(!ifs)
     throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno));
 
-  std::vector<std::tuple<ComboAddress, boost::optional<DNSFilterEngine::Policy>, 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<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) {
+  Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const string& master_, const string& zoneName, const boost::optional<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) {
 
       boost::optional<DNSFilterEngine::Policy> defpol;
       std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
@@ -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<pair<int,boost::variant<string, vector<pair<int, string> > > > > 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<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, const boost::optional<uint8_t> maskV4, boost::optional<uint8_t> maskV6, boost::optional<bool> asyncConnect, boost::optional<bool> taggedOnly) {
+  Lua.writeFunction("protobufServer", [&lci](const string& server_, const boost::optional<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, const boost::optional<uint8_t> maskV4, boost::optional<uint8_t> maskV6, boost::optional<bool> asyncConnect, boost::optional<bool> taggedOnly) {
       try {
        ComboAddress server(server_);
         if (!lci.protobufServer) {
-          if (!checkOnly) {
-            lci.protobufServer = std::make_shared<RemoteLogger>(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false);
-          }
+          lci.protobufServer = std::make_shared<RemoteLogger>(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<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, boost::optional<bool> asyncConnect) {
+  Lua.writeFunction("outgoingProtobufServer", [&lci](const string& server_, const boost::optional<uint16_t> timeout, const boost::optional<uint64_t> maxQueuedEntries, const boost::optional<uint8_t> reconnectWaitTime, boost::optional<bool> asyncConnect) {
       try {
        ComboAddress server(server_);
         if (!lci.outgoingProtobufServer) {
-          if (!checkOnly) {
-            lci.outgoingProtobufServer = std::make_shared<RemoteLogger>(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false);
-          }
+          lci.outgoingProtobufServer = std::make_shared<RemoteLogger>(server, timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1, asyncConnect ? *asyncConnect : false);
         }
         else {
           theL()<<Logger::Error<<"Only one protobuf server can be configured, we already have "<<lci.protobufServer->toString()<<endl;
@@ -334,23 +328,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));
-          t.detach();
-        }
-        catch(const std::exception& e) {
-          L<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.what()<<endl;
-          exit(1);  // FIXME proper exit code?
-        }
-        catch(const PDNSException& e) {
-          L<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.reason<<endl;
-          exit(1);  // FIXME proper exit code?
-        }
-      }
-    }
   }
   catch(const LuaContext::ExecutionErrorException& e) {
     theL()<<Logger::Error<<"Unable to load Lua script from '"+fname+"': ";
@@ -374,3 +351,20 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly)
 
 }
 
+void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads)
+{
+  for (const auto& rpzMaster : delayedThreads.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));
+      t.detach();
+    }
+    catch(const std::exception& e) {
+      L<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.what()<<endl;
+      exit(1);  // FIXME proper exit code?
+    }
+    catch(const PDNSException& e) {
+      L<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.reason<<endl;
+      exit(1);  // FIXME proper exit code?
+    }
+  }
+}
index 62d83b0bf698fd87fe469247db64f9a05e796a45..6bf2ccdeab68f20afb1227c033f47671f2a3f7d6 100644 (file)
@@ -42,5 +42,12 @@ public:
 };
 
 extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
-void loadRecursorLuaConfig(const std::string& fname, bool checkOnly);
+
+struct luaConfigDelayedThreads
+{
+  std::vector<std::tuple<ComboAddress, boost::optional<DNSFilterEngine::Policy>, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t> > rpzMasterThreads;
+};
+
+void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads);
+void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads);
 
index 17dddd0ee9d832d11ec5e0d4ce7ac6db347e6aca..177b0863a497073b1c25ce5116b18997fab69e5d 100644 (file)
@@ -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<<Logger::Warning<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl;
       return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
     }