Add security fixes from c9/bind

This commit is contained in:
Andrew Lukoshko 2024-04-12 17:03:30 +00:00
parent 3b6f9d9991
commit 67be908a61
12 changed files with 3045 additions and 1 deletions

View File

@ -0,0 +1,88 @@
From d258422d3e653621ce6340ba9af0153f8d4e8c07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
Date: Sun, 11 Feb 2024 00:49:32 +0100
Subject: [PATCH] Test case insensitive matching in isc_ht hash table
implementation
The case insensitive matching in isc_ht was basically completely broken
as only the hashvalue computation was case insensitive, but the key
comparison was always case sensitive.
Import only test part from upstream.
(cherry picked from commit 175655b771fd17b06dfb8cfb29eaadf0f3b6a8b5)
(cherry picked from upstream commit f493a8394102b0aeb101d5dc2f963004c8741175)
---
lib/isc/tests/ht_test.c | 53 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/lib/isc/tests/ht_test.c b/lib/isc/tests/ht_test.c
index 74d95c1..65502b5 100644
--- a/lib/isc/tests/ht_test.c
+++ b/lib/isc/tests/ht_test.c
@@ -334,9 +334,62 @@ isc_ht_iterator_test(void **state) {
test_ht_iterator();
}
+static void
+isc_ht_case(void **state) {
+ UNUSED(state);
+
+ isc_ht_t *ht = NULL;
+ void *f = NULL;
+ isc_result_t result = ISC_R_UNSET;
+
+ unsigned char lower[16] = { "test case" };
+ unsigned char same[16] = { "test case" };
+ unsigned char upper[16] = { "TEST CASE" };
+ unsigned char mixed[16] = { "tEsT CaSe" };
+
+ isc_ht_init(&ht, test_mctx, 8, ISC_HT_CASE_SENSITIVE);
+ assert_non_null(ht);
+
+ result = isc_ht_add(ht, lower, 16, (void *)lower);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_add(ht, same, 16, (void *)same);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_add(ht, upper, 16, (void *)upper);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_find(ht, mixed, 16, &f);
+ assert_int_equal(result, ISC_R_NOTFOUND);
+ assert_null(f);
+
+ isc_ht_destroy(&ht);
+ assert_null(ht);
+
+ isc_ht_init(&ht, test_mctx, 8, ISC_HT_CASE_INSENSITIVE);
+ assert_non_null(ht);
+
+ result = isc_ht_add(ht, lower, 16, (void *)lower);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_add(ht, same, 16, (void *)same);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_add(ht, upper, 16, (void *)upper);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_find(ht, mixed, 16, &f);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ assert_ptr_equal(f, &lower);
+
+ isc_ht_destroy(&ht);
+ assert_null(ht);
+}
+
int
main(void) {
const struct CMUnitTest tests[] = {
+ cmocka_unit_test(isc_ht_case),
cmocka_unit_test(isc_ht_20),
cmocka_unit_test(isc_ht_8),
cmocka_unit_test(isc_ht_1),
--
2.43.0

View File

@ -0,0 +1,75 @@
From aa1b0fc4b24d26233db30c85ae3609e54e9fa6d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
Date: Sun, 11 Feb 2024 09:13:43 +0100
Subject: [PATCH] Add a system test for mixed-case data for the same owner
We were missing a test where a single owner name would have multiple
types with a different case. The generated RRSIGs and NSEC records will
then have different case than the signed records and message parser have
to cope with that and treat everything as the same owner.
(cherry picked from commit a114042059ecbbc94ae0f604ca681323a75af480)
(cherry picked from upstream commit b9c10a194da3358204f5ba7d91e55332db435614)
---
bin/tests/system/dnssec/ns3/secure.example.db.in | 5 +++++
bin/tests/system/dnssec/ns3/sign.sh | 4 +++-
bin/tests/system/dnssec/tests.sh | 15 +++++++++++++++
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in
index 27f2b24..599566e 100644
--- a/bin/tests/system/dnssec/ns3/secure.example.db.in
+++ b/bin/tests/system/dnssec/ns3/secure.example.db.in
@@ -45,3 +45,8 @@ rrsigonly A 10.0.0.29
cnameandkey CNAME @
cnamenokey CNAME @
dnameandkey DNAME @
+
+mixedcase A 10.0.0.30
+mixedCASE TXT "mixed case"
+MIXEDcase AAAA 2002::
+mIxEdCaSe LOC 37 52 56.788 N 121 54 55.02 W 1120m 10m 100m 10m
diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh
index 80d412e..d94f382 100644
--- a/bin/tests/system/dnssec/ns3/sign.sh
+++ b/bin/tests/system/dnssec/ns3/sign.sh
@@ -86,7 +86,9 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone
cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" > "$zonefile"
-"$SIGNER" -P -o "$zone" "$zonefile" > /dev/null
+"$SIGNER" -P -D -o "$zone" "$zonefile" >/dev/null
+cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
+mv "$zonefile".tmp "$zonefile".signed
zone=bogus.example.
infile=bogus.example.db.in
diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh
index fe95c8d..0c03970 100644
--- a/bin/tests/system/dnssec/tests.sh
+++ b/bin/tests/system/dnssec/tests.sh
@@ -762,6 +762,21 @@ n=$((n+1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
+echo_i "checking mixed-case positive validation ($n)"
+ret=0
+for type in a txt aaaa loc; do
+ dig_with_opts +noauth mixedcase.secure.example. \
+ @10.53.0.3 $type >dig.out.$type.ns3.test$n || ret=1
+ dig_with_opts +noauth mixedcase.secure.example. \
+ @10.53.0.4 $type >dig.out.$type.ns4.test$n || ret=1
+ digcomp --lc dig.out.$type.ns3.test$n dig.out.$type.ns4.test$n || ret=1
+ grep "status: NOERROR" dig.out.$type.ns4.test$n >/dev/null || ret=1
+ grep "flags:.*ad.*QUERY" dig.out.$type.ns4.test$n >/dev/null || ret=1
+done
+n=$((n + 1))
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status + ret))
+
echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
ret=0
dig_with_opts +noauth a.nsec3.example. \
--
2.43.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,478 @@
From c6e05ffc5fb784514ab54938867abaab41126c65 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Mon, 12 Feb 2024 21:09:51 +0100
Subject: [PATCH] Prevent increased CPU consumption in DNSSEC validator
KeyTrap - Extreme CPU consumption in DNSSEC validator. Preparing an
NSEC3 closest encloser proof can exhaust CPU resources.
6322. [security] Specific DNS answers could cause a denial-of-service
condition due to DNS validation taking a long time.
(CVE-2023-50387) [GL #4424]
Resolves: CVE-2023-50387 CVE-2023-50868
---
lib/dns/dst_api.c | 27 +++++++++----
lib/dns/include/dns/validator.h | 1 +
lib/dns/include/dst/dst.h | 4 ++
lib/dns/resolver.c | 4 +-
lib/dns/validator.c | 67 +++++++++++++++------------------
lib/isc/include/isc/netmgr.h | 3 ++
lib/isc/netmgr/netmgr-int.h | 1 +
lib/isc/netmgr/netmgr.c | 36 +++++++++++-------
lib/isc/netmgr/tcp.c | 6 +--
lib/isc/netmgr/tcpdns.c | 4 +-
lib/isc/netmgr/udp.c | 6 +--
11 files changed, 91 insertions(+), 68 deletions(-)
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 62600dd..3aafd7c 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -160,7 +160,8 @@ computeid(dst_key_t *key);
static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass,
- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp);
static isc_result_t
algorithm_status(unsigned int alg);
@@ -745,6 +746,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+ return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp));
+}
+
+isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp) {
uint8_t alg, proto;
uint32_t flags, extflags;
dst_key_t *key = NULL;
@@ -775,7 +783,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
}
result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
- &key);
+ no_rdata, &key);
if (result != ISC_R_SUCCESS) {
return (result);
}
@@ -796,7 +804,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
REQUIRE(dst_initialized);
result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
- &key);
+ false, &key);
if (result != ISC_R_SUCCESS) {
return (result);
}
@@ -2288,7 +2296,8 @@ computeid(dst_key_t *key) {
static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass,
- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp) {
dst_key_t *key;
isc_result_t ret;
@@ -2313,10 +2322,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
return (DST_R_UNSUPPORTEDALG);
}
- ret = key->func->fromdns(key, source);
- if (ret != ISC_R_SUCCESS) {
- dst_key_free(&key);
- return (ret);
+ if (!no_rdata) {
+ ret = key->func->fromdns(key, source);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
}
}
diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h
index 4744014..fe97e41 100644
--- a/lib/dns/include/dns/validator.h
+++ b/lib/dns/include/dns/validator.h
@@ -148,6 +148,7 @@ struct dns_validator {
unsigned int authcount;
unsigned int authfail;
isc_stdtime_t start;
+ bool failed;
};
/*%
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index f454ebb..36770b5 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -469,6 +469,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory);
*/
isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp);
+isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
/*%<
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 7cbfbb2..be1d735 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -10613,8 +10613,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
* Since we have a pool of tasks we bind them to task queues
* to spread the load evenly
*/
- result = isc_task_create_bound(taskmgr, 0,
- &res->buckets[i].task, i);
+ result = isc_task_create_bound(
+ taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i));
if (result != ISC_R_SUCCESS) {
isc_mutex_destroy(&res->buckets[i].lock);
goto cleanup_buckets;
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index e54fc70..e416cc9 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -1098,8 +1098,8 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
* 'rdataset'. If found, build a dst_key_t for it and point val->key at
* it.
*
- * If val->key is already non-NULL, locate it in the rdataset and then
- * search past it for the *next* key that could have signed 'siginfo', then
+ * If val->key is already non-NULL, start searching from the next position in
+ * 'rdataset' to find the *next* key that could have signed 'siginfo', then
* set val->key to that.
*
* Returns ISC_R_SUCCESS if a possible matching key has been found,
@@ -1112,59 +1112,59 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
isc_buffer_t b;
dns_rdata_t rdata = DNS_RDATA_INIT;
dst_key_t *oldkey = val->key;
- bool foundold;
+ bool no_rdata = false;
if (oldkey == NULL) {
- foundold = true;
+ result = dns_rdataset_first(rdataset);
} else {
- foundold = false;
+ dst_key_free(&oldkey);
val->key = NULL;
+ result = dns_rdataset_next(rdataset);
}
-
- result = dns_rdataset_first(rdataset);
if (result != ISC_R_SUCCESS) {
- goto failure;
+ goto done;
}
+
do {
dns_rdataset_current(rdataset, &rdata);
isc_buffer_init(&b, rdata.data, rdata.length);
isc_buffer_add(&b, rdata.length);
INSIST(val->key == NULL);
- result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
- val->view->mctx, &val->key);
+ result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b,
+ val->view->mctx, no_rdata,
+ &val->key);
if (result == ISC_R_SUCCESS) {
if (siginfo->algorithm ==
(dns_secalg_t)dst_key_alg(val->key) &&
siginfo->keyid ==
(dns_keytag_t)dst_key_id(val->key) &&
+ (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) ==
+ 0 &&
dst_key_iszonekey(val->key))
{
- if (foundold) {
- /*
- * This is the key we're looking for.
- */
- return (ISC_R_SUCCESS);
- } else if (dst_key_compare(oldkey, val->key)) {
- foundold = true;
- dst_key_free(&oldkey);
+ if (no_rdata) {
+ /* Retry with full key */
+ dns_rdata_reset(&rdata);
+ dst_key_free(&val->key);
+ no_rdata = false;
+ continue;
}
+ /* This is the key we're looking for. */
+ goto done;
}
dst_key_free(&val->key);
}
dns_rdata_reset(&rdata);
result = dns_rdataset_next(rdataset);
+ no_rdata = true;
} while (result == ISC_R_SUCCESS);
+done:
if (result == ISC_R_NOMORE) {
result = ISC_R_NOTFOUND;
}
-failure:
- if (oldkey != NULL) {
- dst_key_free(&oldkey);
- }
-
return (result);
}
@@ -1557,20 +1557,9 @@ validate_answer(dns_validator_t *val, bool resume) {
continue;
}
- do {
- isc_result_t tresult;
- vresult = verify(val, val->key, &rdata,
- val->siginfo->keyid);
- if (vresult == ISC_R_SUCCESS) {
- break;
- }
-
- tresult = select_signing_key(val, val->keyset);
- if (tresult != ISC_R_SUCCESS) {
- break;
- }
- } while (1);
+ vresult = verify(val, val->key, &rdata, val->siginfo->keyid);
if (vresult != ISC_R_SUCCESS) {
+ val->failed = true;
validator_log(val, ISC_LOG_DEBUG(3),
"failed to verify rdataset");
} else {
@@ -1607,9 +1596,13 @@ validate_answer(dns_validator_t *val, bool resume) {
} else {
validator_log(val, ISC_LOG_DEBUG(3),
"verify failure: %s",
- isc_result_totext(result));
+ isc_result_totext(vresult));
resume = false;
}
+ if (val->failed) {
+ result = ISC_R_NOMORE;
+ break;
+ }
}
if (result != ISC_R_NOMORE) {
validator_log(val, ISC_LOG_DEBUG(3),
diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h
index be9fd56..dfabdc8 100644
--- a/lib/isc/include/isc/netmgr.h
+++ b/lib/isc/include/isc/netmgr.h
@@ -455,6 +455,9 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
* 'cb'.
*/
+#define ISC_NM_TASK_SLOW_OFFSET -2
+#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i)
+
void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%<
diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h
index f7b54f9..70bb32d 100644
--- a/lib/isc/netmgr/netmgr-int.h
+++ b/lib/isc/netmgr/netmgr-int.h
@@ -673,6 +673,7 @@ struct isc_nm {
#ifdef NETMGR_TRACE
ISC_LIST(isc_nmsocket_t) active_sockets;
#endif
+ int nlisteners;
};
typedef enum isc_nmsocket_type {
diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c
index 0ed3182..898de41 100644
--- a/lib/isc/netmgr/netmgr.c
+++ b/lib/isc/netmgr/netmgr.c
@@ -269,31 +269,34 @@ isc__nm_winsock_destroy(void) {
#endif /* WIN32 */
static void
-isc__nm_threadpool_initialize(uint32_t workers) {
+isc__nm_threadpool_initialize(uint32_t nworkers) {
char buf[11];
int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf,
&(size_t){ sizeof(buf) });
if (r == UV_ENOENT) {
- snprintf(buf, sizeof(buf), "%" PRIu32, workers);
+ snprintf(buf, sizeof(buf), "%" PRIu32, nworkers);
uv_os_setenv("UV_THREADPOOL_SIZE", buf);
}
}
void
-isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
+isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
isc_nm_t *mgr = NULL;
char name[32];
- REQUIRE(workers > 0);
+ REQUIRE(nworkers > 0);
#ifdef WIN32
isc__nm_winsock_initialize();
#endif /* WIN32 */
- isc__nm_threadpool_initialize(workers);
+ isc__nm_threadpool_initialize(nworkers);
mgr = isc_mem_get(mctx, sizeof(*mgr));
- *mgr = (isc_nm_t){ .nworkers = workers };
+ *mgr = (isc_nm_t){
+ .nworkers = nworkers * 2,
+ .nlisteners = nworkers,
+ };
isc_mem_attach(mctx, &mgr->mctx);
isc_mutex_init(&mgr->lock);
@@ -334,11 +337,12 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
isc_mempool_associatelock(mgr->evpool, &mgr->evlock);
isc_mempool_setfillcount(mgr->evpool, 32);
- isc_barrier_init(&mgr->pausing, workers);
- isc_barrier_init(&mgr->resuming, workers);
+ isc_barrier_init(&mgr->pausing, mgr->nworkers);
+ isc_barrier_init(&mgr->resuming, mgr->nworkers);
- mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t));
- for (size_t i = 0; i < workers; i++) {
+ mgr->workers = isc_mem_get(mctx,
+ mgr->nworkers * sizeof(isc__networker_t));
+ for (int i = 0; i < mgr->nworkers; i++) {
int r;
isc__networker_t *worker = &mgr->workers[i];
*worker = (isc__networker_t){
@@ -373,7 +377,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
mgr->workers_running++;
isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread);
- snprintf(name, sizeof(name), "isc-net-%04zu", i);
+ snprintf(name, sizeof(name), "isc-net-%04d", i);
isc_thread_setname(worker->thread, name);
}
@@ -848,9 +852,15 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) {
isc__networker_t *worker = NULL;
if (threadid == -1) {
- tid = (int)isc_random_uniform(nm->nworkers);
+ tid = (int)isc_random_uniform(nm->nlisteners);
+ } else if (threadid == ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners +
+ (int)isc_random_uniform(nm->nworkers - nm->nlisteners);
+ } else if (threadid < ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) %
+ (nm->nworkers - nm->nlisteners));
} else {
- tid = threadid % nm->nworkers;
+ tid = threadid % nm->nlisteners;
}
worker = &nm->workers[tid];
diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c
index 5cca9f5..83bd2e2 100644
--- a/lib/isc/netmgr/tcp.c
+++ b/lib/isc/netmgr/tcp.c
@@ -321,7 +321,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_connectcb(sock, req, result, false);
} else {
isc__nmsocket_clearcb(sock);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_connectcb(sock, req, result, true);
}
atomic_store(&sock->closed, true);
@@ -339,7 +339,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_tcpconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
@@ -435,7 +435,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c
index 188790c..7f13ab2 100644
--- a/lib/isc/netmgr/tcpdns.c
+++ b/lib/isc/netmgr/tcpdns.c
@@ -305,7 +305,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_tcpdnsconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
@@ -404,7 +404,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c
index a91c425..f2e161c 100644
--- a/lib/isc/netmgr/udp.c
+++ b/lib/isc/netmgr/udp.c
@@ -126,7 +126,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
uv_os_sock_t fd = -1;
/*
- * We are creating mgr->nworkers duplicated sockets, one
+ * We are creating mgr->nlisteners duplicated sockets, one
* socket for each worker thread.
*/
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
@@ -136,7 +136,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
@@ -795,7 +795,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_udpconnect(mgr, event);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)event);
}
--
2.43.0

