bind/bind-9.18-CVE-2024-11187.patch
Petr Menšík 4b8cbe77ba Fix patches after rebase
zone.c was left broken. Fix it.

Resolves: RHEL-6454
2026-07-07 14:37:42 +02:00

173 lines
6.0 KiB
Diff

From 0f9d817ca87207f2695560645e12478477d345a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
Date: Thu, 14 Nov 2024 10:37:29 +0100
Subject: [PATCH] Limit the additional processing for large RDATA sets
When answering queries, don't add data to the additional section if
the answer has more than 13 names in the RDATA. This limits the
number of lookups into the database(s) during a single client query,
reducing query processing load.
Also, don't append any additional data to type=ANY queries. The
answer to ANY is already big enough.
(cherry picked from commit a1982cf1bb95c818aa7b58988b5611dec80f2408)
PatchNumber: 47
---
bin/tests/system/additional/tests.sh | 2 +-
lib/dns/include/dns/rdataset.h | 12 ++++++++++++
lib/dns/rbtdb.c | 2 +-
lib/dns/rdataset.c | 11 +++++++++++
lib/ns/query.c | 15 ++++++++++-----
5 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/bin/tests/system/additional/tests.sh b/bin/tests/system/additional/tests.sh
index 3701790..4281238 100644
--- a/bin/tests/system/additional/tests.sh
+++ b/bin/tests/system/additional/tests.sh
@@ -278,7 +278,7 @@ n=$(expr $n + 1)
echo_i "testing with 'minimal-any no;' ($n)"
ret=0
$DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 >dig.out.$n || ret=1
-grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 2" dig.out.$n >/dev/null || ret=1
+grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 1" dig.out.$n > /dev/null || ret=1
if [ $ret -eq 1 ]; then
echo_i "failed"
status=$((status + 1))
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
index de3f638..85c081e 100644
--- a/lib/dns/include/dns/rdataset.h
+++ b/lib/dns/include/dns/rdataset.h
@@ -55,6 +55,8 @@
#include <dns/rdatastruct.h>
#include <dns/types.h>
+#define DNS_RDATASET_MAXADDITIONAL 13
+
ISC_LANG_BEGINDECLS
typedef enum {
@@ -465,13 +467,23 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
*\li If a call to dns_rdata_additionaldata() is not successful, the
* result returned will be the result of dns_rdataset_additionaldata().
*
+ *\li If 'limit' is non-zero and the number of the rdatasets is larger
+ * than 'limit', no additional data will be processed.
+ *
* Returns:
*
*\li #ISC_R_SUCCESS
*
+ *\li #DNS_R_TOOMANYRECORDS in case rdataset count is larger than 'limit'
+ *
*\li Any error that dns_rdata_additionaldata() can return.
*/
+isc_result_t
+dns_rdataset_additionaldata2(dns_rdataset_t *rdataset,
+ dns_additionaldatafunc_t add, void *arg,
+ size_t limit);
+
isc_result_t
dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *neg, dns_rdataset_t *negsig);
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index c2cd63e..b1efa0b 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -10632,7 +10632,7 @@ no_glue:
maybe_rehash_gluetable(rbtversion);
idx = hash_32(hash, rbtversion->glue_table_bits);
- (void)dns_rdataset_additionaldata(rdataset, glue_nsdname_cb, &ctx);
+ (void)dns_rdataset_additionaldata2(rdataset, glue_nsdname_cb, &ctx, 0);
cur = isc_mem_get(rbtdb->common.mctx, sizeof(*cur));
diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
index 221d7f8..0f83d1f 100644
--- a/lib/dns/rdataset.c
+++ b/lib/dns/rdataset.c
@@ -29,6 +29,7 @@
#include <dns/ncache.h>
#include <dns/rdata.h>
#include <dns/rdataset.h>
+#include <dns/result.h>
static const char *trustnames[] = {
"none", "pending-additional",
@@ -579,6 +580,12 @@ dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
isc_result_t
dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
dns_additionaldatafunc_t add, void *arg) {
+ return dns_rdataset_additionaldata2(rdataset, add, arg, 0);
+}
+
+isc_result_t
+dns_rdataset_additionaldata2(dns_rdataset_t *rdataset,
+ dns_additionaldatafunc_t add, void *arg, size_t limit) {
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_result_t result;
@@ -590,6 +597,10 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
+ if (limit != 0 && dns_rdataset_count(rdataset) > limit) {
+ return DNS_R_TOOMANYRECORDS;
+ }
+
result = dns_rdataset_first(rdataset);
if (result != ISC_R_SUCCESS) {
return (result);
diff --git a/lib/ns/query.c b/lib/ns/query.c
index ec9bf5b..b31857c 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -2047,8 +2047,9 @@ addname:
* This cannot go more than MAX_RESTARTS levels deep.
*/
if (trdataset != NULL && dns_rdatatype_followadditional(type)) {
- eresult = dns_rdataset_additionaldata(
- trdataset, query_additional_cb, qctx);
+ eresult = dns_rdataset_additionaldata2(
+ trdataset, query_additional_cb, qctx,
+ DNS_RDATASET_MAXADDITIONAL);
}
cleanup:
@@ -2139,7 +2140,8 @@ regular:
* Add other additional data if needed.
* We don't care if dns_rdataset_additionaldata() fails.
*/
- (void)dns_rdataset_additionaldata(rdataset, query_additional_cb, qctx);
+ (void)dns_rdataset_additionaldata2(rdataset, query_additional_cb,
+ qctx, DNS_RDATASET_MAXADDITIONAL);
CTRACE(ISC_LOG_DEBUG(3), "query_additional: done");
}
@@ -2165,7 +2167,8 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
* To the current response for 'client', add the answer RRset
* '*rdatasetp' and an optional signature set '*sigrdatasetp', with
* owner name '*namep', to section 'section', unless they are
- * already there. Also add any pertinent additional data.
+ * already there. Also add any pertinent additional data, unless
+ * the query was for type ANY.
*
* If 'dbuf' is not NULL, then '*namep' is the name whose data is
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
@@ -2220,7 +2223,9 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
*/
query_addtoname(mname, rdataset);
query_setorder(qctx, mname, rdataset);
- query_additional(qctx, rdataset);
+ if (qctx->qtype != dns_rdatatype_any) {
+ query_additional(qctx, rdataset);
+ }
/*
* Note: we only add SIGs if we've added the type they cover, so
--
2.51.1