Package: bind9 / 1:9.16.50-1~deb11u2

0006-Add-a-limit-to-the-number-of-RR-types-for-single-nam.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
From: =?utf-8?b?T25kxZllaiBTdXLDvQ==?= <ondrej@isc.org>
Date: Wed, 29 May 2024 08:43:39 +0200
Subject: Add a limit to the number of RR types for single name

Previously, the number of RR types for a single owner name was limited
only by the maximum number of the types (64k).  As the data structure
that holds the RR types for the database node is just a linked list, and
there are places where we just walk through the whole list (again and
again), adding a large number of RR types for a single owner named with
would slow down processing of such name (database node).

Add a hard-coded limit (100) to cap the number of the RR types for a single
owner.  The limit can be changed at the compile time by adding following
define to CFLAGS:

    -DDNS_RBTDB_MAX_RTYPES=<limit>
---
 configure       |  2 +-
 configure.ac    |  2 +-
 lib/dns/rbtdb.c | 17 +++++++++++++++++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 30e65f1..835cd94 100755
--- a/configure
+++ b/configure
@@ -12341,7 +12341,7 @@ fi
 
 XTARGETS=
 if test "$enable_developer" = "yes"; then :
-  STD_CDEFINES="$STD_CDEFINES -DISC_MEM_DEFAULTFILL=1 -DISC_LIST_CHECKINIT=1 -DDNS_RDATASET_MAX_RECORDS=5000"
+  STD_CDEFINES="$STD_CDEFINES -DISC_MEM_DEFAULTFILL=1 -DISC_LIST_CHECKINIT=1 -DDNS_RDATASET_MAX_RECORDS=5000 -DDNS_RBTDB_MAX_RTYPES=5000"
        test "${enable_fixed_rrset+set}" = set || enable_fixed_rrset=yes
        test "${enable_querytrace+set}" = set || enable_querytrace=yes
        test "${with_cmocka+set}" = set || with_cmocka=yes
diff --git a/configure.ac b/configure.ac
index ffe087e..6db4250 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,7 +96,7 @@ AC_ARG_ENABLE([developer],
 
 XTARGETS=
 AS_IF([test "$enable_developer" = "yes"],
-      [STD_CDEFINES="$STD_CDEFINES -DISC_MEM_DEFAULTFILL=1 -DISC_LIST_CHECKINIT=1 -DDNS_RDATASET_MAX_RECORDS=5000"
+      [STD_CDEFINES="$STD_CDEFINES -DISC_MEM_DEFAULTFILL=1 -DISC_LIST_CHECKINIT=1 -DDNS_RDATASET_MAX_RECORDS=5000 -DDNS_RBTDB_MAX_RTYPES=5000"
        test "${enable_fixed_rrset+set}" = set || enable_fixed_rrset=yes
        test "${enable_querytrace+set}" = set || enable_querytrace=yes
        test "${with_cmocka+set}" = set || with_cmocka=yes
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 3f06545..b35e101 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -6240,6 +6240,10 @@ update_recordsandxfrsize(bool add, rbtdb_version_t *rbtversion,
 	RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
 }
 
+#ifndef DNS_RBTDB_MAX_RTYPES
+#define DNS_RBTDB_MAX_RTYPES 100
+#endif /* DNS_RBTDB_MAX_RTYPES */
+
 /*
  * write lock on rbtnode must be held.
  */
@@ -6261,6 +6265,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
 	rbtdb_rdatatype_t negtype, sigtype;
 	dns_trust_t trust;
 	int idx;
+	uint32_t ntypes;
 
 	/*
 	 * Add an rdatasetheader_t to a node.
@@ -6325,6 +6330,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
 					set_ttl(rbtdb, topheader, 0);
 					mark_header_ancient(rbtdb, topheader);
 				}
+				ntypes = 0;
 				goto find_header;
 			}
 			/*
@@ -6348,9 +6354,11 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
 			 * check for an extant non-ancient NODATA ncache
 			 * entry which covers the same type as the RRSIG.
 			 */
+			ntypes = 0;
 			for (topheader = rbtnode->data; topheader != NULL;
 			     topheader = topheader->next)
 			{
+				ntypes++;
 				if ((topheader->type ==
 				     RBTDB_RDATATYPE_NCACHEANY) ||
 				    (newheader->type == sigtype &&
@@ -6395,9 +6403,11 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
 		}
 	}
 
+	ntypes = 0;
 	for (topheader = rbtnode->data; topheader != NULL;
 	     topheader = topheader->next)
 	{
+		ntypes++;
 		if (prio_type(topheader->type)) {
 			prioheader = topheader;
 		}
@@ -6755,6 +6765,13 @@ find_header:
 			/*
 			 * No rdatasets of the given type exist at the node.
 			 */
+
+			if (ntypes > DNS_RBTDB_MAX_RTYPES) {
+				free_rdataset(rbtdb, rbtdb->common.mctx,
+					      newheader);
+				return (ISC_R_QUOTA);
+			}
+
 			newheader->down = NULL;
 
 			if (prio_type(newheader->type)) {