View File

@ -0,0 +1,111 @@
From bef141d5795429cab745f29f7d080d1e2ea8f164 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Mon, 12 Feb 2024 20:33:41 +0100
Subject: [PATCH] Prevent assertion failure when nxdomain-redirect is used with
RFC 1918 reverse zones
6316. [security] Specific queries could trigger an assertion check with
nxdomain-redirect enabled. (CVE-2023-5517) [GL #4281]
---
lib/ns/query.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/lib/ns/query.c b/lib/ns/query.c
index 4fe3e30..cc1d179 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -453,10 +453,10 @@ static void
query_addnxrrsetnsec(query_ctx_t *qctx);
static isc_result_t
-query_nxdomain(query_ctx_t *qctx, bool empty_wild);
+query_nxdomain(query_ctx_t *qctx, isc_result_t result);
static isc_result_t
-query_redirect(query_ctx_t *qctx);
+query_redirect(query_ctx_t *qctx, isc_result_t result);
static isc_result_t
query_ncache(query_ctx_t *qctx, isc_result_t result);
@@ -7262,8 +7262,7 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) {
* result from the search.
*/
static isc_result_t
-query_gotanswer(query_ctx_t *qctx, isc_result_t res) {
- isc_result_t result = res;
+query_gotanswer(query_ctx_t *qctx, isc_result_t result) {
char errmsg[256];
CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer");
@@ -7333,16 +7332,16 @@ root_key_sentinel:
return (query_nodata(qctx, DNS_R_NXRRSET));
case DNS_R_EMPTYWILD:
- return (query_nxdomain(qctx, true));
+ return (query_nxdomain(qctx, DNS_R_EMPTYWILD));
case DNS_R_NXDOMAIN:
- return (query_nxdomain(qctx, false));
+ return (query_nxdomain(qctx, DNS_R_NXDOMAIN));
case DNS_R_COVERINGNSEC:
return (query_coveringnsec(qctx));
case DNS_R_NCACHENXDOMAIN:
- result = query_redirect(qctx);
+ result = query_redirect(qctx, result);
if (result != ISC_R_COMPLETE) {
return (result);
}
@@ -9155,10 +9154,10 @@ query_addnxrrsetnsec(query_ctx_t *qctx) {
* Handle NXDOMAIN and empty wildcard responses.
*/
static isc_result_t
-query_nxdomain(query_ctx_t *qctx, bool empty_wild) {
+query_nxdomain(query_ctx_t *qctx, isc_result_t result) {
dns_section_t section;
uint32_t ttl;
- isc_result_t result;
+ bool empty_wild = (result == DNS_R_EMPTYWILD);
CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain");
@@ -9167,7 +9166,7 @@ query_nxdomain(query_ctx_t *qctx, bool empty_wild) {
INSIST(qctx->is_zone || REDIRECT(qctx->client));
if (!empty_wild) {
- result = query_redirect(qctx);
+ result = query_redirect(qctx, result);
if (result != ISC_R_COMPLETE) {
return (result);
}
@@ -9253,7 +9252,7 @@ cleanup:
* redirecting, so query processing should continue past it.
*/
static isc_result_t
-query_redirect(query_ctx_t *qctx) {
+query_redirect(query_ctx_t *qctx, isc_result_t saved_result) {
isc_result_t result;
CCTRACE(ISC_LOG_DEBUG(3), "query_redirect");
@@ -9294,7 +9293,7 @@ query_redirect(query_ctx_t *qctx) {
SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset);
SAVE(qctx->client->query.redirect.sigrdataset,
qctx->sigrdataset);
- qctx->client->query.redirect.result = DNS_R_NCACHENXDOMAIN;
+ qctx->client->query.redirect.result = saved_result;
dns_name_copynf(qctx->fname,
qctx->client->query.redirect.fname);
qctx->client->query.redirect.authoritative =
@@ -9908,7 +9907,7 @@ query_coveringnsec(query_ctx_t *qctx) {
* We now have the proof that we have an NXDOMAIN. Apply
* NXDOMAIN redirection if configured.
*/
- result = query_redirect(qctx);
+ result = query_redirect(qctx, DNS_R_COVERINGNSEC);
if (result != ISC_R_COMPLETE) {
redirected = true;
goto cleanup;
--
2.43.0

View File

@ -0,0 +1,37 @@
From 61112d1ce39848e08ec133f280cf8f729cb70d16 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Mon, 12 Feb 2024 20:41:43 +0100
Subject: [PATCH] Prevent assertion failure if DNS64 and serve-stale is used
Enabling both DNS64 and serve-stale may cause an assertion failure
during recursive resolution.
6317. [security] Restore DNS64 state when handling a serve-stale timeout.
(CVE-2023-5679) [GL #4334]
Resolves: CVE-2023-5679
---
lib/ns/query.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/ns/query.c b/lib/ns/query.c
index cc1d179..1993800 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -5983,6 +5983,13 @@ query_lookup_stale(ns_client_t *client) {
query_ctx_t qctx;
qctx_init(client, NULL, client->query.qtype, &qctx);
+ if (DNS64(client)) {
+ qctx.qtype = qctx.type = dns_rdatatype_a;
+ qctx.dns64 = true;
+ }
+ if (DNS64EXCLUDE(client)) {
+ qctx.dns64_exclude = true;
+ }
dns_db_attach(client->view->cachedb, &qctx.db);
client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
client->query.dboptions |= DNS_DBFIND_STALETIMEOUT;
--
2.43.0

View File

@ -0,0 +1,52 @@
From e91ab7758bed0cf3dcf8ed745f91063d7ec4011c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <michal@isc.org>
Date: Thu, 4 Jan 2024 13:39:27 +0100
Subject: [PATCH] Fix map offsets in the "masterformat" system test
The "masterformat" system test attempts to check named-checkzone
behavior when it is fed corrupt map-format zone files. However, despite
the RBTDB and RBT structures having evolved over the years, the offsets
at which a valid map-format zone file is malformed by the "masterformat"
test have not been updated accordingly, causing the relevant checks to
introduce a different type of corruption than they were originally meant
to cause:
- the "bad node header" check originally mangled the 'type' member of
the rdatasetheader_t structure for cname.example.nil,
- the "bad node data" check originally mangled the 'serial' and
'rdh_ttl' members of the rdatasetheader_t structure for
aaaa.example.nil.
Update the offsets at which the map-format zone file is malformed at by
the "masterformat" system test so that the relevant checks fulfill their
original purpose again.
---
bin/tests/system/masterformat/tests.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh
index 364a0d2..bb4e6ec 100755
--- a/bin/tests/system/masterformat/tests.sh
+++ b/bin/tests/system/masterformat/tests.sh
@@ -295,7 +295,7 @@ status=$((status+ret))
echo_i "checking corrupt map files fail to load (bad node header) ($n)"
ret=0
cp map.5 badmap
-stomp badmap 2754 2 99
+stomp badmap 3706 2 99
$CHECKZONE -D -f map -F text -o text.5 example.nil badmap > /dev/null
[ $? = 1 ] || ret=1
n=$((n+1))
@@ -305,7 +305,7 @@ status=$((status+ret))
echo_i "checking corrupt map files fail to load (bad node data) ($n)"
ret=0
cp map.5 badmap
-stomp badmap 2897 5 127
+stomp badmap 3137 5 127
$CHECKZONE -D -f map -F text -o text.5 example.nil badmap > /dev/null
[ $? = 1 ] || ret=1
n=$((n+1))
--
2.44.0

View File

@ -0,0 +1,283 @@
From 6e08fef24d7ba491228a4083ea0f0e33253a1043 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Mon, 12 Feb 2024 20:48:57 +0100
Subject: [PATCH] Specific recursive query patterns may lead to an
out-of-memory condition
6319. [security] Query patterns that continuously triggered cache
database maintenance could exhaust all available memory
on the host running named. (CVE-2023-6516) [GL #4383]
Resolves: CVE-2023-6516
---
lib/dns/include/dns/rbt.h | 6 ++
lib/dns/mapapi | 2 +-
lib/dns/rbt.c | 1 +
lib/dns/rbtdb.c | 149 +++++++++++++++++++++++++-------------
4 files changed, 107 insertions(+), 51 deletions(-)
diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h
index b67e602..69655b0 100644
--- a/lib/dns/include/dns/rbt.h
+++ b/lib/dns/include/dns/rbt.h
@@ -164,6 +164,12 @@ struct dns_rbtnode {
uint16_t locknum; /* note that this is not in the bitfield */
isc_refcount_t references;
/*@}*/
+
+ /*%
+ * This linked list is used to store nodes from which tree pruning can
+ * be started.
+ */
+ ISC_LINK(dns_rbtnode_t) prunelink;
};
typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
diff --git a/lib/dns/mapapi b/lib/dns/mapapi
index 1b502d3..a46e190 100644
--- a/lib/dns/mapapi
+++ b/lib/dns/mapapi
@@ -13,4 +13,4 @@
# Whenever releasing a new major release of BIND9, set this value
# back to 1.0 when releasing the first alpha. Map files are *never*
# compatible across major releases.
-MAPAPI=3.0
+MAPAPI=4.0
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
index 7f2c2d2..a220368 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.c
@@ -2283,6 +2283,7 @@ create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) {
HASHVAL(node) = 0;
ISC_LINK_INIT(node, deadlink);
+ ISC_LINK_INIT(node, prunelink);
LOCKNUM(node) = 0;
WILD(node) = 0;
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 75f97f5..2707507 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -515,6 +515,10 @@ struct dns_rbtdb {
*/
rbtnodelist_t *deadnodes;
+ /* List of nodes from which recursive tree pruning can be started from.
+ * Locked by tree_lock. */
+ rbtnodelist_t prunenodes;
+
/*
* Heaps. These are used for TTL based expiry in a cache,
* or for zone resigning in a zone DB. hmctx is the memory
@@ -1060,6 +1064,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
unsigned int i;
isc_result_t result;
char buf[DNS_NAME_FORMATSIZE];
+ dns_rbtnode_t *node = NULL;
dns_rbt_t **treep;
isc_time_t start;
dns_dbonupdatelistener_t *listener, *listener_next;
@@ -1086,8 +1091,6 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
* the overhead of unlinking all nodes here should be negligible.
*/
for (i = 0; i < rbtdb->node_lock_count; i++) {
- dns_rbtnode_t *node;
-
node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
while (node != NULL) {
ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink);
@@ -1095,6 +1098,12 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
}
}
+ node = ISC_LIST_HEAD(rbtdb->prunenodes);
+ while (node != NULL) {
+ ISC_LIST_UNLINK(rbtdb->prunenodes, node, prunelink);
+ node = ISC_LIST_HEAD(rbtdb->prunenodes);
+ }
+
if (event == NULL) {
rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0;
}
@@ -1934,19 +1943,32 @@ is_leaf(dns_rbtnode_t *node) {
node->left == NULL && node->right == NULL);
}
+/*%
+ * The tree lock must be held when this function is called as it reads and
+ * updates rbtdb->prunenodes.
+ */
static inline void
send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
isc_rwlocktype_t locktype) {
- isc_event_t *ev;
- dns_db_t *db;
+ bool pruning_queued = (ISC_LIST_HEAD(rbtdb->prunenodes) != NULL);
+
+ INSIST(locktype == isc_rwlocktype_write);
- ev = isc_event_allocate(rbtdb->common.mctx, NULL, DNS_EVENT_RBTPRUNE,
- prune_tree, node, sizeof(isc_event_t));
new_reference(rbtdb, node, locktype);
- db = NULL;
- attach((dns_db_t *)rbtdb, &db);
- ev->ev_sender = db;
- isc_task_send(rbtdb->task, &ev);
+ INSIST(!ISC_LINK_LINKED(node, prunelink));
+ ISC_LIST_APPEND(rbtdb->prunenodes, node, prunelink);
+
+ if (!pruning_queued) {
+ isc_event_t *ev = NULL;
+ dns_db_t *db = NULL;
+
+ attach((dns_db_t *)rbtdb, &db);
+
+ ev = isc_event_allocate(rbtdb->common.mctx, NULL,
+ DNS_EVENT_RBTPRUNE, prune_tree, db,
+ sizeof(isc_event_t));
+ isc_task_send(rbtdb->task, &ev);
+ }
}
/*%
@@ -2220,17 +2242,26 @@ restore_locks:
}
/*
- * Prune the tree by recursively cleaning-up single leaves. In the worst
- * case, the number of iteration is the number of tree levels, which is at
- * most the maximum number of domain name labels, i.e, 127. In practice, this
- * should be much smaller (only a few times), and even the worst case would be
- * acceptable for a single event.
+ * Prune the tree by recursively cleaning up single leaves. Go through all
+ * nodes stored in the rbtdb->prunenodes list; for each of them, in the worst
+ * case, it will be necessary to traverse a number of tree levels equal to the
+ * maximum legal number of domain name labels (127); in practice, the number of
+ * tree levels to traverse will virtually always be much smaller (a few levels
+ * at most). While holding the tree lock throughout this entire operation is
+ * less than ideal, so is splitting the latter up by queueing a separate
+ * prune_tree() run for each node to start pruning from (as queueing requires
+ * allocating memory and can therefore potentially be exploited to exhaust
+ * available memory). Also note that actually freeing up the memory used by
+ * RBTDB nodes (which is what this function does) is essential to keeping cache
+ * memory use in check, so since the tree lock needs to be acquired anyway,
+ * freeing as many nodes as possible before the tree lock gets released is
+ * prudent.
*/
static void
prune_tree(isc_task_t *task, isc_event_t *event) {
- dns_rbtdb_t *rbtdb = event->ev_sender;
- dns_rbtnode_t *node = event->ev_arg;
- dns_rbtnode_t *parent;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)event->ev_arg;
+ dns_rbtnode_t *node = NULL;
+ dns_rbtnode_t *parent = NULL;
unsigned int locknum;
UNUSED(task);
@@ -2238,44 +2269,60 @@ prune_tree(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
- locknum = node->locknum;
- NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
- do {
- parent = node->parent;
- decrement_reference(rbtdb, node, 0, isc_rwlocktype_write,
- isc_rwlocktype_write, true);
- if (parent != NULL && parent->down == NULL) {
- /*
- * node was the only down child of the parent and has
- * just been removed. We'll then need to examine the
- * parent. Keep the lock if possible; otherwise,
- * release the old lock and acquire one for the parent.
- */
- if (parent->locknum != locknum) {
- NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
- isc_rwlocktype_write);
- locknum = parent->locknum;
- NODE_LOCK(&rbtdb->node_locks[locknum].lock,
- isc_rwlocktype_write);
+ while ((node = ISC_LIST_HEAD(rbtdb->prunenodes)) != NULL) {
+ locknum = node->locknum;
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ do {
+ if (ISC_LINK_LINKED(node, prunelink)) {
+ ISC_LIST_UNLINK(rbtdb->prunenodes, node,
+ prunelink);
}
- /*
- * We need to gain a reference to the node before
- * decrementing it in the next iteration.
- */
- if (ISC_LINK_LINKED(parent, deadlink)) {
- ISC_LIST_UNLINK(rbtdb->deadnodes[locknum],
+ parent = node->parent;
+ decrement_reference(rbtdb, node, 0,
+ isc_rwlocktype_write,
+ isc_rwlocktype_write, true);
+
+ if (parent != NULL && parent->down == NULL) {
+ /*
+ * node was the only down child of the parent
+ * and has just been removed. We'll then need
+ * to examine the parent. Keep the lock if
+ * possible; otherwise, release the old lock and
+ * acquire one for the parent.
+ */
+ if (parent->locknum != locknum) {
+ NODE_UNLOCK(
+ &rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ locknum = parent->locknum;
+ NODE_LOCK(
+ &rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ }
+
+ /*
+ * We need to gain a reference to the node
+ * before decrementing it in the next iteration.
+ */
+ if (ISC_LINK_LINKED(parent, deadlink)) {
+ ISC_LIST_UNLINK(
+ rbtdb->deadnodes[locknum],
parent, deadlink);
+ }
+ new_reference(rbtdb, parent,
+ isc_rwlocktype_write);
+ } else {
+ parent = NULL;
}
- new_reference(rbtdb, parent, isc_rwlocktype_write);
- } else {
- parent = NULL;
- }
- node = parent;
- } while (node != NULL);
- NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
+ node = parent;
+ } while (node != NULL);
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ }
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
detach((dns_db_t **)&rbtdb);
@@ -8726,6 +8773,8 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
ISC_LIST_INIT(rbtdb->deadnodes[i]);
}
+ ISC_LIST_INIT(rbtdb->prunenodes);
+
rbtdb->active = rbtdb->node_lock_count;
for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
--
2.43.0

View File

@ -0,0 +1,40 @@
From d249889a9c18df7792ca3cd8d97897e4fb5824b5 Mon Sep 17 00:00:00 2001
From: Aram Sargsyan <aram@isc.org>
Date: Wed, 31 Aug 2022 12:30:38 +0000
Subject: [PATCH] Add mctx attach/detach when creating/destroying a memory pool
This should make sure that the memory context is not destroyed
before the memory pool, which is using the context.
(cherry picked from commit e97c3eea954e055634b72c21325d2611e960ee94)
---
lib/isc/mem.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/isc/mem.c b/lib/isc/mem.c
index f84d300..33ece7a 100644
--- a/lib/isc/mem.c
+++ b/lib/isc/mem.c
@@ -1656,7 +1656,8 @@ isc_mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
mpctx->common.impmagic = MEMPOOL_MAGIC;
mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
mpctx->lock = NULL;
- mpctx->mctx = mctx;
+ mpctx->mctx = NULL;
+ isc_mem_attach((isc_mem_t *)mctx, (isc_mem_t **)&mpctx->mctx);
/*
* Mempools are stored as a linked list of element.
*/
@@ -1765,7 +1766,8 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
mpctx->common.impmagic = 0;
mpctx->common.magic = 0;
- isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
+ isc_mem_putanddetach((isc_mem_t **)&mpctx->mctx, mpctx,
+ sizeof(isc__mempool_t));
if (lock != NULL) {
UNLOCK(lock);
--
2.43.2

View File

@ -0,0 +1,66 @@
From 103b09187466b2afbff7e204d166d21e2fbb057c Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Wed, 21 Feb 2024 11:54:27 +0100
Subject: [PATCH] Downstream specific changes related to KeyTrap
Fix for CVE-2023-50387 introduced new additional thread. But because
isc_hp functions were removed from later bind 9.16 release, their
changes did not contain increase of hazard pointers max thread limit.
To prevent obscure memory corruption increase thread max size.
In addition place at least few INSISTs to check this is catched before
random memory overwrites begins. It would be quite difficult to track
without any check.
---
lib/isc/hp.c | 3 +++
lib/isc/managers.c | 5 +++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/lib/isc/hp.c b/lib/isc/hp.c
index 92d160b..5f9bbf7 100644
--- a/lib/isc/hp.c
+++ b/lib/isc/hp.c
@@ -138,6 +138,7 @@ isc_hp_destroy(isc_hp_t *hp) {
void
isc_hp_clear(isc_hp_t *hp) {
+ INSIST(tid() < isc__hp_max_threads);
for (int i = 0; i < hp->max_hps; i++) {
atomic_store_release(&hp->hp[tid()][i], 0);
}
@@ -152,6 +153,7 @@ uintptr_t
isc_hp_protect(isc_hp_t *hp, int ihp, atomic_uintptr_t *atom) {
uintptr_t n = 0;
uintptr_t ret;
+ INSIST(tid() < isc__hp_max_threads);
while ((ret = atomic_load(atom)) != n) {
atomic_store(&hp->hp[tid()][ihp], ret);
n = ret;
@@ -173,6 +175,7 @@ isc_hp_protect_release(isc_hp_t *hp, int ihp, atomic_uintptr_t ptr) {
void
isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
+ INSIST(tid() < isc__hp_max_threads);
hp->rl[tid()]->list[hp->rl[tid()]->size++] = ptr;
INSIST(hp->rl[tid()]->size < isc__hp_max_retired);
diff --git a/lib/isc/managers.c b/lib/isc/managers.c
index c39a650..3bdca99 100644
--- a/lib/isc/managers.c
+++ b/lib/isc/managers.c
@@ -25,9 +25,10 @@ isc_managers_create(isc_mem_t *mctx, size_t workers, size_t quantum,
/*
* We have ncpus network threads, ncpus old network threads - make
- * it 4x just to be on the safe side.
+ * it 4x just to be on the safe side. One additional for slow netmgr
+ * thread.
*/
- isc_hp_init(4 * workers);
+ isc_hp_init(5 * workers);
REQUIRE(netmgrp != NULL && *netmgrp == NULL);
isc__netmgr_create(mctx, workers, &netmgr);
--
2.43.2

View File

@ -0,0 +1,33 @@
From 7cc9fd1870e5264abd885ed2c419034945121d0f Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Mon, 19 Feb 2024 22:13:52 +0100
Subject: [PATCH] Define variants to empty values
DNSSEC_VARIANT and NAMED_VARIANT are special Red Hat modifications to
allow testing or alternative rebuilds, with support for pkcs11 or sdb.
But undefined value breaks some tests, so define them to empty values.
That means normal build variant.
Required to pass upstream test suite cds test correctly.
---
bin/tests/system/conf.sh.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in
index 7b2b309..c2d6526 100644
--- a/bin/tests/system/conf.sh.in
+++ b/bin/tests/system/conf.sh.in
@@ -24,6 +24,10 @@ TMPDIR=${TMPDIR:-/tmp}
# This is not the windows build.
CYGWIN=""
+# RH specific, allow variants testing
+: ${DNSSEC_VARIANT:=}
+: ${NAMED_VARIANT:=}
+
# Load common values shared between windows and unix/linux.
. $TOP/bin/tests/system/conf.sh.common
--
2.43.2

View File

@ -57,7 +57,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
Name: bind9.16
License: MPLv2.0
Version: 9.16.23
Release: 0.14%{?dist}.2.alma.1
Release: 0.16%{?dist}.2.alma.1
Epoch: 32
Url: https://www.isc.org/downloads/bind/
#
@ -130,6 +130,23 @@ Patch187: bind-9.16-CVE-2022-3924.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/f1d9e9ee3859976f403914d20ad2a10855343702
Patch188: bind-9.16-CVE-2023-2828.patch
Patch189: bind-9.16-CVE-2023-3341.patch
Patch194: bind-9.16-CVE-2023-4408.patch
Patch195: bind-9.16-CVE-2023-5517.patch
Patch196: bind-9.16-CVE-2023-5679.patch
Patch197: bind-9.16-CVE-2023-6516.patch
Patch198: bind-9.16-CVE-2023-50387.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/f493a8394102b0aeb101d5dc2f963004c8741175
Patch199: bind-9.16-CVE-2023-4408-test1.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/b9c10a194da3358204f5ba7d91e55332db435614
Patch200: bind-9.16-CVE-2023-4408-test2.patch
# Downstream only change, fixes patch 171
Patch201: bind-9.16-system-test-cds.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/32779aba8a0a5f852c611f44ecbeab5aab633e34
Patch202: bind-9.16-isc-mempool-attach.patch
# Downstream only change, complements patch 198
Patch203: bind-9.16-isc_hp-CVE-2023-50387.patch
# https://gitlab.isc.org/isc-projects/bind9/commit/1237d73cd1120b146ee699bbae7b2fe837cf2f98
Patch204: bind-9.16-CVE-2023-6516-test.patch
%{?systemd_ordering}
Requires: coreutils
@ -171,6 +188,7 @@ BuildRequires: softhsm
%if %{with SYSTEMTEST}
# bin/tests/system dependencies
BuildRequires: perl(Net::DNS) perl(Net::DNS::Nameserver) perl(Time::HiRes) perl(Getopt::Long)
BuildRequires: python-dns
# manual configuration requires this tool
BuildRequires: iproute
%endif
@ -443,6 +461,17 @@ in HTML and PDF format.
%patch187 -p1 -b .CVE-2022-3924
%patch188 -p1 -b .CVE-2023-2828
%patch189 -p1 -b .CVE-2023-3341
%patch194 -p1 -b .CVE-2023-4408
%patch195 -p1 -b .CVE-2023-5517
%patch196 -p1 -b .CVE-2023-5679
%patch197 -p1 -b .CVE-2023-6516
%patch198 -p1 -b .CVE-2023-50387
%patch199 -p1
%patch200 -p1
%patch201 -p1 -b .test-variant-def
%patch202 -p1 -b .mempool-attach
%patch203 -p1 -b .isc_hp-CVE-2023-50387
%patch204 -p1
%if %{with PKCS11}
%patch135 -p1 -b .config-pkcs11
@ -543,6 +572,11 @@ export LIBDIR_SUFFIX
--enable-fixed-rrset \
--enable-full-report \
;
%if 0%{?bind_skip_parsetab}
sed -e 's/^TARGETS =/& #/' -i bin/python/isc/Makefile
%endif
%if %{with DNSTAP}
pushd lib
SRCLIB="../../../lib"
@ -1162,6 +1196,18 @@ fi;
%endif
%changelog
* Fri Apr 12 2024 Andrew Lukoshko <alukoshko@almalinux.org> - 32:9.16.23-0.16.2.alma
- Import tests for large DNS messages fix
- Add downstream change complementing CVE-2023-50387
- Prevent increased CPU load on large DNS messages (CVE-2023-4408)
- Prevent assertion failure when nxdomain-redirect is used with
RFC 1918 reverse zones (CVE-2023-5517)
- Prevent assertion failure if DNS64 and serve-stale is used (CVE-2023-5679)
- Specific recursive query patterns may lead to an out-of-memory
condition (CVE-2023-6516)
- Prevent increased CPU consumption in DNSSEC validator (CVE-2023-50387
CVE-2023-50868)
* Thu Oct 05 2023 Andrew Lukoshko <alukoshko@almalinux.org> - 32:9.16.23-0.14.2.alma
- Prevent exahustion of memory from control channel (CVE-2023-3341)