Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:GA
bind
bind-9.11-CVE-2024-1737.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bind-9.11-CVE-2024-1737.patch of Package bind
commit be06e6215cb2a2891d0035e296a7ec1cda66ce8f Author: Nicki Křížek <nicki@isc.org> Date: Wed Jul 24 08:55:54 2024 +0000 [9.11] [CVE-2024-1737] Previously, the number of RRs in the RRSets were internally unlimited. As the data structure that holds the RRs is just a linked list, and there are places where we just walk through all of the RRs, adding an RRSet with huge number of RRs inside would slow down processing of said RRSets. The fix for end-of-life branches make the limit compile-time only for simplicity and the limit can be changed at the compile time by adding following define to CFLAGS: -DDNS_RDATASET_MAX_RECORDS=<limit> Backport of https://gitlab.isc.org/isc-private/bind9/-/merge_requests/698 See isc-projects/bind9#3405 Merge branch '3405-limit-the-number-of-resource-records-in-rrset-9.11' into 'bind-9.11' See merge request isc-projects/bind9!9169 [9.11][CVE-2024-1737 (part 2)] Be smarter about refusing to add many RR types to the database Add HTTPS, SVCB, SRV, PTR, NAPTR, DNSKEY and TXT records to the list of the priority types that are put at the beginning of the slabheader list for faster access and to avoid eviction when there are more types than the max-types-per-name limit. (cherry picked from commit b27c6bcce894786a8e082eafd59eccbf6f2731cb) --- Backport of MR https://gitlab.isc.org/isc-private/bind9/-/merge_requests/712 Related https://gitlab.isc.org/isc-projects/bind9/-/issues/3405 Merge branch '3405-limit-the-number-of-resource-records-in-rrset-nxdomain-9.11' into 'bind-9.11' See merge request isc-projects/bind9!9171 diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 51ea530ebe..5a6513aea3 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1765,15 +1765,17 @@ awk '/IN *SOA/ {if (NF != 7) exit(1)}' signer/signer.out.4 || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` -echo_i "checking TTLs are capped by dnssec-signzone -M ($n)" -ret=0 -( -cd signer -$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null 2>&1 -) || ret=1 -awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1 -if [ $ret != 0 ]; then echo_i "failed"; fi -status=`expr $status + $ret` +# Skip test because it doesn't work with the maximum records of 100 for CVE-2024-1737 +# bsc#1229002 +#echo_i "checking TTLs are capped by dnssec-signzone -M ($n)" +#ret=0 +#( +#cd signer +#$SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db > /dev/null 2>&1 +#) || ret=1 +#awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1 +#if [ $ret != 0 ]; then echo_i "failed"; fi +#status=`expr $status + $ret` echo_i "checking dnssec-signzone -N date ($n)" ret=0 diff --git a/bin/tests/system/limits/prereq.sh b/bin/tests/system/limits/prereq.sh new file mode 100644 index 0000000000..3ae82b8191 --- /dev/null +++ b/bin/tests/system/limits/prereq.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +# Skip test because it doesn't work with the maximum records of 100 for CVE-2024-1737 +# bsc#1229002 +exit 255 diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh index 6383fbddb1..17ec4a3102 100755 --- a/bin/tests/system/masterformat/tests.sh +++ b/bin/tests/system/masterformat/tests.sh @@ -183,21 +183,23 @@ n=$((n+1)) [ $ret -eq 0 ] || echo_i "failed" status=$((status+ret)) -echo_i "checking that large rdatasets loaded ($n)" -for i in 0 1 2 3 4 5 6 7 8 9 -do -ret=0 -for a in a b c -do - $DIG +tcp txt "${a}.large" @10.53.0.2 -p "${PORT}" > "dig.out.ns2.test$n" - grep "status: NOERROR" "dig.out.ns2.test$n" > /dev/null || ret=1 -done -[ $ret -eq 0 ] && break -sleep 1 -done -n=$((n+1)) -[ $ret -eq 0 ] || echo_i "failed" -status=$((status+ret)) +# Skip test because it doesn't work with the maximum records of 100 for CVE-2024-1737 +# bsc#1229002 +#echo_i "checking that large rdatasets loaded ($n)" +#for i in 0 1 2 3 4 5 6 7 8 9 +#do +#ret=0 +#for a in a b c +#do +# $DIG +tcp txt "${a}.large" @10.53.0.2 -p "${PORT}" > "dig.out.ns2.test$n" +# grep "status: NOERROR" "dig.out.ns2.test$n" > /dev/null || ret=1 +#done +#[ $ret -eq 0 ] && break +#sleep 1 +#done +#n=$((n+1)) +#[ $ret -eq 0 ] || echo_i "failed" +#status=$((status+ret)) echo_i "checking format transitions: text->raw->map->text ($n)" ret=0 diff --git a/configure b/configure index 887787faef..dac8cfe03b 100755 --- a/configure +++ b/configure @@ -12169,7 +12169,7 @@ fi XTARGETS= case "$enable_developer" in yes) - STD_CDEFINES="$STD_CDEFINES -DISC_LIST_CHECKINIT=1" + STD_CDEFINES="$STD_CDEFINES -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 "${enable_filter_aaaa+set}" = set || enable_filter_aaaa=yes diff --git a/configure.ac b/configure.ac index 33bd76ac3b..f42b4f8fd0 100644 --- a/configure.ac +++ b/configure.ac @@ -94,7 +94,7 @@ AC_ARG_ENABLE(developer, XTARGETS= case "$enable_developer" in yes) - STD_CDEFINES="$STD_CDEFINES -DISC_LIST_CHECKINIT=1" + STD_CDEFINES="$STD_CDEFINES -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 "${enable_filter_aaaa+set}" = set || enable_filter_aaaa=yes diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 7a622103a7..55ad7fa946 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -1127,6 +1127,44 @@ set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) { isc_heap_decreased(heap, header->heap_index); } +static bool +prio_type(rbtdb_rdatatype_t type) { + switch (type) { + case dns_rdatatype_soa: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_soa): + case dns_rdatatype_a: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_a): + case dns_rdatatype_mx: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_mx): + case dns_rdatatype_aaaa: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_aaaa): + case dns_rdatatype_nsec: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec): + case dns_rdatatype_nsec3: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec3): + case dns_rdatatype_ns: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns): + case dns_rdatatype_ds: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ds): + case dns_rdatatype_cname: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname): + case dns_rdatatype_dname: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname): + case dns_rdatatype_dnskey: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dnskey): + case dns_rdatatype_srv: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_srv): + case dns_rdatatype_txt: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_txt): + case dns_rdatatype_ptr: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ptr): + case dns_rdatatype_naptr: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_naptr): + return (true); + } + return (false); +} + /*% * These functions allow the heap code to rank the priority of each * element. It returns true if v1 happens "sooner" than v2. @@ -6127,6 +6165,30 @@ update_recordsandbytes(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 */ + +static bool +overmaxtype(dns_rbtdb_t *rbtdb, uint32_t ntypes) { + UNUSED(rbtdb); + + if (DNS_RBTDB_MAX_RTYPES == 0) { + return (false); + } + + return (ntypes >= DNS_RBTDB_MAX_RTYPES); +} + +static bool +prio_header(rdatasetheader_t *header) { + if (NEGATIVE(header) && prio_type(RBTDB_RDATATYPE_EXT(header->type))) { + return (true); + } + + return (prio_type(header->type)); +} + /* * write lock on rbtnode must be held. */ @@ -6137,6 +6199,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, { rbtdb_changed_t *changed = NULL; rdatasetheader_t *topheader, *topheader_prev, *header, *sigheader; + rdatasetheader_t *prioheader = NULL, *expireheader = NULL; unsigned char *merged; isc_result_t result; bool header_nx; @@ -6146,6 +6209,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, rbtdb_rdatatype_t negtype, sigtype; dns_trust_t trust; int idx; + uint32_t ntypes = 0; /* * Add an rdatasetheader_t to a node. @@ -6278,6 +6342,15 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, for (topheader = rbtnode->data; topheader != NULL; topheader = topheader->next) { + if (IS_CACHE(rbtdb) && ACTIVE(topheader, now)) { + ++ntypes; + expireheader = topheader; + } else if (!IS_CACHE(rbtdb)) { + ++ntypes; + } + if (prio_header(topheader)) { + prioheader = topheader; + } if (topheader->type == newheader->type || topheader->type == negtype) break; @@ -6633,9 +6706,46 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, /* * No rdatasets of the given type exist at the node. */ - newheader->next = rbtnode->data; + if (!IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) { + free_rdataset(rbtdb, rbtdb->common.mctx, + newheader); + return (ISC_R_QUOTA); + } + newheader->down = NULL; - rbtnode->data = newheader; + + if (prio_header(newheader)) { + /* This is a priority type, prepend it */ + newheader->next = rbtnode->data; + rbtnode->data = newheader; + } else if (prioheader != NULL) { + /* Append after the priority headers */ + newheader->next = prioheader->next; + prioheader->next = newheader; + } else { + /* There were no priority headers */ + newheader->next = rbtnode->data; + rbtnode->data = newheader; + } + + if (IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) { + if (expireheader == NULL) { + expireheader = newheader; + } + if (NEGATIVE(newheader) && + !prio_header(newheader)) + { + /* + * Add the new non-priority negative + * header to the database only + * temporarily. + */ + expireheader = newheader; + } + + set_ttl(rbtdb, expireheader, 0); + mark_stale_header(rbtdb, expireheader); + } } } diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 7cd3855d77..22fe63e063 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -115,6 +115,10 @@ fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable, } #endif +#ifndef DNS_RDATASET_MAX_RECORDS +#define DNS_RDATASET_MAX_RECORDS 100 +#endif /* DNS_RDATASET_MAX_RECORDS */ + isc_result_t dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region, unsigned int reservelen) @@ -161,6 +165,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, return (ISC_R_SUCCESS); } + if (nitems > DNS_RDATASET_MAX_RECORDS) { + return (DNS_R_TOOMANYRECORDS); + } + if (nitems > 0xffff) return (ISC_R_NOSPACE); @@ -654,6 +662,10 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, #endif INSIST(ocount > 0 && ncount > 0); + if (ocount + ncount > DNS_RDATASET_MAX_RECORDS) { + return (DNS_R_TOOMANYRECORDS); + } + #if DNS_RDATASET_FIXED oncount = ncount; #endif
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor