From: Otto Moerbeek Date: Mon, 22 Jun 2020 08:11:39 +0000 (+0200) Subject: Control stack depth when priming. X-Git-Tag: dnsdist-1.5.0-rc4~16^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F9267%2Fhead;p=thirdparty%2Fpdns.git Control stack depth when priming. 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. --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index f99dd5af58..cd336817df 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -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); } } diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index ac95f95d3c..97ff66d4b7 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -22,7 +22,7 @@ ArgvMap& arg() return theArg; } -void primeRootNSZones(bool) +void primeRootNSZones(bool, unsigned int) { } diff --git a/pdns/reczones.cc b/pdns/reczones.cc index 5b65d12167..28716ac317 100644 --- a/pdns/reczones.cc +++ b/pdns/reczones.cc @@ -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 ret; - sr.beginResolve(qname, QType(QType::NS), QClass::IN, ret); + sr.beginResolve(qname, QType(QType::NS), QClass::IN, ret, depth + 1); } } diff --git a/pdns/syncres.cc b/pdns/syncres.cc index d66cbb8825..f69d73d860 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -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&ret) +int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&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 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< 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) diff --git a/pdns/syncres.hh b/pdns/syncres.hh index f4c791675f..fe2084be20 100644 --- a/pdns/syncres.hh +++ b/pdns/syncres.hh @@ -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&ret); + int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector&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;