4ba560
From bf2ea6d8525bfd96a84dad221ba9e004adb710a8 Mon Sep 17 00:00:00 2001
4ba560
From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <michal@isc.org>
4ba560
Date: Thu, 8 Sep 2022 11:11:30 +0200
4ba560
Subject: [PATCH] Bound the amount of work performed for delegations
4ba560
4ba560
Limit the amount of database lookups that can be triggered in
4ba560
fctx_getaddresses() (i.e. when determining the name server addresses to
4ba560
query next) by setting a hard limit on the number of NS RRs processed
4ba560
for any delegation encountered.  Without any limit in place, named can
4ba560
be forced to perform large amounts of database lookups per each query
4ba560
received, which severely impacts resolver performance.
4ba560
4ba560
The limit used (20) is an arbitrary value that is considered to be big
4ba560
enough for any sane DNS delegation.
4ba560
4ba560
(cherry picked from commit 3a44097fd6c6c260765b628cd1d2c9cb7efb0b2a)
4ba560
---
4ba560
 lib/dns/resolver.c | 12 ++++++++++++
4ba560
 1 file changed, 12 insertions(+)
4ba560
4ba560
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
4ba560
index d2cf14bbc8..73a0ee9f77 100644
4ba560
--- a/lib/dns/resolver.c
4ba560
+++ b/lib/dns/resolver.c
4ba560
@@ -195,6 +195,12 @@
4ba560
  */
4ba560
 #define NS_FAIL_LIMIT 4
4ba560
 #define NS_RR_LIMIT   5
4ba560
+/*
4ba560
+ * IP address lookups are performed for at most NS_PROCESSING_LIMIT NS RRs in
4ba560
+ * any NS RRset encountered, to avoid excessive resource use while processing
4ba560
+ * large delegations.
4ba560
+ */
4ba560
+#define NS_PROCESSING_LIMIT 20
4ba560
 
4ba560
 /* Number of hash buckets for zone counters */
4ba560
 #ifndef RES_DOMAIN_BUCKETS
4ba560
@@ -3711,6 +3717,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
4ba560
 	bool need_alternate = false;
4ba560
 	bool all_spilled = true;
4ba560
 	unsigned int no_addresses = 0;
4ba560
+	unsigned int ns_processed = 0;
4ba560
 
4ba560
 	FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
4ba560
 
4ba560
@@ -3902,6 +3909,11 @@ normal_nses:
4ba560
 
4ba560
 		dns_rdata_reset(&rdata);
4ba560
 		dns_rdata_freestruct(&ns);
4ba560
+
4ba560
+		if (++ns_processed >= NS_PROCESSING_LIMIT) {
4ba560
+			result = ISC_R_NOMORE;
4ba560
+			break;
4ba560
+		}
4ba560
 	}
4ba560
 	if (result != ISC_R_NOMORE) {
4ba560
 		return (result);
4ba560
-- 
4ba560
2.37.3
4ba560