]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Control stack depth when priming. 9267/head
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 22 Jun 2020 08:11:39 +0000 (10:11 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 22 Jun 2020 08:11:39 +0000 (10:11 +0200)
If you clear the cache for . in a tight loop, the priming code gets
called recursively in an unbounded fashion. This keeps track of the
stack depth and ServFails if needed.

pdns/pdns_recursor.cc
pdns/recursordist/test-syncres_cc.cc
pdns/reczones.cc
pdns/syncres.cc
pdns/syncres.hh

index f99dd5af58d0d5fa164ffa52292a70dee088e2f5..cd336817df5128cb7af4d0fae62b1445e00d386f 100644 (file)
@@ -3183,11 +3183,11 @@ static void houseKeeping(void *)
         last_RC_prune = now.tv_sec;
       }
       // XXX !!! global
-      if(now.tv_sec - last_rootupdate > 7200) {
-        int res = SyncRes::getRootNS(g_now, nullptr);
+      if (now.tv_sec - last_rootupdate > 7200) {
+        int res = SyncRes::getRootNS(g_now, nullptr, 0);
         if (!res) {
           last_rootupdate=now.tv_sec;
-          primeRootNSZones(g_dnssecmode != DNSSECMode::Off);
+          primeRootNSZones(g_dnssecmode != DNSSECMode::Off, 0);
         }
       }
 
index ac95f95d3cf9250e2579c7fa1f735cca643b9b92..97ff66d4b7617b73bdcd1bb858e75db71e92333e 100644 (file)
@@ -22,7 +22,7 @@ ArgvMap& arg()
   return theArg;
 }
 
-void primeRootNSZones(bool)
+void primeRootNSZones(bool, unsigned int)
 {
 }
 
index 5b65d121673f9c7fd07e3300588bf3c6221854ef..28716ac31768c4ebf0d1bdcf6db2861f5ce213f1 100644 (file)
@@ -115,7 +115,7 @@ void primeHints(void)
 // servers are authoritative for root-servers.net, and some
 // implementations reply not with a delegation on a root-servers.net
 // DS query, but with a NODATA response (the domain is unsigned).
-void primeRootNSZones(bool dnssecmode)
+void primeRootNSZones(bool dnssecmode, unsigned int depth)
 {
   struct timeval now;
   gettimeofday(&now, 0);
@@ -132,7 +132,7 @@ void primeRootNSZones(bool dnssecmode)
   for (const auto & qname: copy) {
     s_RC->doWipeCache(qname, false, QType::NS);
     vector<DNSRecord> ret;
-    sr.beginResolve(qname, QType(QType::NS), QClass::IN, ret);
+    sr.beginResolve(qname, QType(QType::NS), QClass::IN, ret, depth + 1);
   }
 }
 
index d66cbb882502e267b295509697a238708ee653fd..f69d73d8605c7a8387d3f21b871c31df7b4b297e 100644 (file)
@@ -131,7 +131,7 @@ SyncRes::SyncRes(const struct timeval& now) :  d_authzonequeries(0), d_outquerie
 }
 
 /** everything begins here - this is the entry point just after receiving a packet */
-int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
+int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret, unsigned int depth)
 {
   vState state = Indeterminate;
   s_queries++;
@@ -155,7 +155,7 @@ int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qcl
     return -1;
 
   set<GetBestNSAnswer> beenthere;
-  int res=doResolve(qname, qtype, ret, 0, beenthere, state);
+  int res=doResolve(qname, qtype, ret, depth, beenthere, state);
   d_queryValidationState = state;
 
   if (shouldValidate()) {
@@ -1101,11 +1101,11 @@ void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vecto
     if(subdomain.isRoot() && !brokeloop) {
       // We lost the root NS records
       primeHints();
-      primeRootNSZones(g_dnssecmode != DNSSECMode::Off);
+      primeRootNSZones(g_dnssecmode != DNSSECMode::Off, depth);
       LOG(prefix<<qname<<": reprimed the root"<<endl);
       /* let's prevent an infinite loop */
       if (!d_updatingRootNS) {
-        getRootNS(d_now, d_asyncResolve);
+        getRootNS(d_now, d_asyncResolve, depth);
       }
     }
   } while(subdomain.chopOff());
@@ -3750,7 +3750,7 @@ int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<D
   SyncRes sr(now);
   int res = -1;
   try {
-    res = sr.beginResolve(qname, QType(qtype), qclass, ret);
+    res = sr.beginResolve(qname, QType(qtype), qclass, ret, 0);
   }
   catch(const PDNSException& e) {
     g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got pdns exception: "<<e.reason<<endl;
@@ -3776,7 +3776,7 @@ int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<D
   return res;
 }
 
-int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
+int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth) {
   SyncRes sr(now);
   sr.setDoEDNS0(true);
   sr.setUpdatingRootNS();
@@ -3787,7 +3787,7 @@ int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
   vector<DNSRecord> ret;
   int res=-1;
   try {
-    res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
+    res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret, depth + 1);
     if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
       auto state = sr.getValidationState();
       if (state == Bogus)
index f4c791675f9acd1a380cc7b16089aa61f14cfc99..fe2084be20975c267dbbf73d79d73a805ff37f01 100644 (file)
@@ -416,7 +416,7 @@ public:
   static uint64_t doDumpNSSpeeds(int fd);
   static uint64_t doDumpThrottleMap(int fd);
   static uint64_t doDumpFailedServers(int fd);
-  static int getRootNS(struct timeval now, asyncresolve_t asyncCallback);
+  static int getRootNS(struct timeval now, asyncresolve_t asyncCallback, unsigned int depth);
   static void clearDelegationOnly()
   {
     s_delegationOnly.clear();
@@ -604,7 +604,8 @@ public:
 
   explicit SyncRes(const struct timeval& now);
 
-  int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret);
+  int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret, unsigned int depth = 0);
+
   void setId(int id)
   {
     if(doLog())
@@ -1113,7 +1114,7 @@ uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qty
 uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree=false);
 void doCarbonDump(void*);
 void primeHints(void);
-void primeRootNSZones(bool);
+void primeRootNSZones(bool, unsigned int depth);
 
 extern __thread struct timeval g_now;