From f00117a4226be90d1bc865aff19bddf114242914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 22 Jul 2025 08:07:02 +0200 Subject: [PATCH 01/16] Fail the DNSSEC validation if matching but invalid DNSKEY is found If a matching but cryptographically invalid key was encountered during the DNSSEC validation, the key would be just skipped and not counted towards validation failures. Treat such DNSSEC keys as hard failures and fail the DNSSEC validation immediatelly instead of continuing the DNSSEC validation with the next DNSKEYs in the RRset. Co-authored-by: Matthijs Mekking --- lib/dns/validator.c | 66 ++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/lib/dns/validator.c b/lib/dns/validator.c index e81146763b..72d7a45dd9 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -366,6 +366,12 @@ trynsec3: static void resume_answer_with_key_done(void *arg); +static bool +over_max_fails(dns_validator_t *val); + +static void +consume_validation_fail(dns_validator_t *val); + static void resume_answer_with_key(void *arg) { dns_validator_t *val = arg; @@ -374,6 +380,13 @@ resume_answer_with_key(void *arg) { isc_result_t result = select_signing_key(val, rdataset); if (result == ISC_R_SUCCESS) { val->keyset = &val->frdataset; + } else if (result != ISC_R_NOTFOUND) { + val->result = result; + if (over_max_fails(val)) { + INSIST(val->key == NULL); + val->result = ISC_R_QUOTA; + } + consume_validation_fail(val); } (void)validate_async_run(val, resume_answer_with_key_done); @@ -383,6 +396,16 @@ static void resume_answer_with_key_done(void *arg) { dns_validator_t *val = arg; + switch (val->result) { + case ISC_R_CANCELED: /* Validation was canceled */ + case ISC_R_SHUTTINGDOWN: /* Server shutting down */ + case ISC_R_QUOTA: /* Validation fails quota reached */ + dns_validator_cancel(val); + break; + default: + break; + } + resume_answer(val); } @@ -1047,9 +1070,6 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { val->key = NULL; result = dns_rdataset_next(rdataset); } - if (result == ISC_R_NOMORE) { - return ISC_R_NOTFOUND; - } for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_rrsig_t *siginfo = val->siginfo; @@ -1072,18 +1092,11 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { continue; } - result = dns_dnssec_keyfromrdata(&siginfo->signer, &rdata, - val->view->mctx, &val->key); - if (result == ISC_R_SUCCESS) { - /* found the key we wanted */ - break; - } - } - if (result == ISC_R_NOMORE) { - result = ISC_R_NOTFOUND; + return dns_dnssec_keyfromrdata(&siginfo->signer, &rdata, + val->view->mctx, &val->key); } - return result; + return ISC_R_NOTFOUND; } /*% @@ -1354,7 +1367,7 @@ selfsigned_dnskey(dns_validator_t *val) { result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx, &dstkey); if (result != ISC_R_SUCCESS) { - continue; + return result; } /* @@ -1594,7 +1607,7 @@ validate_answer_signing_key_done(void *arg); static void validate_answer_signing_key(void *arg) { dns_validator_t *val = arg; - isc_result_t result = ISC_R_NOTFOUND; + isc_result_t result; if (CANCELED(val) || CANCELING(val)) { val->result = ISC_R_CANCELED; @@ -1617,15 +1630,21 @@ validate_answer_signing_key(void *arg) { default: /* Select next signing key */ result = select_signing_key(val, val->keyset); + if (result == ISC_R_SUCCESS) { + INSIST(val->key != NULL); + } else if (result == ISC_R_NOTFOUND) { + INSIST(val->key == NULL); + } else { + val->result = result; + if (over_max_fails(val)) { + INSIST(val->key == NULL); + val->result = ISC_R_QUOTA; + } + consume_validation_fail(val); + } break; } - if (result == ISC_R_SUCCESS) { - INSIST(val->key != NULL); - } else { - INSIST(val->key == NULL); - } - (void)validate_async_run(val, validate_answer_signing_key_done); } @@ -1892,10 +1911,7 @@ check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid, result = dns_dnssec_keyfromrdata( val->name, keyrdata, val->view->mctx, &dstkey); if (result != ISC_R_SUCCESS) { - /* - * This really shouldn't happen, but... - */ - continue; + return result; } } result = verify(val, dstkey, &rdata, sig.keyid); From fa153f791f9324bf84abf8d259e11c0531fe6e25 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 10 Jul 2025 09:37:36 +1000 Subject: [PATCH 02/16] Tighten restrictions on caching NS RRsets in authority section To prevent certain spoofing attacks, a new check has been added to the existing rules for whether NS data can be cached: the owner name of the NS RRset must be an ancestor of the name being queried. --- lib/dns/resolver.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 61ec6191f6..85b8aafadd 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -8435,8 +8435,8 @@ rctx_answer_dname(respctx_t *rctx) { * section to be subdomains of the domain being queried; any that are * not are skipped. We expect to find only *one* owner name; any names * after the first one processed are ignored. We expect to find only - * rdatasets of type NS, RRSIG, or SIG; all others are ignored. Whatever - * remains can be cached at trust level authauthority or additional + * rdatasets of type NS; all others are ignored. Whatever remains can + * be cached at trust level authauthority or additional * (depending on whether the AA bit was set on the answer). */ static void @@ -8445,7 +8445,9 @@ rctx_authority_positive(respctx_t *rctx) { dns_message_t *msg = rctx->query->rmessage; MSG_SECTION_FOREACH(msg, DNS_SECTION_AUTHORITY, name) { - if (!name_external(name, dns_rdatatype_ns, fctx)) { + if (!name_external(name, dns_rdatatype_ns, fctx) && + dns_name_issubdomain(fctx->name, name)) + { /* * We expect to find NS or SIG NS rdatasets, and * nothing else. From a41054e9e606a61f1b3c8bc0c54e2f1059347165 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 14 Aug 2025 14:35:46 +1000 Subject: [PATCH 03/16] Further restrict addresses that are cached when processing referrals Use the owner name of the NS record as the bailwick apex name when determining which additional records to cache, rather than the name of the delegating zone (or a parent thereof). --- lib/dns/resolver.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 85b8aafadd..7d2823e129 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -6359,7 +6359,8 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset, bool external, * locally served zone. */ static inline bool -name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { +name_external(const dns_name_t *name, dns_rdatatype_t type, respctx_t *rctx) { + fetchctx_t *fctx = rctx->fctx; isc_result_t result; dns_forwarders_t *forwarders = NULL; dns_name_t *apex = NULL; @@ -6369,7 +6370,7 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) { dns_namereln_t rel; apex = (ISDUALSTACK(fctx->addrinfo) || !ISFORWARDER(fctx->addrinfo)) - ? fctx->domain + ? rctx->ns_name != NULL ? rctx->ns_name : fctx->domain : fctx->fwdname; /* @@ -6466,7 +6467,7 @@ check_section(void *arg, const dns_name_t *addname, dns_rdatatype_t type, result = dns_message_findname(rctx->query->rmessage, section, addname, dns_rdatatype_any, 0, &name, NULL); if (result == ISC_R_SUCCESS) { - external = name_external(name, type, fctx); + external = name_external(name, type, rctx); if (type == dns_rdatatype_a) { ISC_LIST_FOREACH(name->list, rdataset, link) { if (dns_rdatatype_issig(rdataset->type)) { @@ -8152,7 +8153,7 @@ rctx_answer_scan(respctx_t *rctx) { /* * Don't accept DNAME from parent namespace. */ - if (name_external(name, dns_rdatatype_dname, fctx)) { + if (name_external(name, dns_rdatatype_dname, rctx)) { continue; } @@ -8445,7 +8446,7 @@ rctx_authority_positive(respctx_t *rctx) { dns_message_t *msg = rctx->query->rmessage; MSG_SECTION_FOREACH(msg, DNS_SECTION_AUTHORITY, name) { - if (!name_external(name, dns_rdatatype_ns, fctx) && + if (!name_external(name, dns_rdatatype_ns, rctx) && dns_name_issubdomain(fctx->name, name)) { /* From 2e40705c06831988106335ed77db3cf924d431f6 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 13 Aug 2025 13:56:01 +1000 Subject: [PATCH 04/16] Retry lookups with unsigned DNAME over TCP To prevent spoofed unsigned DNAME responses being accepted retry response with unsigned DNAMEs over TCP if the response is not TSIG signed or there isn't a good DNS CLIENT COOKIE. --- doc/arm/reference.rst | 2 + lib/dns/include/dns/message.h | 8 +++ lib/dns/message.c | 12 +++++ lib/dns/resolver.c | 99 ++++++++++++++++++++++++++++------- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 3a761cfd1b..7d78c93adb 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -2207,6 +2207,8 @@ Boolean Options autodetection of DNS COOKIE support to determine when to retry a request over TCP. + For DNAME lookups the default is ``yes`` and it is enforced. Servers + serving DNAME must correctly support DNS over TCP. .. note:: If a UDP response is signed using TSIG, :iscman:`named` accepts it even if diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 557a745bbc..bfda3fbb56 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -261,6 +261,7 @@ struct dns_message { unsigned int rdclass_set : 1; /* 14 */ unsigned int fuzzing : 1; /* 15 */ unsigned int free_pools : 1; /* 16 */ + unsigned int has_dname : 1; /* 17 */ unsigned int : 0; unsigned int opt_reserved; @@ -1456,3 +1457,10 @@ dns_message_createpools(isc_mem_t *mctx, isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp); void dns_message_destroypools(isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp); + +bool +dns_message_hasdname(dns_message_t *msg); +/*%< + * Return whether a DNAME was detected in the ANSWER section of a QUERY + * message when it was parsed. + */ diff --git a/lib/dns/message.c b/lib/dns/message.c index e773a419d4..eadc99d015 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -442,6 +442,7 @@ msginit(dns_message_t *m) { m->cc_bad = 0; m->tkey = 0; m->rdclass_set = 0; + m->has_dname = 0; m->querytsig = NULL; m->indent.string = "\t"; m->indent.count = 0; @@ -1494,6 +1495,11 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx, */ msg->tsigname->attributes.nocompress = true; free_name = false; + } else if (rdtype == dns_rdatatype_dname && + sectionid == DNS_SECTION_ANSWER && + msg->opcode == dns_opcode_query) + { + msg->has_dname = 1; } rdataset = NULL; @@ -5083,3 +5089,9 @@ dns_message_destroypools(isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp) { isc_mempool_destroy(rdspoolp); isc_mempool_destroy(namepoolp); } + +bool +dns_message_hasdname(dns_message_t *msg) { + REQUIRE(DNS_MESSAGE_VALID(msg)); + return msg->has_dname; +} diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 7d2823e129..30537e418e 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -854,6 +854,7 @@ typedef struct respctx { bool get_nameservers; /* get a new NS rrset at * zone cut? */ bool resend; /* resend this query? */ + bool secured; /* message was signed or had a valid cookie */ bool nextitem; /* invalid response; keep * listening for the correct one */ bool truncated; /* response was truncated */ @@ -7278,13 +7279,10 @@ rctx_cookiecheck(respctx_t *rctx) { resquery_t *query = rctx->query; /* - * If TSIG signed, sent via TCP, or cookie present, - * no need to continue. + * If the message was secured or TCP is already in the + * retry flags, no need to continue. */ - if (dns_message_gettsig(query->rmessage, NULL) != NULL || - query->rmessage->cc_ok || query->rmessage->cc_bad || - (rctx->retryopts & DNS_FETCHOPT_TCP) != 0) - { + if (rctx->secured || (rctx->retryopts & DNS_FETCHOPT_TCP) != 0) { return ISC_R_SUCCESS; } @@ -7347,6 +7345,47 @@ rctx_cookiecheck(respctx_t *rctx) { return ISC_R_SUCCESS; } +static bool +rctx_need_tcpretry(respctx_t *rctx) { + resquery_t *query = rctx->query; + if ((rctx->retryopts & DNS_FETCHOPT_TCP) != 0) { + /* TCP is already in the retry flags */ + return false; + } + + /* + * If the message was secured, no need to continue. + */ + if (rctx->secured) { + return false; + } + + /* + * Currently the only extra reason why we might need to + * retry a UDP response over TCP is a DNAME in the message. + */ + if (dns_message_hasdname(query->rmessage)) { + return true; + } + + return false; +} + +static isc_result_t +rctx_tcpretry(respctx_t *rctx) { + /* + * Do we need to retry a UDP response over TCP? + */ + if (rctx_need_tcpretry(rctx)) { + rctx->retryopts |= DNS_FETCHOPT_TCP; + rctx->resend = true; + rctx_done(rctx, ISC_R_SUCCESS); + return ISC_R_COMPLETE; + } + + return ISC_R_SUCCESS; +} + static void resquery_response_continue(void *arg, isc_result_t result) { respctx_t *rctx = arg; @@ -7366,6 +7405,17 @@ resquery_response_continue(void *arg, isc_result_t result) { goto cleanup; } + /* + * Remember whether this message was signed or had a + * valid client cookie; if not, we may need to retry over + * TCP later. + */ + if (query->rmessage->cc_ok || query->rmessage->tsig != NULL || + query->rmessage->sig0 != NULL) + { + rctx->secured = true; + } + /* * The dispatcher should ensure we only get responses with QR * set. @@ -7373,13 +7423,21 @@ resquery_response_continue(void *arg, isc_result_t result) { INSIST((query->rmessage->flags & DNS_MESSAGEFLAG_QR) != 0); /* - * Check for cookie issues. + * Check for cookie issues; if found, maybe retry over TCP. */ result = rctx_cookiecheck(rctx); if (result == ISC_R_COMPLETE) { goto cleanup; } + /* + * Check whether we need to retry over TCP for some other reason. + */ + result = rctx_tcpretry(rctx); + if (result == ISC_R_COMPLETE) { + goto cleanup; + } + /* * Check for EDNS issues. */ @@ -8092,8 +8150,8 @@ rctx_answer_positive(respctx_t *rctx) { } /* - * Cache records in the authority section, if - * there are any suitable for caching. + * Cache records in the authority section, if there are + * any suitable for caching. */ rctx_authority_positive(rctx); @@ -8431,20 +8489,25 @@ rctx_answer_dname(respctx_t *rctx) { /* * rctx_authority_positive(): - * Examine the records in the authority section (if there are any) for a - * positive answer. We expect the names for all rdatasets in this - * section to be subdomains of the domain being queried; any that are - * not are skipped. We expect to find only *one* owner name; any names - * after the first one processed are ignored. We expect to find only - * rdatasets of type NS; all others are ignored. Whatever remains can - * be cached at trust level authauthority or additional - * (depending on whether the AA bit was set on the answer). + * If a positive answer was received over TCP or secured with a cookie + * or TSIG, examine the authority section. We expect names for all + * rdatasets in this section to be subdomains of the domain being queried; + * any that are not are skipped. We expect to find only *one* owner name; + * any names after the first one processed are ignored. We expect to find + * only rdatasets of type NS; all others are ignored. Whatever remains can + * be cached at trust level authauthority or additional (depending on + * whether the AA bit was set on the answer). */ static void rctx_authority_positive(respctx_t *rctx) { fetchctx_t *fctx = rctx->fctx; - dns_message_t *msg = rctx->query->rmessage; + + /* If it's spoofable, don't cache it. */ + if (!rctx->secured && (rctx->query->options & DNS_FETCHOPT_TCP) == 0) { + return; + } + MSG_SECTION_FOREACH(msg, DNS_SECTION_AUTHORITY, name) { if (!name_external(name, dns_rdatatype_ns, rctx) && dns_name_issubdomain(fctx->name, name)) From cffcab9d5f3e709002f331b72498fcc229786ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 19 Aug 2025 19:22:18 +0200 Subject: [PATCH 05/16] Use cryptographically-secure pseudo-random generator everywhere It was discovered in an upcoming academic paper that a xoshiro128** internal state can be recovered by an external 3rd party allowing to predict UDP ports and DNS IDs in the outgoing queries. This could lead to an attacker spoofing the DNS answers with great efficiency and poisoning the DNS cache. Change the internal random generator to system CSPRNG with buffering to avoid excessive syscalls. Thanks Omer Ben Simhon and Amit Klein of Hebrew University of Jerusalem for responsibly reporting this to us. Very cool research! --- lib/isc/include/isc/random.h | 2 +- lib/isc/random.c | 109 ++++++++--------------------------- tests/isc/random_test.c | 4 +- 3 files changed, 29 insertions(+), 86 deletions(-) diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h index 213e979ec6..f7638905c1 100644 --- a/lib/isc/include/isc/random.h +++ b/lib/isc/include/isc/random.h @@ -19,7 +19,7 @@ #include /*! \file isc/random.h - * \brief Implements wrapper around a non-cryptographically secure + * \brief Implements wrapper around a cryptographically secure * pseudo-random number generator. * */ diff --git a/lib/isc/random.c b/lib/isc/random.c index 88efd21c4e..666975c119 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -31,125 +31,66 @@ */ #include -#include -#include -#include +#include #include +#include #include -#include #include -#include #include -/* - * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) - * - * To the extent possible under law, the author has dedicated all - * copyright and related and neighboring rights to this software to the - * public domain worldwide. This software is distributed without any - * warranty. - * - * See . - */ +#define ISC_RANDOM_BUFSIZE (ISC_OS_CACHELINE_SIZE / sizeof(uint32_t)) -/* - * This is xoshiro128** 1.0, our 32-bit all-purpose, rock-solid generator. - * It has excellent (sub-ns) speed, a state size (128 bits) that is large - * enough for mild parallelism, and it passes all tests we are aware of. - * - * The state must be seeded so that it is not everywhere zero. - */ - -static thread_local bool initialized = false; -static thread_local uint32_t seed[4] = { 0 }; +thread_local static uint32_t isc__random_pool[ISC_RANDOM_BUFSIZE]; +thread_local static size_t isc__random_pos = ISC_RANDOM_BUFSIZE; static uint32_t -rotl(const uint32_t x, int k) { - return (x << k) | (x >> (32 - k)); -} - -static uint32_t -next(void) { - uint32_t result_starstar, t; - - result_starstar = rotl(seed[0] * 5, 7) * 9; - t = seed[1] << 9; - - seed[2] ^= seed[0]; - seed[3] ^= seed[1]; - seed[1] ^= seed[2]; - seed[0] ^= seed[3]; - - seed[2] ^= t; - - seed[3] = rotl(seed[3], 11); - - return result_starstar; -} - -static void -isc__random_initialize(void) { - if (initialized) { - return; - } - +random_u32(void) { #if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* - * A fixed seed helps with problem reproduction when fuzzing. It must be - * non-zero else xoshiro128starstar will generate only zeroes, and the - * first result needs to be non-zero as expected by random_test.c + * A fixed stream of numbers helps with problem reproduction when + * fuzzing. The first result needs to be non-zero as expected by + * random_test.c (it starts with ISC_RANDOM_BUFSIZE, see above). */ - seed[0] = 1; + return (uint32_t)(isc__random_pos++); #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ - while (seed[0] == 0 && seed[1] == 0 && seed[2] == 0 && seed[3] == 0) { - isc_entropy_get(seed, sizeof(seed)); + if (isc__random_pos == ISC_RANDOM_BUFSIZE) { + isc_entropy_get(isc__random_pool, sizeof(isc__random_pool)); + isc__random_pos = 0; } - initialized = true; + + return isc__random_pool[isc__random_pos++]; } uint8_t isc_random8(void) { - isc__random_initialize(); - return (uint8_t)next(); + return (uint8_t)random_u32(); } uint16_t isc_random16(void) { - isc__random_initialize(); - return (uint16_t)next(); + return (uint16_t)random_u32(); } uint32_t isc_random32(void) { - isc__random_initialize(); - return next(); + return random_u32(); } void isc_random_buf(void *buf, size_t buflen) { - REQUIRE(buf != NULL); - REQUIRE(buflen > 0); + REQUIRE(buflen == 0 || buf != NULL); - int i; - uint32_t r; - - isc__random_initialize(); - - for (i = 0; i + sizeof(r) <= buflen; i += sizeof(r)) { - r = next(); - memmove((uint8_t *)buf + i, &r, sizeof(r)); + if (buf == NULL || buflen == 0) { + return; } - r = next(); - memmove((uint8_t *)buf + i, &r, buflen % sizeof(r)); - return; + + isc_entropy_get(buf, buflen); } uint32_t isc_random_uniform(uint32_t limit) { - isc__random_initialize(); - /* * Daniel Lemire's nearly-divisionless unbiased bounded random numbers. * @@ -161,7 +102,7 @@ isc_random_uniform(uint32_t limit) { * integer part (upper 32 bits), and we will use the fraction part * (lower 32 bits) to determine whether or not we need to resample. */ - uint64_t num = (uint64_t)next() * (uint64_t)limit; + uint64_t num = (uint64_t)random_u32() * (uint64_t)limit; /* * In the fast path, we avoid doing a division in most cases by * comparing the fraction part of `num` with the limit, which is @@ -213,7 +154,7 @@ isc_random_uniform(uint32_t limit) { * our valid range, it is superfluous, and we resample. */ while ((uint32_t)(num) < residue) { - num = (uint64_t)next() * (uint64_t)limit; + num = (uint64_t)random_u32() * (uint64_t)limit; } } /* diff --git a/tests/isc/random_test.c b/tests/isc/random_test.c index 70bd4b6a79..a8cce6ceca 100644 --- a/tests/isc/random_test.c +++ b/tests/isc/random_test.c @@ -321,7 +321,9 @@ random_test(pvalue_func_t *func, isc_random_func test_func) { } break; case ISC_RANDOM_BYTES: - isc_random_buf(values, sizeof(values)); + for (i = 0; i < ARRAY_SIZE(values); i++) { + values[i] = isc_random32(); + } break; case ISC_RANDOM_UNIFORM: uniform_values = (uint16_t *)values; From 4db9e5d90e290f77718f8e1e0a64c3e1a8fe34f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 25 Aug 2025 19:02:54 +0200 Subject: [PATCH 06/16] Use arc4random for CSPRNG when available Use arc4random on platforms where available. arc4random() provides high quality cryptographically-secure pseudo-random numbers and is generally recommended for application use. The uv_random() call unfortunately uses getentropy() on platforms like MacOS, OpenBSD or NetBSD which is not recommended for application use. --- lib/isc/entropy.c | 24 ------------------------ lib/isc/hash.c | 3 +-- lib/isc/hashmap.c | 1 - lib/isc/include/isc/entropy.h | 29 ----------------------------- lib/isc/include/isc/nonce.h | 8 ++++++-- lib/isc/include/isc/random.h | 35 +++++++++++++++++++++++------------ lib/isc/meson.build | 2 -- lib/isc/nonce.c | 20 -------------------- lib/isc/random.c | 34 ++++++++++++---------------------- meson.build | 3 +++ 10 files changed, 45 insertions(+), 114 deletions(-) delete mode 100644 lib/isc/entropy.c delete mode 100644 lib/isc/include/isc/entropy.h delete mode 100644 lib/isc/nonce.c diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c deleted file mode 100644 index a037960bd1..0000000000 --- a/lib/isc/entropy.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include -#include -#include - -void -isc_entropy_get(void *buf, size_t buflen) { - int r = uv_random(NULL, NULL, buf, buflen, 0, NULL); - - UV_RUNTIME_CHECK(uv_random, r); -} diff --git a/lib/isc/hash.c b/lib/isc/hash.c index 387e2373cd..49b942ef5b 100644 --- a/lib/isc/hash.c +++ b/lib/isc/hash.c @@ -16,7 +16,6 @@ #include #include -#include #include /* IWYU pragma: keep */ #include #include @@ -35,7 +34,7 @@ isc__hash_initialize(void) { */ uint8_t key[16] = { 1 }; #if !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - isc_entropy_get(key, sizeof(key)); + isc_random_buf(key, sizeof(key)); #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ STATIC_ASSERT(sizeof(key) >= sizeof(isc_hash_key), "sizeof(key) < sizeof(isc_hash_key)"); diff --git a/lib/isc/hashmap.c b/lib/isc/hashmap.c index d8c2bd58ae..87b1a3f21a 100644 --- a/lib/isc/hashmap.c +++ b/lib/isc/hashmap.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h deleted file mode 100644 index 81c2ed7cac..0000000000 --- a/lib/isc/include/isc/entropy.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -#include - -/*! \file isc/entropy.h - * \brief Implements wrapper around CSPRNG cryptographic library calls - * for getting cryptographically secure pseudo-random numbers. - * - * Uses synchronous version of uv_random(). - */ - -void -isc_entropy_get(void *buf, size_t buflen); -/*!< - * \brief Get cryptographically-secure pseudo-random data. - */ diff --git a/lib/isc/include/isc/nonce.h b/lib/isc/include/isc/nonce.h index ce15b7e12a..b61270bd82 100644 --- a/lib/isc/include/isc/nonce.h +++ b/lib/isc/include/isc/nonce.h @@ -15,12 +15,16 @@ #include +#include + /*! \file isc/nonce.h * \brief Provides a function for generating an arbitrarily long nonce. */ -void -isc_nonce_buf(void *buf, size_t buflen); +static inline void +isc_nonce_buf(void *buf, size_t buflen) { + isc_random_buf(buf, buflen); +} /*!< * Fill 'buf', up to 'buflen' bytes, with random data from the * crypto provider's random function. diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h index f7638905c1..efee399095 100644 --- a/lib/isc/include/isc/random.h +++ b/lib/isc/include/isc/random.h @@ -24,18 +24,11 @@ * */ -uint8_t -isc_random8(void); -/*!< - * \brief Returns a single 8-bit random value. - */ - -uint16_t -isc_random16(void); -/*!< - * \brief Returns a single 16-bit random value. - */ - +#if HAVE_ARC4RANDOM && !defined(__linux__) +#define isc_random32() arc4random() +#define isc_random_buf(buf, buflen) arc4random_buf(buf, buflen) +#define isc_random_uniform(upper_bound) arc4random_uniform(upper_bound) +#else /* HAVE_ARC4RANDOM && !defined(__linux__) */ uint32_t isc_random32(void); /*!< @@ -64,3 +57,21 @@ isc_random_uniform(uint32_t upper_bound); * resample is very small when the upper_bound is small, rising to 0.5 * when upper_bound is UINT32_MAX/2. */ + +#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */ + +static inline uint8_t +isc_random8(void) { + return (uint8_t)isc_random32(); +} +/*!< + * \brief Returns a single 8-bit random value. + */ + +static inline uint16_t +isc_random16(void) { + return (uint16_t)isc_random32(); +} +/*!< + * \brief Returns a single 16-bit random value. + */ diff --git a/lib/isc/meson.build b/lib/isc/meson.build index 0e8e9cf0b3..d4db21672e 100644 --- a/lib/isc/meson.build +++ b/lib/isc/meson.build @@ -77,7 +77,6 @@ isc_srcset.add( 'counter.c', 'crypto.c', 'dir.c', - 'entropy.c', 'errno.c', 'errno2result.c', 'error.c', @@ -106,7 +105,6 @@ isc_srcset.add( 'net.c', 'netaddr.c', 'netscope.c', - 'nonce.c', 'openssl_shim.c', 'os.c', 'parseint.c', diff --git a/lib/isc/nonce.c b/lib/isc/nonce.c deleted file mode 100644 index 316498a613..0000000000 --- a/lib/isc/nonce.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#include -#include - -void -isc_nonce_buf(void *buf, size_t buflen) { - isc_entropy_get(buf, buflen); -} diff --git a/lib/isc/random.c b/lib/isc/random.c index 666975c119..1367fd5a12 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -30,22 +30,24 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if !HAVE_ARC4RANDOM || defined(__linux__) + #include #include -#include #include #include #include #include +#include #define ISC_RANDOM_BUFSIZE (ISC_OS_CACHELINE_SIZE / sizeof(uint32_t)) thread_local static uint32_t isc__random_pool[ISC_RANDOM_BUFSIZE]; thread_local static size_t isc__random_pos = ISC_RANDOM_BUFSIZE; -static uint32_t -random_u32(void) { +uint32_t +isc_random32(void) { #if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* * A fixed stream of numbers helps with problem reproduction when @@ -56,28 +58,13 @@ random_u32(void) { #endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ if (isc__random_pos == ISC_RANDOM_BUFSIZE) { - isc_entropy_get(isc__random_pool, sizeof(isc__random_pool)); + isc_random_buf(isc__random_pool, sizeof(isc__random_pool)); isc__random_pos = 0; } return isc__random_pool[isc__random_pos++]; } -uint8_t -isc_random8(void) { - return (uint8_t)random_u32(); -} - -uint16_t -isc_random16(void) { - return (uint16_t)random_u32(); -} - -uint32_t -isc_random32(void) { - return random_u32(); -} - void isc_random_buf(void *buf, size_t buflen) { REQUIRE(buflen == 0 || buf != NULL); @@ -86,7 +73,8 @@ isc_random_buf(void *buf, size_t buflen) { return; } - isc_entropy_get(buf, buflen); + int r = uv_random(NULL, NULL, buf, buflen, 0, NULL); + UV_RUNTIME_CHECK(uv_random, r); } uint32_t @@ -102,7 +90,7 @@ isc_random_uniform(uint32_t limit) { * integer part (upper 32 bits), and we will use the fraction part * (lower 32 bits) to determine whether or not we need to resample. */ - uint64_t num = (uint64_t)random_u32() * (uint64_t)limit; + uint64_t num = (uint64_t)isc_random32() * (uint64_t)limit; /* * In the fast path, we avoid doing a division in most cases by * comparing the fraction part of `num` with the limit, which is @@ -154,7 +142,7 @@ isc_random_uniform(uint32_t limit) { * our valid range, it is superfluous, and we resample. */ while ((uint32_t)(num) < residue) { - num = (uint64_t)random_u32() * (uint64_t)limit; + num = (uint64_t)isc_random32() * (uint64_t)limit; } } /* @@ -162,3 +150,5 @@ isc_random_uniform(uint32_t limit) { */ return (uint32_t)(num >> 32); } + +#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */ diff --git a/meson.build b/meson.build index f614dfe422..9322379457 100644 --- a/meson.build +++ b/meson.build @@ -519,6 +519,9 @@ foreach fn, header : { 'sched_getaffinity': '#include ', 'sched_yield': '#include ', + # CSPRNG + 'arc4random': '#include ', + # Misc. 'chroot': '#include ', 'clock_gettime': '#include ', From 3a6b756179a2bb15909f6366e999fb62e5fee304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 2 Oct 2025 18:12:18 +0200 Subject: [PATCH 07/16] Generate changelog for BIND 9.21.13 --- doc/arm/changelog.rst | 1 + doc/changelog/changelog-9.21.13.rst | 436 ++++++++++++++++++++++++++++ 2 files changed, 437 insertions(+) create mode 100644 doc/changelog/changelog-9.21.13.rst diff --git a/doc/arm/changelog.rst b/doc/arm/changelog.rst index 9f0c194a97..5d6b31ec83 100644 --- a/doc/arm/changelog.rst +++ b/doc/arm/changelog.rst @@ -18,6 +18,7 @@ Changelog development. Regular users should refer to :ref:`Release Notes ` for changes relevant to them. +.. include:: ../changelog/changelog-9.21.13.rst .. include:: ../changelog/changelog-9.21.12.rst .. include:: ../changelog/changelog-9.21.11.rst .. include:: ../changelog/changelog-9.21.10.rst diff --git a/doc/changelog/changelog-9.21.13.rst b/doc/changelog/changelog-9.21.13.rst new file mode 100644 index 0000000000..78c8ed3f41 --- /dev/null +++ b/doc/changelog/changelog-9.21.13.rst @@ -0,0 +1,436 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +BIND 9.21.13 +------------ + +Security Fixes +~~~~~~~~~~~~~~ + +- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY + is found. ``1d851c23529`` + + Previously, if a matching but cryptographically invalid key was + encountered during DNSSEC validation, the key was skipped and not + counted towards validation failures. :iscman:`named` now treats such + DNSSEC keys as hard failures and the DNSSEC validation fails + immediately, instead of continuing with the next DNSKEYs in the RRset. + + ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One + Security and Privacy Laboratory at Nankai University for bringing this + vulnerability to our attention. :gl:`#5343` + +- [CVE-2025-40778] Address various spoofing attacks. ``7b95c382dbd`` + + Previously, several issues could be exploited to poison a DNS cache + with spoofed records for zones which were not DNSSEC-signed or if the + resolver was configured to not do DNSSEC validation. These issues were + assigned CVE-2025-40778 and have now been fixed. + + As an additional layer of protection, :iscman:`named` no longer + accepts DNAME records or extraneous NS records in the AUTHORITY + section unless these are received via spoofing-resistant transport + (TCP, UDP with DNS cookies, TSIG, or SIG(0)). + + ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin + Duan from Tsinghua University for bringing this vulnerability to our + attention. :gl:`#5414` + +- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number + generator. ``6876753c7cc`` + + It was discovered during research for an upcoming academic paper that + a xoshiro128\*\* internal state can be recovered by an external 3rd + party, allowing the prediction of UDP ports and DNS IDs in outgoing + queries. This could lead to an attacker spoofing the DNS answers with + great efficiency and poisoning the DNS cache. + + The internal random generator has been changed to a cryptographically + secure pseudo-random generator. + + ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from + Hebrew University of Jerusalem for bringing this vulnerability to our + attention. :gl:`#5484` + +New Features +~~~~~~~~~~~~ + +- Add extra tokens to the zone file name template. ``b449fa95005`` + + Extend the `$name`, `$view` and `$type` tokens (expanding into the + zone name, zone's view name and type); the new following tokens are + now also accepted: + + - `$name` or `%s` is replaced with the zone name in lower case; - + `$type` or `%t` is replaced with the zone type -- i.e., primary, + secondary, etc); - `$view` or `%v` is replaced with the view name; - + `$char1` or `%1` is replaced with the first character of the zone + name; - `$char2` or `%2` is replaced with the second character of the + zone name (or a dot if there is no second character); - `$char3` or + `%3` is replaced with the third character of the zone name (or a dot + if there is no third character); - `$label1` or `%z` is replaced with + the toplevel domain of the zone (or a dot if it is the root zone); - + `$label2` or `%y` is replaced with the next label under the toplevel + domain (or a dot if there is no next label); - `$label3` or `%x` is + replaced with the next-next label under the toplevel domain (or a + dot if there is no next-next label). :gl:`#85` :gl:`!10779` + +- Add support for synthetic records. ``cefed841046`` + + Add a query plugin which, in "reverse" mode, enables the server to + build a synthesized response to a PTR query when the PTR record + requested is not found in the zone. The dynamically-built name is + constructed from a static prefix (passed as a plugin parameter), the + IP address (extracted from the query name) and a suffix (also passed + as a plugin parameter). An `allow-synth` address-match list can be + used to limit the network addresses for which the plugin may generate + responses. The plugin can also be used in "forward" mode, to + build synthesized A/AAAA records from names using the same format as + the dynamically-built PTR names. The same parameters are used: the + plugin will react and answer a query if the name matches the + configured prefix and origin, and encodes an IP address that is within + `allow-synth`. :gl:`#1586` :gl:`!10348` + +- Support for zone-specific plugins. ``65fa5693572`` + + Query plugins can now be configured at the `zone` level, as well as + globally or at the `view` level. A plugin's hooks are then called only + while that specific zone's database is being used to answer a query. + + This simplifies the implementation of plugins that are only needed for + specific namespaces for which the server is authoritative. It can also + enable quicker responses, since plugins will only be called when they + are needed. :gl:`#5356` :gl:`!10483` + +- Add dnssec-policy keys configuration check to named-checkconf. + ``23a79b42ea4`` + + A new option `-k` is added to `named-checkconf` that allows checking + the `dnssec-policy` `keys` configuration against the configured key + stores. If the found key files are not in sync with the given + `dnssec-policy`, the check will fail. + + This is useful to run before migrating to `dnssec-policy`. :gl:`#5486` + :gl:`!10907` + +Removed Features +~~~~~~~~~~~~~~~~ + +- Remove randomized RRset ordering. ``014a05a2781`` + + The rrset-order random doesn't offer uniform distribution of all + permutations and it isn't superior to cyclic order in any way. Make + the random ordering an alias to the cyclic ordering. :gl:`#5513` + :gl:`!10912` + +- Remove CHECK_FOR_GLUE_IN_ANSWER. ``7fa4cbedc50`` + + Macro CHECK_FOR_GLUE_IN_ANSWER is defined in `lib/dns/resolver.c` + only, documented nowhere and not exposed as build configuration. This + is valid at least for 9.21+, 9.20 and 9.18. Furthermore, it doesn't + compile anymore on 9.21+ with -DCHECK_FOR_GLUE_IN_ANSWER=1. + + Considering it is very unlikely that anyone build named with this, + remove the code rather than fixing it. :gl:`#5538` :gl:`!11029` + +- Remove orphan dns_loadmgr_t type. ``96855b5449f`` + + dns_loadmgr_t typedef is declared but never defines as well as a + pointer of this type in named_server_t. Removing it. :gl:`!10974` + +Feature Changes +~~~~~~~~~~~~~~~ + +- Add a circular reference between slabtops for type and RRSIG(type) + ``a20c8fe74b0`` + + Previously, the slabtops for "type" and its signature was only loosely + coupled and the headers could expire at different time (both TTL and + LRU based expiry). Add a .related member to the slabtop that allows + us to expire the headers in both related headers and also optimize the + lookups because now both slabtops are looked up at the same time. + :gl:`#3396` :gl:`!10985` + +- Refactor view creation/configuration loops in dedicated functions. + ``cb0807be2be`` + + Refactor a bit of `apply_configuration` by extracting (into respective + dedicated function) the logic to build the keystores list, the KASP + list as well as creating the view/zones and configuring those. This is + the next step of MR !10895 and !10901 + + While the code is extracted, some global variables has been changed + into a function parameters which enable to have a clear view of the + dependency of the function, typically, to know if it depends on local + configuration object or runtime "production" object. The end goal (not + in this MR, but later on) is to move as much as possible + initialization logic outside of the exclusive mode. + + As a first step, latest commits move the keystores list, KASP list and + view/zones creation outside of the exclusive mode. (The view/zone + configuration remain in exclusive mode for now, because of a + dependency to the runtime "cachelist". This is the target of a next + MR. + + For the record; while moving the keystores list, KASP list and + view/zone creation doesn't have a significant impact on the time the + exclusive mode is taken (from my experiment on a 1M small zones + instance); moving `configure_views` did have a _massive_ impact + (basically, the time spend in the exclusive mode is then non + calculable). Configuring views outside the exclusive mode needs more + work, which will be done in future MRs. :gl:`#4673` :gl:`!10910` + +- Add option to always build fuzz binaries. ``54c8252c6e2`` + + Currently the fuzzer binaries are only built when someone requests a + fuzzer. This might cause us to inadvertently break fuzzing when + changing function signatures. It also deviates with the behaviour we + had with autotools, where the fuzz binaries were built with make test. + + This commit splits the -Dfuzzing option into two: fuzzing, and + fuzzing-backend. The fuzzing option controls whether the fuzzing + binaries are built. The fuzzing-backend option controls which backend + to use, and defaults to none. If the value none is used the binaries + are built, but no backend is used or guaranteed, which means that the + binaries might be non-functional. :gl:`#5526` :gl:`!10990` + +- Rename cfg_aclconfctx_t variables to aclctx. ``0411142f826`` + + ACL configuration context variables are inconsistently named as + `actx`, `ac`, or `aclconfctx`, which caused confusion during code + reviews. This commit renames all `cfg_aclconfctx_t` variables to + `aclctx`, which is short, consistent, and unambiguous. :gl:`#5530` + :gl:`!11003` + +- Provide more context when registering plugins. ``ac4cf4cce8d`` + + Add a new type, `ns_pluginregister_ctx_t`, which is passed to + `plugin_register()` in place of the `source` parameter. The source + value is now just part of the structure, which also holds a pointer to + the zone origin if the plugin is loaded at a zone level. This + provides more contextual information, enabling the plugin to make + specific configuration decisions based on the name of the zone for + which it is loaded. It's also flexible if more contextual data + are needed in the future: add a new field to + `ns_pluginregister_ctx_t`, and new plugins can use it without + affecting compatibility with existing plugins. :gl:`#5533` + :gl:`!11019` + +- Add option to compile named with static linking and LTO. + ``b6971fb7240`` + + Statically linking lib{isc,dns,ns,cfg,isccc} and enabling LTO shows + over 10% improvements on all almost measurements in perflab. That + said, we can't use Meson's option for LTO since it would result in + every binary being compiled with LTO and a great increase in compile + time. + + To work around it, we add a configuration option that enables LTO and + static linking only for the `named` binary. :gl:`!10761` + +- Convert slabtop and slabheader to use the cds list. ``7443ff330cc`` + + This is the first MR in series that aims to reduce the node locking by + replacing the single-linked list of slabtop(s) and slabheader(s) with + CDS linked list. This commit doesn't do anything else beyond + replacing .next and .down links with the cds_list_head. The RCU + semantics will be added later. :gl:`!10944` + +- Make the database ownercase modifiable only via addrdataset() + ``dbc47312925`` + + Simplify the implementation around the database ownercase. Remove the + dns_rdataset_setownercase() implementation for the slabheaders and + only allow setting ownercase on rdatalists and rdatasets. The + ownercase in the database can now be set only with + dns_db_addrdataset() by passing rdataset with correctly set ownercase. + :gl:`!10971` + +- Minor refactor of dst code. ``f5af3e431b9`` + + Convert the defines to enums. Initialize the tags more explicitly and + less ugly. :gl:`!11000` + +- Rename ns_pluginregister_ctx_t into ns_pluginctx_t. ``029a7152bba`` + + The type `ns_pluginregister_ctx_t` was initially added to pass plugin + contextual data when the plugin is registered, but this is also now + passed into `plugin_check`. Furthermore, those various data are not + specific to the registration in particular. Rename the type into + `ns_pluginctx_t` for clarity. :gl:`!11035` + +- Simplify nchildren count in isc_nm_listenudp. ``722ce92f107`` + + Slight simplification of the logic to define .nchildren listening UDP + socket. :gl:`!10978` + +- Squash the qpcache tree and nsec tries. ``22803b93e3f`` + + The dns_qpcache already had all the namespace changes needed to put + the normal data and auxiliary NSEC data into a single tree. Remove + the extra nsec QP trie and use the single QP trie for all the cache + data. :gl:`!10975` + +- Use lock-free hashtable for storing resolver fetch contexts. + ``0ac744ee4de`` + + Replace the locked hashmap with the lock-free hashtable from the RCU + library and protect the fetch contexts against reuse by replacing the + libisc reference counting with urcu_ref that can soft-fail in + situation where the reference count is already zero. This allows us + to easily skip re-using the fetch context if it is already in process + of being destroyed. :gl:`!10653` + +Bug Fixes +~~~~~~~~~ + +- Use signer name when disabling DNSSEC algorithms. ``7e0318df857`` + + ``disable-algorithms`` could cause DNSSEC validation failures when the + parent zone was signed with the algorithms that were being disabled + for the child zone. This has been fixed; `disable-algorithms` now + works on a whole-of-zone basis. + + If the zone's name is at or below the ``disable-algorithms`` name the + algorithm is disabled for that zone, using deepest match when there + are multiple ``disable-algorithms`` clauses. :gl:`#5165` :gl:`!10837` + +- Rndc sign during ZSK rollover will now replace signatures. + ``6246f9d7cb1`` + + When performing a ZSK rollover, if the new DNSKEY is omnipresent, the + :option:`rndc sign` command now signs the zone completely with the + successor key, replacing all zone signatures from the predecessor key + with new ones. :gl:`#5483` :gl:`!10867` + +- Missing DNSSEC information when CD bit is set in query. + ``5fcc063ce9a`` + + The RRSIGs for glue records were not being cached correctly for CD=1 + queries. This has been fixed. :gl:`#5502` :gl:`!10938` + +- Fix datarace between unlocking fctx lock and shuttingdown fctx. + ``2924f59cb3e`` + + There was a data race where new fetch response could be added to the + fetch context after we unlock the fetch context and before we shut it + down. This could cause assertion failure when fctx__done() was called + with ISC_R_SUCCESS because there was originally no fetch response, but + new fetch response without associated dataset was added before we had + a chance to shutdown the fetch context. This manifested in the + validated() callback, where cache_rrset() now returns ISC_R_SUCCESS + instead of DNS_R_UNCHANGED when cache was not changed. However the + data race was wrong on a general level. + + Add new argument to fctx__done() that allows to call it with + fctx->lock already acquired to prevent these data races. :gl:`#5507` + :gl:`!10961` + +- Add chroot check to meson.build. ``f2f2488bbe1`` + + The meson build procedure was not checking for the existence of the + chroot function. This has been fixed. :gl:`#5519` :gl:`!10973` + +- Preserve cache when reload fails and reload the server again. + ``33bcff46d30`` + + Fixes an issue where failing to reconfigure/reload the server would + prevent to preserved the views caches on the subsequent server + reconfiguration/reload. :gl:`#5523` :gl:`!10984` + +- Apply_configuration: leave exclusive mode after viewlist cleanup. + ``5c53695bf32`` + + When a re-configuration fails, `apply_configuration` flows jump to a + cleanup label and, at some point, leave the exclusive mode and cleanup + the viewlist. It looks fine as the viewlist is at this point only + locally known (if this is a configuration failure, this is the new + view list, if this is a success, this is the old list which has been + swapped out from the production list during the exclusive mode). + + However, the view and zone initialization code enqueues job callbacks, + for instance from `dns_zone_setsigninginterval` (but there are others + cases) which will be called for the new views and zones after the + exclusive mode is over. + + Depending where the configuration fails, those views and zones can be + half-configured, for instance a view might have an unfrozen resolver. + Hence, leaving the exclusive mode before cleaning up those views ans + zones will immediately called the previously enqueued callbacks and + lead to this reconfiguration-failure crash stack: + + ``` isc_assertion_failed dns_resolver_createfetch do_keyfetch + isc__async_cb ... uv_run loop_thread thread_body thread_run + start_thread ... ``` + + To avoid the problem, the views are now cleaned up before leaving the + exclusive mode (which also clean up the zones and enqueued callbacks). + + As context, the bug was introduced by !10910 which moved the creation + (not configuration) of the view outsides of the exclusive mode. This + is a safe move (as at this point, the newly view are only known + locally by `apply_configuration`) but the re-order was wrong regarding + the point where the exclusive mode was ended (before the change, the + exclusive mode as always ended before the new view are detached). + :gl:`!11016` + +- Check plugin config before registering. ``0e575d150fd`` + + In `named_config_parsefile()`, when checking the validity of + `named.conf`, the checking of plugin correctness was deliberately + postponed until the plugin is loaded and registered. However, the + checking was never actually done: the `plugin_register()` + implementation was called, but `plugin_check()` was not. + + `ns_plugin_register()` (used by `named`) now calls the check function + before the register function, and aborts if either one fails. + `ns_plugin_check()` (used by `named-checkconf`) calls only the check + function. :gl:`!11031` + +- Clean up the dns_db API. ``29fc7850f1e`` + + Some of the API calls in `dns_db` were obsolete, and have been + removed. Others were more complicated than necessary, and have been + refactored to simplify. :gl:`!10830` + +- Do not inline dns_zone_gethooktable. ``e7156fe57ae`` + + Since !10959 `dns_zone_gethooktable()` is only called once per query, + and the suspicion (from perflab analysis) that this (simple, as just + returning a pointer) call was slowing things down (perhaps because of + code locality reasons?) doesn't matter anymore. So even if !10959 + inlined it, it shouldn't matter anymore. :gl:`!10962` + +- Fix detection of whether node is active in find_wildcard() + ``f717bad1086`` + + The current code would fail during the write transaction. The first + header would not match the search->serial and the node might be + incorrectly detected as inactive. :gl:`!10972` + +- Hookasyncctx renaming. ``6ec65c3d1ad`` + + The field `ns_hookasync_t` was initially named `hook_actx` and wrongly + renamed `hook_aclctx` during a mass-renaming of various names for the + config acl context into a consistent `aclctx` name (see !11003). Of + course this is wrong as `ns_hookasync_t` has nothing to do with ACL + but about _async_ context. This commit fixes the mistake by renaming + this field `hookasyncctx` :gl:`!11021` + +- Minimize zone hooktable lookups. ``89039e0d78e`` + + Merging !10483 caused a performance regression because the zone + hooktable had to be looked up every time a hook point was reached, + even if no zone plugins were configured. We now look up the zone + hooktable when a zone is attached to the query context, and keep a + pointer to it until the qctx is destroyed. :gl:`!10959` + + From 40a62df4f08994d311569a4bfbc311f220b2a4c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 2 Oct 2025 18:12:18 +0200 Subject: [PATCH 08/16] Prepare release notes for BIND 9.21.13 --- doc/arm/notes.rst | 1 + doc/notes/notes-9.21.13.rst | 168 ++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 doc/notes/notes-9.21.13.rst diff --git a/doc/arm/notes.rst b/doc/arm/notes.rst index 9a5a74633c..83686dc00e 100644 --- a/doc/arm/notes.rst +++ b/doc/arm/notes.rst @@ -47,6 +47,7 @@ The list of known issues affecting the latest version in the 9.21 branch can be found at https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21 +.. include:: ../notes/notes-9.21.13.rst .. include:: ../notes/notes-9.21.12.rst .. include:: ../notes/notes-9.21.11.rst .. include:: ../notes/notes-9.21.10.rst diff --git a/doc/notes/notes-9.21.13.rst b/doc/notes/notes-9.21.13.rst new file mode 100644 index 0000000000..3462b96d98 --- /dev/null +++ b/doc/notes/notes-9.21.13.rst @@ -0,0 +1,168 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +Notes for BIND 9.21.13 +---------------------- + +Security Fixes +~~~~~~~~~~~~~~ + +- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY + is found. + + Previously, if a matching but cryptographically invalid key was + encountered during DNSSEC validation, the key was skipped and not + counted towards validation failures. :iscman:`named` now treats such + DNSSEC keys as hard failures and the DNSSEC validation fails + immediately, instead of continuing with the next DNSKEYs in the RRset. + + ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One + Security and Privacy Laboratory at Nankai University for bringing this + vulnerability to our attention. :gl:`#5343` + +- [CVE-2025-40778] Address various spoofing attacks. + + Previously, several issues could be exploited to poison a DNS cache + with spoofed records for zones which were not DNSSEC-signed or if the + resolver was configured to not do DNSSEC validation. These issues were + assigned CVE-2025-40778 and have now been fixed. + + As an additional layer of protection, :iscman:`named` no longer + accepts DNAME records or extraneous NS records in the AUTHORITY + section unless these are received via spoofing-resistant transport + (TCP, UDP with DNS cookies, TSIG, or SIG(0)). + + ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin + Duan from Tsinghua University for bringing this vulnerability to our + attention. :gl:`#5414` + +- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number + generator. + + It was discovered during research for an upcoming academic paper that + a xoshiro128\*\* internal state can be recovered by an external 3rd + party, allowing the prediction of UDP ports and DNS IDs in outgoing + queries. This could lead to an attacker spoofing the DNS answers with + great efficiency and poisoning the DNS cache. + + The internal random generator has been changed to a cryptographically + secure pseudo-random generator. + + ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from + Hebrew University of Jerusalem for bringing this vulnerability to our + attention. :gl:`#5484` + +New Features +~~~~~~~~~~~~ + +- Add extra tokens to the zone file name template. + + Extend the `$name`, `$view` and `$type` tokens (expanding into the + zone name, zone's view name and type); the new following tokens are + now also accepted: + + - `$name` or `%s` is replaced with the zone name in lower case; - + `$type` or `%t` is replaced with the zone type -- i.e., primary, + secondary, etc); - `$view` or `%v` is replaced with the view name; - + `$char1` or `%1` is replaced with the first character of the zone + name; - `$char2` or `%2` is replaced with the second character of the + zone name (or a dot if there is no second character); - `$char3` or + `%3` is replaced with the third character of the zone name (or a dot + if there is no third character); - `$label1` or `%z` is replaced with + the toplevel domain of the zone (or a dot if it is the root zone); - + `$label2` or `%y` is replaced with the next label under the toplevel + domain (or a dot if there is no next label); - `$label3` or `%x` is + replaced with the next-next label under the toplevel domain (or a + dot if there is no next-next label). :gl:`#85` + +- Add support for synthetic records. + + Add a query plugin which, in "reverse" mode, enables the server to + build a synthesized response to a PTR query when the PTR record + requested is not found in the zone. The dynamically-built name is + constructed from a static prefix (passed as a plugin parameter), the + IP address (extracted from the query name) and a suffix (also passed + as a plugin parameter). An `allow-synth` address-match list can be + used to limit the network addresses for which the plugin may generate + responses. The plugin can also be used in "forward" mode, to + build synthesized A/AAAA records from names using the same format as + the dynamically-built PTR names. The same parameters are used: the + plugin will react and answer a query if the name matches the + configured prefix and origin, and encodes an IP address that is within + `allow-synth`. :gl:`#1586` + +- Support for zone-specific plugins. + + Query plugins can now be configured at the `zone` level, as well as + globally or at the `view` level. A plugin's hooks are then called only + while that specific zone's database is being used to answer a query. + + This simplifies the implementation of plugins that are only needed for + specific namespaces for which the server is authoritative. It can also + enable quicker responses, since plugins will only be called when they + are needed. :gl:`#5356` + +- Add dnssec-policy keys configuration check to named-checkconf. + + A new option `-k` is added to `named-checkconf` that allows checking + the `dnssec-policy` `keys` configuration against the configured key + stores. If the found key files are not in sync with the given + `dnssec-policy`, the check will fail. + + This is useful to run before migrating to `dnssec-policy`. :gl:`#5486` + +Removed Features +~~~~~~~~~~~~~~~~ + +- Remove randomized RRset ordering. + + The rrset-order random doesn't offer uniform distribution of all + permutations and it isn't superior to cyclic order in any way. Make + the random ordering an alias to the cyclic ordering. :gl:`#5513` + +Bug Fixes +~~~~~~~~~ + +- Use signer name when disabling DNSSEC algorithms. + + ``disable-algorithms`` could cause DNSSEC validation failures when the + parent zone was signed with the algorithms that were being disabled + for the child zone. This has been fixed; `disable-algorithms` now + works on a whole-of-zone basis. + + If the zone's name is at or below the ``disable-algorithms`` name the + algorithm is disabled for that zone, using deepest match when there + are multiple ``disable-algorithms`` clauses. :gl:`#5165` + +- Rndc sign during ZSK rollover will now replace signatures. + + When performing a ZSK rollover, if the new DNSKEY is omnipresent, the + :option:`rndc sign` command now signs the zone completely with the + successor key, replacing all zone signatures from the predecessor key + with new ones. :gl:`#5483` + +- Missing DNSSEC information when CD bit is set in query. + + The RRSIGs for glue records were not being cached correctly for CD=1 + queries. This has been fixed. :gl:`#5502` + +- Add chroot check to meson.build. + + The meson build procedure was not checking for the existence of the + chroot function. This has been fixed. :gl:`#5519` + +- Preserve cache when reload fails and reload the server again. + + Fixes an issue where failing to reconfigure/reload the server would + prevent to preserved the views caches on the subsequent server + reconfiguration/reload. :gl:`#5523` + + From 63a93a1a079f4a50baa2e531452a7bbb43b75e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 2 Oct 2025 18:12:18 +0200 Subject: [PATCH 09/16] Tweak and reword release notes --- doc/changelog/changelog-9.21.13.rst | 31 ++++--- doc/notes/notes-9.21.13.rst | 124 +++++++++++++--------------- 2 files changed, 75 insertions(+), 80 deletions(-) diff --git a/doc/changelog/changelog-9.21.13.rst b/doc/changelog/changelog-9.21.13.rst index 78c8ed3f41..375d83168c 100644 --- a/doc/changelog/changelog-9.21.13.rst +++ b/doc/changelog/changelog-9.21.13.rst @@ -69,19 +69,24 @@ New Features zone name, zone's view name and type); the new following tokens are now also accepted: - - `$name` or `%s` is replaced with the zone name in lower case; - - `$type` or `%t` is replaced with the zone type -- i.e., primary, - secondary, etc); - `$view` or `%v` is replaced with the view name; - - `$char1` or `%1` is replaced with the first character of the zone - name; - `$char2` or `%2` is replaced with the second character of the - zone name (or a dot if there is no second character); - `$char3` or - `%3` is replaced with the third character of the zone name (or a dot - if there is no third character); - `$label1` or `%z` is replaced with - the toplevel domain of the zone (or a dot if it is the root zone); - - `$label2` or `%y` is replaced with the next label under the toplevel - domain (or a dot if there is no next label); - `$label3` or `%x` is - replaced with the next-next label under the toplevel domain (or a - dot if there is no next-next label). :gl:`#85` :gl:`!10779` + - `$name` or `%s` is replaced with the zone name in lower case; + - `$type` or `%t` is replaced with the zone type -- i.e., primary, + secondary, etc); + - `$view` or `%v` is replaced with the view name; + - `$char1` or `%1` is replaced with the first character of the zone + name; + - `$char2` or `%2` is replaced with the second character of the zone + name (or a dot if there is no second character); + - `$char3` or `%3` is replaced with the third character of the zone + name (or a dot if there is no third character); + - `$label1` or `%z` is replaced with the toplevel domain of the zone + (or a dot if it is the root zone); + - `$label2` or `%y` is replaced with the next label under the toplevel + domain (or a dot if there is no next label); + - `$label3` or `%x` is replaced with the next-next label under the + toplevel domain (or a dot if there is no next-next label). + + :gl:`#85` :gl:`!10779` - Add support for synthetic records. ``cefed841046`` diff --git a/doc/notes/notes-9.21.13.rst b/doc/notes/notes-9.21.13.rst index 3462b96d98..5fb5d95a41 100644 --- a/doc/notes/notes-9.21.13.rst +++ b/doc/notes/notes-9.21.13.rst @@ -15,8 +15,8 @@ Notes for BIND 9.21.13 Security Fixes ~~~~~~~~~~~~~~ -- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY - is found. +- DNSSEC validation fails if matching but invalid DNSKEY is found. + :cve:`2025-8677` Previously, if a matching but cryptographically invalid key was encountered during DNSSEC validation, the key was skipped and not @@ -28,7 +28,7 @@ Security Fixes Security and Privacy Laboratory at Nankai University for bringing this vulnerability to our attention. :gl:`#5343` -- [CVE-2025-40778] Address various spoofing attacks. +- Address various spoofing attacks. :cve:`2025-40778` Previously, several issues could be exploited to poison a DNS cache with spoofed records for zones which were not DNSSEC-signed or if the @@ -44,8 +44,8 @@ Security Fixes Duan from Tsinghua University for bringing this vulnerability to our attention. :gl:`#5414` -- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number - generator. +- Cache-poisoning due to weak pseudo-random number generator. + :cve:`2025-40780` It was discovered during research for an upcoming academic paper that a xoshiro128\*\* internal state can be recovered by an external 3rd @@ -63,86 +63,78 @@ Security Fixes New Features ~~~~~~~~~~~~ -- Add extra tokens to the zone file name template. +- Support for additional tokens in the zone file name template. - Extend the `$name`, `$view` and `$type` tokens (expanding into the - zone name, zone's view name and type); the new following tokens are - now also accepted: - - - `$name` or `%s` is replaced with the zone name in lower case; - - `$type` or `%t` is replaced with the zone type -- i.e., primary, - secondary, etc); - `$view` or `%v` is replaced with the view name; - - `$char1` or `%1` is replaced with the first character of the zone - name; - `$char2` or `%2` is replaced with the second character of the - zone name (or a dot if there is no second character); - `$char3` or - `%3` is replaced with the third character of the zone name (or a dot - if there is no third character); - `$label1` or `%z` is replaced with - the toplevel domain of the zone (or a dot if it is the root zone); - - `$label2` or `%y` is replaced with the next label under the toplevel - domain (or a dot if there is no next label); - `$label3` or `%x` is - replaced with the next-next label under the toplevel domain (or a - dot if there is no next-next label). :gl:`#85` + See :any:`file` for a complete list of currently supported tokens. + :gl:`#85` - Add support for synthetic records. - Add a query plugin which, in "reverse" mode, enables the server to - build a synthesized response to a PTR query when the PTR record - requested is not found in the zone. The dynamically-built name is - constructed from a static prefix (passed as a plugin parameter), the - IP address (extracted from the query name) and a suffix (also passed - as a plugin parameter). An `allow-synth` address-match list can be - used to limit the network addresses for which the plugin may generate - responses. The plugin can also be used in "forward" mode, to - build synthesized A/AAAA records from names using the same format as - the dynamically-built PTR names. The same parameters are used: the - plugin will react and answer a query if the name matches the - configured prefix and origin, and encodes an IP address that is within - `allow-synth`. :gl:`#1586` + Add :iscman:`synthrecord` query plugin which, in "reverse" mode, + enables the server to build a synthesized response to a PTR query when + the PTR record requested is not found in the zone. + + The dynamically built name is constructed from a static prefix (passed + as a plugin parameter), the IP address (extracted from the query + name), and a suffix (also passed as a plugin parameter). An + ``allow-synth`` address-match list can be used to limit the network + addresses for which the plugin may generate responses. + + The plugin can also be used in "forward" mode, to build synthesized + A/AAAA records from names using the same format as the dynamically + built PTR names. The same parameters are used: the plugin reacts and + answers a query if the name matches the configured prefix and origin, + and encodes an IP address that is within ``allow-synth``. :gl:`#1586` - Support for zone-specific plugins. - Query plugins can now be configured at the `zone` level, as well as - globally or at the `view` level. A plugin's hooks are then called only - while that specific zone's database is being used to answer a query. + Query plugins can now be configured at the :any:`zone` level, as well + as globally or at the :any:`view` level. A plugin's hooks are then + called only while that specific zone's database is being used to + answer a query. This simplifies the implementation of plugins that are only needed for specific namespaces for which the server is authoritative. It can also - enable quicker responses, since plugins will only be called when they - are needed. :gl:`#5356` + enable quicker responses, since plugins are only called when they are + needed. :gl:`#5356` -- Add dnssec-policy keys configuration check to named-checkconf. +- Add :any:`dnssec-policy` keys configuration check to + :iscman:`named-checkconf`. - A new option `-k` is added to `named-checkconf` that allows checking - the `dnssec-policy` `keys` configuration against the configured key - stores. If the found key files are not in sync with the given - `dnssec-policy`, the check will fail. + A new option :option:`-k ` was added to + :iscman:`named-checkconf` that allows checking the + :any:`dnssec-policy` :any:`keys` configuration against the configured + key stores. If the found key files are not in sync with the given + :any:`dnssec-policy`, the check will fail. - This is useful to run before migrating to `dnssec-policy`. :gl:`#5486` + This is useful to run before migrating to :any:`dnssec-policy`. + :gl:`#5486` Removed Features ~~~~~~~~~~~~~~~~ - Remove randomized RRset ordering. - The rrset-order random doesn't offer uniform distribution of all - permutations and it isn't superior to cyclic order in any way. Make - the random ordering an alias to the cyclic ordering. :gl:`#5513` + :any:`rrset-order` ``random`` did not offer uniform distribution of + all permutations and it was not superior to the ``cyclic`` order in + any way. ``random`` ordering is now an alias for ``cyclic`` ordering. + :gl:`#5513` Bug Fixes ~~~~~~~~~ - Use signer name when disabling DNSSEC algorithms. - ``disable-algorithms`` could cause DNSSEC validation failures when the - parent zone was signed with the algorithms that were being disabled - for the child zone. This has been fixed; `disable-algorithms` now - works on a whole-of-zone basis. + :any:`disable-algorithms` could cause DNSSEC validation failures when + the parent zone was signed with the algorithms that were being + disabled for the child zone. This has been fixed; + :any:`disable-algorithms` now works on a whole-of-zone basis. - If the zone's name is at or below the ``disable-algorithms`` name the - algorithm is disabled for that zone, using deepest match when there - are multiple ``disable-algorithms`` clauses. :gl:`#5165` + If the zone's name is at or below the :any:`disable-algorithms` name + the algorithm is disabled for that zone, using deepest match when + there are multiple :any:`disable-algorithms` clauses. :gl:`#5165` -- Rndc sign during ZSK rollover will now replace signatures. +- :option:`rndc sign` during ZSK rollover will now replace signatures. When performing a ZSK rollover, if the new DNSKEY is omnipresent, the :option:`rndc sign` command now signs the zone completely with the @@ -152,17 +144,15 @@ Bug Fixes - Missing DNSSEC information when CD bit is set in query. The RRSIGs for glue records were not being cached correctly for CD=1 - queries. This has been fixed. :gl:`#5502` + queries. This has been fixed. :gl:`#5502` -- Add chroot check to meson.build. +- Add a check for ``chroot()`` to the build system. - The meson build procedure was not checking for the existence of the - chroot function. This has been fixed. :gl:`#5519` + The Meson build procedure was not checking for the existence of the + ``chroot()`` function. This has been fixed. :gl:`#5519` - Preserve cache when reload fails and reload the server again. - Fixes an issue where failing to reconfigure/reload the server would - prevent to preserved the views caches on the subsequent server - reconfiguration/reload. :gl:`#5523` - - + This fixes an issue where failing to reconfigure/reload the server + would fail to preserve the views' caches for subsequent server + reconfigurations/reloads. :gl:`#5523` From 7e60dbe424013cb876bb286697243148286d44e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 2 Oct 2025 18:12:18 +0200 Subject: [PATCH 10/16] Reorder release notes --- doc/notes/notes-9.21.13.rst | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/doc/notes/notes-9.21.13.rst b/doc/notes/notes-9.21.13.rst index 5fb5d95a41..9ce8efb07c 100644 --- a/doc/notes/notes-9.21.13.rst +++ b/doc/notes/notes-9.21.13.rst @@ -63,10 +63,17 @@ Security Fixes New Features ~~~~~~~~~~~~ -- Support for additional tokens in the zone file name template. +- Add :any:`dnssec-policy` keys configuration check to + :iscman:`named-checkconf`. - See :any:`file` for a complete list of currently supported tokens. - :gl:`#85` + A new option :option:`-k ` was added to + :iscman:`named-checkconf` that allows checking the + :any:`dnssec-policy` :any:`keys` configuration against the configured + key stores. If the found key files are not in sync with the given + :any:`dnssec-policy`, the check will fail. + + This is useful to run before migrating to :any:`dnssec-policy`. + :gl:`#5486` - Add support for synthetic records. @@ -98,17 +105,10 @@ New Features enable quicker responses, since plugins are only called when they are needed. :gl:`#5356` -- Add :any:`dnssec-policy` keys configuration check to - :iscman:`named-checkconf`. +- Support for additional tokens in the zone file name template. - A new option :option:`-k ` was added to - :iscman:`named-checkconf` that allows checking the - :any:`dnssec-policy` :any:`keys` configuration against the configured - key stores. If the found key files are not in sync with the given - :any:`dnssec-policy`, the check will fail. - - This is useful to run before migrating to :any:`dnssec-policy`. - :gl:`#5486` + See :any:`file` for a complete list of currently supported tokens. + :gl:`#85` Removed Features ~~~~~~~~~~~~~~~~ @@ -123,6 +123,23 @@ Removed Features Bug Fixes ~~~~~~~~~ +- Missing DNSSEC information when CD bit is set in query. + + The RRSIGs for glue records were not being cached correctly for CD=1 + queries. This has been fixed. :gl:`#5502` + +- :option:`rndc sign` during ZSK rollover will now replace signatures. + + When performing a ZSK rollover, if the new DNSKEY is omnipresent, the + :option:`rndc sign` command now signs the zone completely with the + successor key, replacing all zone signatures from the predecessor key + with new ones. :gl:`#5483` + +- Add a check for ``chroot()`` to the build system. + + The Meson build procedure was not checking for the existence of the + ``chroot()`` function. This has been fixed. :gl:`#5519` + - Use signer name when disabling DNSSEC algorithms. :any:`disable-algorithms` could cause DNSSEC validation failures when @@ -134,23 +151,6 @@ Bug Fixes the algorithm is disabled for that zone, using deepest match when there are multiple :any:`disable-algorithms` clauses. :gl:`#5165` -- :option:`rndc sign` during ZSK rollover will now replace signatures. - - When performing a ZSK rollover, if the new DNSKEY is omnipresent, the - :option:`rndc sign` command now signs the zone completely with the - successor key, replacing all zone signatures from the predecessor key - with new ones. :gl:`#5483` - -- Missing DNSSEC information when CD bit is set in query. - - The RRSIGs for glue records were not being cached correctly for CD=1 - queries. This has been fixed. :gl:`#5502` - -- Add a check for ``chroot()`` to the build system. - - The Meson build procedure was not checking for the existence of the - ``chroot()`` function. This has been fixed. :gl:`#5519` - - Preserve cache when reload fails and reload the server again. This fixes an issue where failing to reconfigure/reload the server From 3be0cd8196d692df9a7b890a961eff2caa7463b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Thu, 2 Oct 2025 18:19:19 +0200 Subject: [PATCH 11/16] Update BIND version for release --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 9322379457..eb6f6afe99 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,7 @@ project( 'bind', ['c'], - version: '9.21.13-dev', + version: '9.21.13', meson_version: '>=0.61', license: 'MPL-2.0', default_options: [ From 7b26176c46e3c2a9e97a1177ee1d91236fd643e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 13 Oct 2025 14:10:06 +0200 Subject: [PATCH 12/16] Fix the assertion failure in the selfsigned DNSKEY handling The selfsigned_dnskey() function can now return all the return codes that dns_dnssec_keyfromrdata() can return and this would cause an assertion failure as we were not expecting new isc_result_t codes. --- lib/dns/validator.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 72d7a45dd9..cfe331691f 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -1324,6 +1324,7 @@ selfsigned_dnskey(dns_validator_t *val) { dns_name_t *name = val->name; isc_result_t result; isc_mem_t *mctx = val->view->mctx; + bool match = false; if (rdataset->type != dns_rdatatype_dnskey) { return DNS_R_NOKEYMATCH; @@ -1357,17 +1358,16 @@ selfsigned_dnskey(dns_validator_t *val) { /* * If the REVOKE bit is not set we have a - * theoretically self signed DNSKEY RRset. - * This will be verified later. + * theoretically self-signed DNSKEY RRset; + * this will be verified later. + * + * We don't return the answer yet, though, + * because we need to check the remaining keys + * and possbly remove them if they're revoked. */ if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) { - return ISC_R_SUCCESS; - } - - result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx, - &dstkey); - if (result != ISC_R_SUCCESS) { - return result; + match = true; + break; } /* @@ -1377,6 +1377,20 @@ selfsigned_dnskey(dns_validator_t *val) { if (DNS_TRUST_PENDING(rdataset->trust) && dns_view_istrusted(val->view, name, &key)) { + result = dns_dnssec_keyfromrdata( + name, &keyrdata, mctx, &dstkey); + if (result == DST_R_UNSUPPORTEDALG) { + /* don't count towards max fails */ + break; /* continue with next key */ + } else if (result != ISC_R_SUCCESS) { + consume_validation(val); + if (over_max_fails(val)) { + return ISC_R_QUOTA; + } + consume_validation_fail(val); + break; /* continue with next key */ + } + if (over_max_validations(val)) { dst_key_free(&dstkey); return ISC_R_QUOTA; @@ -1410,6 +1424,8 @@ selfsigned_dnskey(dns_validator_t *val) { consume_validation_fail(val); break; } + + dst_key_free(&dstkey); } else if (rdataset->trust >= dns_trust_secure) { /* * We trust this RRset so if the key is @@ -1417,12 +1433,14 @@ selfsigned_dnskey(dns_validator_t *val) { */ dns_view_untrust(val->view, name, &key); } - - dst_key_free(&dstkey); } } - return DNS_R_NOKEYMATCH; + if (!match) { + return DNS_R_NOKEYMATCH; + } + + return ISC_R_SUCCESS; } /*% From a63db9857ccbf84ec63a99458bd4c9b9371cc01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sat, 18 Oct 2025 09:47:28 +0200 Subject: [PATCH 13/16] Prepare changelog for BIND 9.21.14 --- doc/arm/changelog.rst | 1 + doc/changelog/changelog-9.21.13.rst | 429 +-------------------------- doc/changelog/changelog-9.21.14.rst | 441 ++++++++++++++++++++++++++++ 3 files changed, 445 insertions(+), 426 deletions(-) create mode 100644 doc/changelog/changelog-9.21.14.rst diff --git a/doc/arm/changelog.rst b/doc/arm/changelog.rst index 5d6b31ec83..9f201051d1 100644 --- a/doc/arm/changelog.rst +++ b/doc/arm/changelog.rst @@ -18,6 +18,7 @@ Changelog development. Regular users should refer to :ref:`Release Notes ` for changes relevant to them. +.. include:: ../changelog/changelog-9.21.14.rst .. include:: ../changelog/changelog-9.21.13.rst .. include:: ../changelog/changelog-9.21.12.rst .. include:: ../changelog/changelog-9.21.11.rst diff --git a/doc/changelog/changelog-9.21.13.rst b/doc/changelog/changelog-9.21.13.rst index 375d83168c..2a10446273 100644 --- a/doc/changelog/changelog-9.21.13.rst +++ b/doc/changelog/changelog-9.21.13.rst @@ -12,430 +12,7 @@ BIND 9.21.13 ------------ -Security Fixes -~~~~~~~~~~~~~~ - -- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY - is found. ``1d851c23529`` - - Previously, if a matching but cryptographically invalid key was - encountered during DNSSEC validation, the key was skipped and not - counted towards validation failures. :iscman:`named` now treats such - DNSSEC keys as hard failures and the DNSSEC validation fails - immediately, instead of continuing with the next DNSKEYs in the RRset. - - ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One - Security and Privacy Laboratory at Nankai University for bringing this - vulnerability to our attention. :gl:`#5343` - -- [CVE-2025-40778] Address various spoofing attacks. ``7b95c382dbd`` - - Previously, several issues could be exploited to poison a DNS cache - with spoofed records for zones which were not DNSSEC-signed or if the - resolver was configured to not do DNSSEC validation. These issues were - assigned CVE-2025-40778 and have now been fixed. - - As an additional layer of protection, :iscman:`named` no longer - accepts DNAME records or extraneous NS records in the AUTHORITY - section unless these are received via spoofing-resistant transport - (TCP, UDP with DNS cookies, TSIG, or SIG(0)). - - ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin - Duan from Tsinghua University for bringing this vulnerability to our - attention. :gl:`#5414` - -- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number - generator. ``6876753c7cc`` - - It was discovered during research for an upcoming academic paper that - a xoshiro128\*\* internal state can be recovered by an external 3rd - party, allowing the prediction of UDP ports and DNS IDs in outgoing - queries. This could lead to an attacker spoofing the DNS answers with - great efficiency and poisoning the DNS cache. - - The internal random generator has been changed to a cryptographically - secure pseudo-random generator. - - ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from - Hebrew University of Jerusalem for bringing this vulnerability to our - attention. :gl:`#5484` - -New Features -~~~~~~~~~~~~ - -- Add extra tokens to the zone file name template. ``b449fa95005`` - - Extend the `$name`, `$view` and `$type` tokens (expanding into the - zone name, zone's view name and type); the new following tokens are - now also accepted: - - - `$name` or `%s` is replaced with the zone name in lower case; - - `$type` or `%t` is replaced with the zone type -- i.e., primary, - secondary, etc); - - `$view` or `%v` is replaced with the view name; - - `$char1` or `%1` is replaced with the first character of the zone - name; - - `$char2` or `%2` is replaced with the second character of the zone - name (or a dot if there is no second character); - - `$char3` or `%3` is replaced with the third character of the zone - name (or a dot if there is no third character); - - `$label1` or `%z` is replaced with the toplevel domain of the zone - (or a dot if it is the root zone); - - `$label2` or `%y` is replaced with the next label under the toplevel - domain (or a dot if there is no next label); - - `$label3` or `%x` is replaced with the next-next label under the - toplevel domain (or a dot if there is no next-next label). - - :gl:`#85` :gl:`!10779` - -- Add support for synthetic records. ``cefed841046`` - - Add a query plugin which, in "reverse" mode, enables the server to - build a synthesized response to a PTR query when the PTR record - requested is not found in the zone. The dynamically-built name is - constructed from a static prefix (passed as a plugin parameter), the - IP address (extracted from the query name) and a suffix (also passed - as a plugin parameter). An `allow-synth` address-match list can be - used to limit the network addresses for which the plugin may generate - responses. The plugin can also be used in "forward" mode, to - build synthesized A/AAAA records from names using the same format as - the dynamically-built PTR names. The same parameters are used: the - plugin will react and answer a query if the name matches the - configured prefix and origin, and encodes an IP address that is within - `allow-synth`. :gl:`#1586` :gl:`!10348` - -- Support for zone-specific plugins. ``65fa5693572`` - - Query plugins can now be configured at the `zone` level, as well as - globally or at the `view` level. A plugin's hooks are then called only - while that specific zone's database is being used to answer a query. - - This simplifies the implementation of plugins that are only needed for - specific namespaces for which the server is authoritative. It can also - enable quicker responses, since plugins will only be called when they - are needed. :gl:`#5356` :gl:`!10483` - -- Add dnssec-policy keys configuration check to named-checkconf. - ``23a79b42ea4`` - - A new option `-k` is added to `named-checkconf` that allows checking - the `dnssec-policy` `keys` configuration against the configured key - stores. If the found key files are not in sync with the given - `dnssec-policy`, the check will fail. - - This is useful to run before migrating to `dnssec-policy`. :gl:`#5486` - :gl:`!10907` - -Removed Features -~~~~~~~~~~~~~~~~ - -- Remove randomized RRset ordering. ``014a05a2781`` - - The rrset-order random doesn't offer uniform distribution of all - permutations and it isn't superior to cyclic order in any way. Make - the random ordering an alias to the cyclic ordering. :gl:`#5513` - :gl:`!10912` - -- Remove CHECK_FOR_GLUE_IN_ANSWER. ``7fa4cbedc50`` - - Macro CHECK_FOR_GLUE_IN_ANSWER is defined in `lib/dns/resolver.c` - only, documented nowhere and not exposed as build configuration. This - is valid at least for 9.21+, 9.20 and 9.18. Furthermore, it doesn't - compile anymore on 9.21+ with -DCHECK_FOR_GLUE_IN_ANSWER=1. - - Considering it is very unlikely that anyone build named with this, - remove the code rather than fixing it. :gl:`#5538` :gl:`!11029` - -- Remove orphan dns_loadmgr_t type. ``96855b5449f`` - - dns_loadmgr_t typedef is declared but never defines as well as a - pointer of this type in named_server_t. Removing it. :gl:`!10974` - -Feature Changes -~~~~~~~~~~~~~~~ - -- Add a circular reference between slabtops for type and RRSIG(type) - ``a20c8fe74b0`` - - Previously, the slabtops for "type" and its signature was only loosely - coupled and the headers could expire at different time (both TTL and - LRU based expiry). Add a .related member to the slabtop that allows - us to expire the headers in both related headers and also optimize the - lookups because now both slabtops are looked up at the same time. - :gl:`#3396` :gl:`!10985` - -- Refactor view creation/configuration loops in dedicated functions. - ``cb0807be2be`` - - Refactor a bit of `apply_configuration` by extracting (into respective - dedicated function) the logic to build the keystores list, the KASP - list as well as creating the view/zones and configuring those. This is - the next step of MR !10895 and !10901 - - While the code is extracted, some global variables has been changed - into a function parameters which enable to have a clear view of the - dependency of the function, typically, to know if it depends on local - configuration object or runtime "production" object. The end goal (not - in this MR, but later on) is to move as much as possible - initialization logic outside of the exclusive mode. - - As a first step, latest commits move the keystores list, KASP list and - view/zones creation outside of the exclusive mode. (The view/zone - configuration remain in exclusive mode for now, because of a - dependency to the runtime "cachelist". This is the target of a next - MR. - - For the record; while moving the keystores list, KASP list and - view/zone creation doesn't have a significant impact on the time the - exclusive mode is taken (from my experiment on a 1M small zones - instance); moving `configure_views` did have a _massive_ impact - (basically, the time spend in the exclusive mode is then non - calculable). Configuring views outside the exclusive mode needs more - work, which will be done in future MRs. :gl:`#4673` :gl:`!10910` - -- Add option to always build fuzz binaries. ``54c8252c6e2`` - - Currently the fuzzer binaries are only built when someone requests a - fuzzer. This might cause us to inadvertently break fuzzing when - changing function signatures. It also deviates with the behaviour we - had with autotools, where the fuzz binaries were built with make test. - - This commit splits the -Dfuzzing option into two: fuzzing, and - fuzzing-backend. The fuzzing option controls whether the fuzzing - binaries are built. The fuzzing-backend option controls which backend - to use, and defaults to none. If the value none is used the binaries - are built, but no backend is used or guaranteed, which means that the - binaries might be non-functional. :gl:`#5526` :gl:`!10990` - -- Rename cfg_aclconfctx_t variables to aclctx. ``0411142f826`` - - ACL configuration context variables are inconsistently named as - `actx`, `ac`, or `aclconfctx`, which caused confusion during code - reviews. This commit renames all `cfg_aclconfctx_t` variables to - `aclctx`, which is short, consistent, and unambiguous. :gl:`#5530` - :gl:`!11003` - -- Provide more context when registering plugins. ``ac4cf4cce8d`` - - Add a new type, `ns_pluginregister_ctx_t`, which is passed to - `plugin_register()` in place of the `source` parameter. The source - value is now just part of the structure, which also holds a pointer to - the zone origin if the plugin is loaded at a zone level. This - provides more contextual information, enabling the plugin to make - specific configuration decisions based on the name of the zone for - which it is loaded. It's also flexible if more contextual data - are needed in the future: add a new field to - `ns_pluginregister_ctx_t`, and new plugins can use it without - affecting compatibility with existing plugins. :gl:`#5533` - :gl:`!11019` - -- Add option to compile named with static linking and LTO. - ``b6971fb7240`` - - Statically linking lib{isc,dns,ns,cfg,isccc} and enabling LTO shows - over 10% improvements on all almost measurements in perflab. That - said, we can't use Meson's option for LTO since it would result in - every binary being compiled with LTO and a great increase in compile - time. - - To work around it, we add a configuration option that enables LTO and - static linking only for the `named` binary. :gl:`!10761` - -- Convert slabtop and slabheader to use the cds list. ``7443ff330cc`` - - This is the first MR in series that aims to reduce the node locking by - replacing the single-linked list of slabtop(s) and slabheader(s) with - CDS linked list. This commit doesn't do anything else beyond - replacing .next and .down links with the cds_list_head. The RCU - semantics will be added later. :gl:`!10944` - -- Make the database ownercase modifiable only via addrdataset() - ``dbc47312925`` - - Simplify the implementation around the database ownercase. Remove the - dns_rdataset_setownercase() implementation for the slabheaders and - only allow setting ownercase on rdatalists and rdatasets. The - ownercase in the database can now be set only with - dns_db_addrdataset() by passing rdataset with correctly set ownercase. - :gl:`!10971` - -- Minor refactor of dst code. ``f5af3e431b9`` - - Convert the defines to enums. Initialize the tags more explicitly and - less ugly. :gl:`!11000` - -- Rename ns_pluginregister_ctx_t into ns_pluginctx_t. ``029a7152bba`` - - The type `ns_pluginregister_ctx_t` was initially added to pass plugin - contextual data when the plugin is registered, but this is also now - passed into `plugin_check`. Furthermore, those various data are not - specific to the registration in particular. Rename the type into - `ns_pluginctx_t` for clarity. :gl:`!11035` - -- Simplify nchildren count in isc_nm_listenudp. ``722ce92f107`` - - Slight simplification of the logic to define .nchildren listening UDP - socket. :gl:`!10978` - -- Squash the qpcache tree and nsec tries. ``22803b93e3f`` - - The dns_qpcache already had all the namespace changes needed to put - the normal data and auxiliary NSEC data into a single tree. Remove - the extra nsec QP trie and use the single QP trie for all the cache - data. :gl:`!10975` - -- Use lock-free hashtable for storing resolver fetch contexts. - ``0ac744ee4de`` - - Replace the locked hashmap with the lock-free hashtable from the RCU - library and protect the fetch contexts against reuse by replacing the - libisc reference counting with urcu_ref that can soft-fail in - situation where the reference count is already zero. This allows us - to easily skip re-using the fetch context if it is already in process - of being destroyed. :gl:`!10653` - -Bug Fixes -~~~~~~~~~ - -- Use signer name when disabling DNSSEC algorithms. ``7e0318df857`` - - ``disable-algorithms`` could cause DNSSEC validation failures when the - parent zone was signed with the algorithms that were being disabled - for the child zone. This has been fixed; `disable-algorithms` now - works on a whole-of-zone basis. - - If the zone's name is at or below the ``disable-algorithms`` name the - algorithm is disabled for that zone, using deepest match when there - are multiple ``disable-algorithms`` clauses. :gl:`#5165` :gl:`!10837` - -- Rndc sign during ZSK rollover will now replace signatures. - ``6246f9d7cb1`` - - When performing a ZSK rollover, if the new DNSKEY is omnipresent, the - :option:`rndc sign` command now signs the zone completely with the - successor key, replacing all zone signatures from the predecessor key - with new ones. :gl:`#5483` :gl:`!10867` - -- Missing DNSSEC information when CD bit is set in query. - ``5fcc063ce9a`` - - The RRSIGs for glue records were not being cached correctly for CD=1 - queries. This has been fixed. :gl:`#5502` :gl:`!10938` - -- Fix datarace between unlocking fctx lock and shuttingdown fctx. - ``2924f59cb3e`` - - There was a data race where new fetch response could be added to the - fetch context after we unlock the fetch context and before we shut it - down. This could cause assertion failure when fctx__done() was called - with ISC_R_SUCCESS because there was originally no fetch response, but - new fetch response without associated dataset was added before we had - a chance to shutdown the fetch context. This manifested in the - validated() callback, where cache_rrset() now returns ISC_R_SUCCESS - instead of DNS_R_UNCHANGED when cache was not changed. However the - data race was wrong on a general level. - - Add new argument to fctx__done() that allows to call it with - fctx->lock already acquired to prevent these data races. :gl:`#5507` - :gl:`!10961` - -- Add chroot check to meson.build. ``f2f2488bbe1`` - - The meson build procedure was not checking for the existence of the - chroot function. This has been fixed. :gl:`#5519` :gl:`!10973` - -- Preserve cache when reload fails and reload the server again. - ``33bcff46d30`` - - Fixes an issue where failing to reconfigure/reload the server would - prevent to preserved the views caches on the subsequent server - reconfiguration/reload. :gl:`#5523` :gl:`!10984` - -- Apply_configuration: leave exclusive mode after viewlist cleanup. - ``5c53695bf32`` - - When a re-configuration fails, `apply_configuration` flows jump to a - cleanup label and, at some point, leave the exclusive mode and cleanup - the viewlist. It looks fine as the viewlist is at this point only - locally known (if this is a configuration failure, this is the new - view list, if this is a success, this is the old list which has been - swapped out from the production list during the exclusive mode). - - However, the view and zone initialization code enqueues job callbacks, - for instance from `dns_zone_setsigninginterval` (but there are others - cases) which will be called for the new views and zones after the - exclusive mode is over. - - Depending where the configuration fails, those views and zones can be - half-configured, for instance a view might have an unfrozen resolver. - Hence, leaving the exclusive mode before cleaning up those views ans - zones will immediately called the previously enqueued callbacks and - lead to this reconfiguration-failure crash stack: - - ``` isc_assertion_failed dns_resolver_createfetch do_keyfetch - isc__async_cb ... uv_run loop_thread thread_body thread_run - start_thread ... ``` - - To avoid the problem, the views are now cleaned up before leaving the - exclusive mode (which also clean up the zones and enqueued callbacks). - - As context, the bug was introduced by !10910 which moved the creation - (not configuration) of the view outsides of the exclusive mode. This - is a safe move (as at this point, the newly view are only known - locally by `apply_configuration`) but the re-order was wrong regarding - the point where the exclusive mode was ended (before the change, the - exclusive mode as always ended before the new view are detached). - :gl:`!11016` - -- Check plugin config before registering. ``0e575d150fd`` - - In `named_config_parsefile()`, when checking the validity of - `named.conf`, the checking of plugin correctness was deliberately - postponed until the plugin is loaded and registered. However, the - checking was never actually done: the `plugin_register()` - implementation was called, but `plugin_check()` was not. - - `ns_plugin_register()` (used by `named`) now calls the check function - before the register function, and aborts if either one fails. - `ns_plugin_check()` (used by `named-checkconf`) calls only the check - function. :gl:`!11031` - -- Clean up the dns_db API. ``29fc7850f1e`` - - Some of the API calls in `dns_db` were obsolete, and have been - removed. Others were more complicated than necessary, and have been - refactored to simplify. :gl:`!10830` - -- Do not inline dns_zone_gethooktable. ``e7156fe57ae`` - - Since !10959 `dns_zone_gethooktable()` is only called once per query, - and the suspicion (from perflab analysis) that this (simple, as just - returning a pointer) call was slowing things down (perhaps because of - code locality reasons?) doesn't matter anymore. So even if !10959 - inlined it, it shouldn't matter anymore. :gl:`!10962` - -- Fix detection of whether node is active in find_wildcard() - ``f717bad1086`` - - The current code would fail during the write transaction. The first - header would not match the search->serial and the node might be - incorrectly detected as inactive. :gl:`!10972` - -- Hookasyncctx renaming. ``6ec65c3d1ad`` - - The field `ns_hookasync_t` was initially named `hook_actx` and wrongly - renamed `hook_aclctx` during a mass-renaming of various names for the - config acl context into a consistent `aclctx` name (see !11003). Of - course this is wrong as `ns_hookasync_t` has nothing to do with ACL - but about _async_ context. This commit fixes the mistake by renaming - this field `hookasyncctx` :gl:`!11021` - -- Minimize zone hooktable lookups. ``89039e0d78e`` - - Merging !10483 caused a performance regression because the zone - hooktable had to be looked up every time a hook point was reached, - even if no zone plugins were configured. We now look up the zone - hooktable when a zone is attached to the query context, and keep a - pointer to it until the qctx is destroyed. :gl:`!10959` - +.. note:: + The BIND 9.21.13 release was withdrawn after the discovery of a + regression in a security fix in it during pre-release testing. diff --git a/doc/changelog/changelog-9.21.14.rst b/doc/changelog/changelog-9.21.14.rst new file mode 100644 index 0000000000..72b9bae0a5 --- /dev/null +++ b/doc/changelog/changelog-9.21.14.rst @@ -0,0 +1,441 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +BIND 9.21.14 +------------ + +Security Fixes +~~~~~~~~~~~~~~ + +- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY + is found. ``1d851c23529`` + + Previously, if a matching but cryptographically invalid key was + encountered during DNSSEC validation, the key was skipped and not + counted towards validation failures. :iscman:`named` now treats such + DNSSEC keys as hard failures and the DNSSEC validation fails + immediately, instead of continuing with the next DNSKEYs in the RRset. + + ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One + Security and Privacy Laboratory at Nankai University for bringing this + vulnerability to our attention. :gl:`#5343` + +- [CVE-2025-40778] Address various spoofing attacks. ``7b95c382dbd`` + + Previously, several issues could be exploited to poison a DNS cache + with spoofed records for zones which were not DNSSEC-signed or if the + resolver was configured to not do DNSSEC validation. These issues were + assigned CVE-2025-40778 and have now been fixed. + + As an additional layer of protection, :iscman:`named` no longer + accepts DNAME records or extraneous NS records in the AUTHORITY + section unless these are received via spoofing-resistant transport + (TCP, UDP with DNS cookies, TSIG, or SIG(0)). + + ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin + Duan from Tsinghua University for bringing this vulnerability to our + attention. :gl:`#5414` + +- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number + generator. ``6876753c7cc`` + + It was discovered during research for an upcoming academic paper that + a xoshiro128\*\* internal state can be recovered by an external 3rd + party, allowing the prediction of UDP ports and DNS IDs in outgoing + queries. This could lead to an attacker spoofing the DNS answers with + great efficiency and poisoning the DNS cache. + + The internal random generator has been changed to a cryptographically + secure pseudo-random generator. + + ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from + Hebrew University of Jerusalem for bringing this vulnerability to our + attention. :gl:`#5484` + +New Features +~~~~~~~~~~~~ + +- Add extra tokens to the zone file name template. ``b449fa95005`` + + Extend the `$name`, `$view` and `$type` tokens (expanding into the + zone name, zone's view name and type); the new following tokens are + now also accepted: + + - `$name` or `%s` is replaced with the zone name in lower case; + - `$type` or `%t` is replaced with the zone type -- i.e., primary, + secondary, etc); + - `$view` or `%v` is replaced with the view name; + - `$char1` or `%1` is replaced with the first character of the zone + name; + - `$char2` or `%2` is replaced with the second character of the zone + name (or a dot if there is no second character); + - `$char3` or `%3` is replaced with the third character of the zone + name (or a dot if there is no third character); + - `$label1` or `%z` is replaced with the toplevel domain of the zone + (or a dot if it is the root zone); + - `$label2` or `%y` is replaced with the next label under the toplevel + domain (or a dot if there is no next label); + - `$label3` or `%x` is replaced with the next-next label under the + toplevel domain (or a dot if there is no next-next label). + + :gl:`#85` :gl:`!10779` + +- Add support for synthetic records. ``cefed841046`` + + Add a query plugin which, in "reverse" mode, enables the server to + build a synthesized response to a PTR query when the PTR record + requested is not found in the zone. The dynamically-built name is + constructed from a static prefix (passed as a plugin parameter), the + IP address (extracted from the query name) and a suffix (also passed + as a plugin parameter). An `allow-synth` address-match list can be + used to limit the network addresses for which the plugin may generate + responses. The plugin can also be used in "forward" mode, to + build synthesized A/AAAA records from names using the same format as + the dynamically-built PTR names. The same parameters are used: the + plugin will react and answer a query if the name matches the + configured prefix and origin, and encodes an IP address that is within + `allow-synth`. :gl:`#1586` :gl:`!10348` + +- Support for zone-specific plugins. ``65fa5693572`` + + Query plugins can now be configured at the `zone` level, as well as + globally or at the `view` level. A plugin's hooks are then called only + while that specific zone's database is being used to answer a query. + + This simplifies the implementation of plugins that are only needed for + specific namespaces for which the server is authoritative. It can also + enable quicker responses, since plugins will only be called when they + are needed. :gl:`#5356` :gl:`!10483` + +- Add dnssec-policy keys configuration check to named-checkconf. + ``23a79b42ea4`` + + A new option `-k` is added to `named-checkconf` that allows checking + the `dnssec-policy` `keys` configuration against the configured key + stores. If the found key files are not in sync with the given + `dnssec-policy`, the check will fail. + + This is useful to run before migrating to `dnssec-policy`. :gl:`#5486` + :gl:`!10907` + +Removed Features +~~~~~~~~~~~~~~~~ + +- Remove randomized RRset ordering. ``014a05a2781`` + + The rrset-order random doesn't offer uniform distribution of all + permutations and it isn't superior to cyclic order in any way. Make + the random ordering an alias to the cyclic ordering. :gl:`#5513` + :gl:`!10912` + +- Remove CHECK_FOR_GLUE_IN_ANSWER. ``7fa4cbedc50`` + + Macro CHECK_FOR_GLUE_IN_ANSWER is defined in `lib/dns/resolver.c` + only, documented nowhere and not exposed as build configuration. This + is valid at least for 9.21+, 9.20 and 9.18. Furthermore, it doesn't + compile anymore on 9.21+ with -DCHECK_FOR_GLUE_IN_ANSWER=1. + + Considering it is very unlikely that anyone build named with this, + remove the code rather than fixing it. :gl:`#5538` :gl:`!11029` + +- Remove orphan dns_loadmgr_t type. ``96855b5449f`` + + dns_loadmgr_t typedef is declared but never defines as well as a + pointer of this type in named_server_t. Removing it. :gl:`!10974` + +Feature Changes +~~~~~~~~~~~~~~~ + +- Add a circular reference between slabtops for type and RRSIG(type) + ``a20c8fe74b0`` + + Previously, the slabtops for "type" and its signature was only loosely + coupled and the headers could expire at different time (both TTL and + LRU based expiry). Add a .related member to the slabtop that allows + us to expire the headers in both related headers and also optimize the + lookups because now both slabtops are looked up at the same time. + :gl:`#3396` :gl:`!10985` + +- Refactor view creation/configuration loops in dedicated functions. + ``cb0807be2be`` + + Refactor a bit of `apply_configuration` by extracting (into respective + dedicated function) the logic to build the keystores list, the KASP + list as well as creating the view/zones and configuring those. This is + the next step of MR !10895 and !10901 + + While the code is extracted, some global variables has been changed + into a function parameters which enable to have a clear view of the + dependency of the function, typically, to know if it depends on local + configuration object or runtime "production" object. The end goal (not + in this MR, but later on) is to move as much as possible + initialization logic outside of the exclusive mode. + + As a first step, latest commits move the keystores list, KASP list and + view/zones creation outside of the exclusive mode. (The view/zone + configuration remain in exclusive mode for now, because of a + dependency to the runtime "cachelist". This is the target of a next + MR. + + For the record; while moving the keystores list, KASP list and + view/zone creation doesn't have a significant impact on the time the + exclusive mode is taken (from my experiment on a 1M small zones + instance); moving `configure_views` did have a _massive_ impact + (basically, the time spend in the exclusive mode is then non + calculable). Configuring views outside the exclusive mode needs more + work, which will be done in future MRs. :gl:`#4673` :gl:`!10910` + +- Add option to always build fuzz binaries. ``54c8252c6e2`` + + Currently the fuzzer binaries are only built when someone requests a + fuzzer. This might cause us to inadvertently break fuzzing when + changing function signatures. It also deviates with the behaviour we + had with autotools, where the fuzz binaries were built with make test. + + This commit splits the -Dfuzzing option into two: fuzzing, and + fuzzing-backend. The fuzzing option controls whether the fuzzing + binaries are built. The fuzzing-backend option controls which backend + to use, and defaults to none. If the value none is used the binaries + are built, but no backend is used or guaranteed, which means that the + binaries might be non-functional. :gl:`#5526` :gl:`!10990` + +- Rename cfg_aclconfctx_t variables to aclctx. ``0411142f826`` + + ACL configuration context variables are inconsistently named as + `actx`, `ac`, or `aclconfctx`, which caused confusion during code + reviews. This commit renames all `cfg_aclconfctx_t` variables to + `aclctx`, which is short, consistent, and unambiguous. :gl:`#5530` + :gl:`!11003` + +- Provide more context when registering plugins. ``ac4cf4cce8d`` + + Add a new type, `ns_pluginregister_ctx_t`, which is passed to + `plugin_register()` in place of the `source` parameter. The source + value is now just part of the structure, which also holds a pointer to + the zone origin if the plugin is loaded at a zone level. This + provides more contextual information, enabling the plugin to make + specific configuration decisions based on the name of the zone for + which it is loaded. It's also flexible if more contextual data + are needed in the future: add a new field to + `ns_pluginregister_ctx_t`, and new plugins can use it without + affecting compatibility with existing plugins. :gl:`#5533` + :gl:`!11019` + +- Add option to compile named with static linking and LTO. + ``b6971fb7240`` + + Statically linking lib{isc,dns,ns,cfg,isccc} and enabling LTO shows + over 10% improvements on all almost measurements in perflab. That + said, we can't use Meson's option for LTO since it would result in + every binary being compiled with LTO and a great increase in compile + time. + + To work around it, we add a configuration option that enables LTO and + static linking only for the `named` binary. :gl:`!10761` + +- Convert slabtop and slabheader to use the cds list. ``7443ff330cc`` + + This is the first MR in series that aims to reduce the node locking by + replacing the single-linked list of slabtop(s) and slabheader(s) with + CDS linked list. This commit doesn't do anything else beyond + replacing .next and .down links with the cds_list_head. The RCU + semantics will be added later. :gl:`!10944` + +- Make the database ownercase modifiable only via addrdataset() + ``dbc47312925`` + + Simplify the implementation around the database ownercase. Remove the + dns_rdataset_setownercase() implementation for the slabheaders and + only allow setting ownercase on rdatalists and rdatasets. The + ownercase in the database can now be set only with + dns_db_addrdataset() by passing rdataset with correctly set ownercase. + :gl:`!10971` + +- Minor refactor of dst code. ``f5af3e431b9`` + + Convert the defines to enums. Initialize the tags more explicitly and + less ugly. :gl:`!11000` + +- Rename ns_pluginregister_ctx_t into ns_pluginctx_t. ``029a7152bba`` + + The type `ns_pluginregister_ctx_t` was initially added to pass plugin + contextual data when the plugin is registered, but this is also now + passed into `plugin_check`. Furthermore, those various data are not + specific to the registration in particular. Rename the type into + `ns_pluginctx_t` for clarity. :gl:`!11035` + +- Simplify nchildren count in isc_nm_listenudp. ``722ce92f107`` + + Slight simplification of the logic to define .nchildren listening UDP + socket. :gl:`!10978` + +- Squash the qpcache tree and nsec tries. ``22803b93e3f`` + + The dns_qpcache already had all the namespace changes needed to put + the normal data and auxiliary NSEC data into a single tree. Remove + the extra nsec QP trie and use the single QP trie for all the cache + data. :gl:`!10975` + +- Use lock-free hashtable for storing resolver fetch contexts. + ``0ac744ee4de`` + + Replace the locked hashmap with the lock-free hashtable from the RCU + library and protect the fetch contexts against reuse by replacing the + libisc reference counting with urcu_ref that can soft-fail in + situation where the reference count is already zero. This allows us + to easily skip re-using the fetch context if it is already in process + of being destroyed. :gl:`!10653` + +Bug Fixes +~~~~~~~~~ + +- Use signer name when disabling DNSSEC algorithms. ``7e0318df857`` + + ``disable-algorithms`` could cause DNSSEC validation failures when the + parent zone was signed with the algorithms that were being disabled + for the child zone. This has been fixed; `disable-algorithms` now + works on a whole-of-zone basis. + + If the zone's name is at or below the ``disable-algorithms`` name the + algorithm is disabled for that zone, using deepest match when there + are multiple ``disable-algorithms`` clauses. :gl:`#5165` :gl:`!10837` + +- Rndc sign during ZSK rollover will now replace signatures. + ``6246f9d7cb1`` + + When performing a ZSK rollover, if the new DNSKEY is omnipresent, the + :option:`rndc sign` command now signs the zone completely with the + successor key, replacing all zone signatures from the predecessor key + with new ones. :gl:`#5483` :gl:`!10867` + +- Missing DNSSEC information when CD bit is set in query. + ``5fcc063ce9a`` + + The RRSIGs for glue records were not being cached correctly for CD=1 + queries. This has been fixed. :gl:`#5502` :gl:`!10938` + +- Fix datarace between unlocking fctx lock and shuttingdown fctx. + ``2924f59cb3e`` + + There was a data race where new fetch response could be added to the + fetch context after we unlock the fetch context and before we shut it + down. This could cause assertion failure when fctx__done() was called + with ISC_R_SUCCESS because there was originally no fetch response, but + new fetch response without associated dataset was added before we had + a chance to shutdown the fetch context. This manifested in the + validated() callback, where cache_rrset() now returns ISC_R_SUCCESS + instead of DNS_R_UNCHANGED when cache was not changed. However the + data race was wrong on a general level. + + Add new argument to fctx__done() that allows to call it with + fctx->lock already acquired to prevent these data races. :gl:`#5507` + :gl:`!10961` + +- Add chroot check to meson.build. ``f2f2488bbe1`` + + The meson build procedure was not checking for the existence of the + chroot function. This has been fixed. :gl:`#5519` :gl:`!10973` + +- Preserve cache when reload fails and reload the server again. + ``33bcff46d30`` + + Fixes an issue where failing to reconfigure/reload the server would + prevent to preserved the views caches on the subsequent server + reconfiguration/reload. :gl:`#5523` :gl:`!10984` + +- Apply_configuration: leave exclusive mode after viewlist cleanup. + ``5c53695bf32`` + + When a re-configuration fails, `apply_configuration` flows jump to a + cleanup label and, at some point, leave the exclusive mode and cleanup + the viewlist. It looks fine as the viewlist is at this point only + locally known (if this is a configuration failure, this is the new + view list, if this is a success, this is the old list which has been + swapped out from the production list during the exclusive mode). + + However, the view and zone initialization code enqueues job callbacks, + for instance from `dns_zone_setsigninginterval` (but there are others + cases) which will be called for the new views and zones after the + exclusive mode is over. + + Depending where the configuration fails, those views and zones can be + half-configured, for instance a view might have an unfrozen resolver. + Hence, leaving the exclusive mode before cleaning up those views ans + zones will immediately called the previously enqueued callbacks and + lead to this reconfiguration-failure crash stack: + + ``` isc_assertion_failed dns_resolver_createfetch do_keyfetch + isc__async_cb ... uv_run loop_thread thread_body thread_run + start_thread ... ``` + + To avoid the problem, the views are now cleaned up before leaving the + exclusive mode (which also clean up the zones and enqueued callbacks). + + As context, the bug was introduced by !10910 which moved the creation + (not configuration) of the view outsides of the exclusive mode. This + is a safe move (as at this point, the newly view are only known + locally by `apply_configuration`) but the re-order was wrong regarding + the point where the exclusive mode was ended (before the change, the + exclusive mode as always ended before the new view are detached). + :gl:`!11016` + +- Check plugin config before registering. ``0e575d150fd`` + + In `named_config_parsefile()`, when checking the validity of + `named.conf`, the checking of plugin correctness was deliberately + postponed until the plugin is loaded and registered. However, the + checking was never actually done: the `plugin_register()` + implementation was called, but `plugin_check()` was not. + + `ns_plugin_register()` (used by `named`) now calls the check function + before the register function, and aborts if either one fails. + `ns_plugin_check()` (used by `named-checkconf`) calls only the check + function. :gl:`!11031` + +- Clean up the dns_db API. ``29fc7850f1e`` + + Some of the API calls in `dns_db` were obsolete, and have been + removed. Others were more complicated than necessary, and have been + refactored to simplify. :gl:`!10830` + +- Do not inline dns_zone_gethooktable. ``e7156fe57ae`` + + Since !10959 `dns_zone_gethooktable()` is only called once per query, + and the suspicion (from perflab analysis) that this (simple, as just + returning a pointer) call was slowing things down (perhaps because of + code locality reasons?) doesn't matter anymore. So even if !10959 + inlined it, it shouldn't matter anymore. :gl:`!10962` + +- Fix detection of whether node is active in find_wildcard() + ``f717bad1086`` + + The current code would fail during the write transaction. The first + header would not match the search->serial and the node might be + incorrectly detected as inactive. :gl:`!10972` + +- Hookasyncctx renaming. ``6ec65c3d1ad`` + + The field `ns_hookasync_t` was initially named `hook_actx` and wrongly + renamed `hook_aclctx` during a mass-renaming of various names for the + config acl context into a consistent `aclctx` name (see !11003). Of + course this is wrong as `ns_hookasync_t` has nothing to do with ACL + but about _async_ context. This commit fixes the mistake by renaming + this field `hookasyncctx` :gl:`!11021` + +- Minimize zone hooktable lookups. ``89039e0d78e`` + + Merging !10483 caused a performance regression because the zone + hooktable had to be looked up every time a hook point was reached, + even if no zone plugins were configured. We now look up the zone + hooktable when a zone is attached to the query context, and keep a + pointer to it until the qctx is destroyed. :gl:`!10959` + + From 3ecab35af617939e529f4600bfc6a2f583155711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sat, 18 Oct 2025 09:47:28 +0200 Subject: [PATCH 14/16] Prepare release notes for BIND 9.21.14 --- doc/arm/notes.rst | 1 + doc/notes/notes-9.21.13.rst | 146 +-------------------------------- doc/notes/notes-9.21.14.rst | 158 ++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 143 deletions(-) create mode 100644 doc/notes/notes-9.21.14.rst diff --git a/doc/arm/notes.rst b/doc/arm/notes.rst index 83686dc00e..97300c407d 100644 --- a/doc/arm/notes.rst +++ b/doc/arm/notes.rst @@ -47,6 +47,7 @@ The list of known issues affecting the latest version in the 9.21 branch can be found at https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21 +.. include:: ../notes/notes-9.21.14.rst .. include:: ../notes/notes-9.21.13.rst .. include:: ../notes/notes-9.21.12.rst .. include:: ../notes/notes-9.21.11.rst diff --git a/doc/notes/notes-9.21.13.rst b/doc/notes/notes-9.21.13.rst index 9ce8efb07c..65b5372cf4 100644 --- a/doc/notes/notes-9.21.13.rst +++ b/doc/notes/notes-9.21.13.rst @@ -12,147 +12,7 @@ Notes for BIND 9.21.13 ---------------------- -Security Fixes -~~~~~~~~~~~~~~ +.. note:: -- DNSSEC validation fails if matching but invalid DNSKEY is found. - :cve:`2025-8677` - - Previously, if a matching but cryptographically invalid key was - encountered during DNSSEC validation, the key was skipped and not - counted towards validation failures. :iscman:`named` now treats such - DNSSEC keys as hard failures and the DNSSEC validation fails - immediately, instead of continuing with the next DNSKEYs in the RRset. - - ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One - Security and Privacy Laboratory at Nankai University for bringing this - vulnerability to our attention. :gl:`#5343` - -- Address various spoofing attacks. :cve:`2025-40778` - - Previously, several issues could be exploited to poison a DNS cache - with spoofed records for zones which were not DNSSEC-signed or if the - resolver was configured to not do DNSSEC validation. These issues were - assigned CVE-2025-40778 and have now been fixed. - - As an additional layer of protection, :iscman:`named` no longer - accepts DNAME records or extraneous NS records in the AUTHORITY - section unless these are received via spoofing-resistant transport - (TCP, UDP with DNS cookies, TSIG, or SIG(0)). - - ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin - Duan from Tsinghua University for bringing this vulnerability to our - attention. :gl:`#5414` - -- Cache-poisoning due to weak pseudo-random number generator. - :cve:`2025-40780` - - It was discovered during research for an upcoming academic paper that - a xoshiro128\*\* internal state can be recovered by an external 3rd - party, allowing the prediction of UDP ports and DNS IDs in outgoing - queries. This could lead to an attacker spoofing the DNS answers with - great efficiency and poisoning the DNS cache. - - The internal random generator has been changed to a cryptographically - secure pseudo-random generator. - - ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from - Hebrew University of Jerusalem for bringing this vulnerability to our - attention. :gl:`#5484` - -New Features -~~~~~~~~~~~~ - -- Add :any:`dnssec-policy` keys configuration check to - :iscman:`named-checkconf`. - - A new option :option:`-k ` was added to - :iscman:`named-checkconf` that allows checking the - :any:`dnssec-policy` :any:`keys` configuration against the configured - key stores. If the found key files are not in sync with the given - :any:`dnssec-policy`, the check will fail. - - This is useful to run before migrating to :any:`dnssec-policy`. - :gl:`#5486` - -- Add support for synthetic records. - - Add :iscman:`synthrecord` query plugin which, in "reverse" mode, - enables the server to build a synthesized response to a PTR query when - the PTR record requested is not found in the zone. - - The dynamically built name is constructed from a static prefix (passed - as a plugin parameter), the IP address (extracted from the query - name), and a suffix (also passed as a plugin parameter). An - ``allow-synth`` address-match list can be used to limit the network - addresses for which the plugin may generate responses. - - The plugin can also be used in "forward" mode, to build synthesized - A/AAAA records from names using the same format as the dynamically - built PTR names. The same parameters are used: the plugin reacts and - answers a query if the name matches the configured prefix and origin, - and encodes an IP address that is within ``allow-synth``. :gl:`#1586` - -- Support for zone-specific plugins. - - Query plugins can now be configured at the :any:`zone` level, as well - as globally or at the :any:`view` level. A plugin's hooks are then - called only while that specific zone's database is being used to - answer a query. - - This simplifies the implementation of plugins that are only needed for - specific namespaces for which the server is authoritative. It can also - enable quicker responses, since plugins are only called when they are - needed. :gl:`#5356` - -- Support for additional tokens in the zone file name template. - - See :any:`file` for a complete list of currently supported tokens. - :gl:`#85` - -Removed Features -~~~~~~~~~~~~~~~~ - -- Remove randomized RRset ordering. - - :any:`rrset-order` ``random`` did not offer uniform distribution of - all permutations and it was not superior to the ``cyclic`` order in - any way. ``random`` ordering is now an alias for ``cyclic`` ordering. - :gl:`#5513` - -Bug Fixes -~~~~~~~~~ - -- Missing DNSSEC information when CD bit is set in query. - - The RRSIGs for glue records were not being cached correctly for CD=1 - queries. This has been fixed. :gl:`#5502` - -- :option:`rndc sign` during ZSK rollover will now replace signatures. - - When performing a ZSK rollover, if the new DNSKEY is omnipresent, the - :option:`rndc sign` command now signs the zone completely with the - successor key, replacing all zone signatures from the predecessor key - with new ones. :gl:`#5483` - -- Add a check for ``chroot()`` to the build system. - - The Meson build procedure was not checking for the existence of the - ``chroot()`` function. This has been fixed. :gl:`#5519` - -- Use signer name when disabling DNSSEC algorithms. - - :any:`disable-algorithms` could cause DNSSEC validation failures when - the parent zone was signed with the algorithms that were being - disabled for the child zone. This has been fixed; - :any:`disable-algorithms` now works on a whole-of-zone basis. - - If the zone's name is at or below the :any:`disable-algorithms` name - the algorithm is disabled for that zone, using deepest match when - there are multiple :any:`disable-algorithms` clauses. :gl:`#5165` - -- Preserve cache when reload fails and reload the server again. - - This fixes an issue where failing to reconfigure/reload the server - would fail to preserve the views' caches for subsequent server - reconfigurations/reloads. :gl:`#5523` + The BIND 9.21.13 release was withdrawn after the discovery of a + regression in a security fix in it during pre-release testing. diff --git a/doc/notes/notes-9.21.14.rst b/doc/notes/notes-9.21.14.rst new file mode 100644 index 0000000000..199d481f7a --- /dev/null +++ b/doc/notes/notes-9.21.14.rst @@ -0,0 +1,158 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +Notes for BIND 9.21.14 +---------------------- + +Security Fixes +~~~~~~~~~~~~~~ + +- DNSSEC validation fails if matching but invalid DNSKEY is found. + :cve:`2025-8677` + + Previously, if a matching but cryptographically invalid key was + encountered during DNSSEC validation, the key was skipped and not + counted towards validation failures. :iscman:`named` now treats such + DNSSEC keys as hard failures and the DNSSEC validation fails + immediately, instead of continuing with the next DNSKEYs in the RRset. + + ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One + Security and Privacy Laboratory at Nankai University for bringing this + vulnerability to our attention. :gl:`#5343` + +- Address various spoofing attacks. :cve:`2025-40778` + + Previously, several issues could be exploited to poison a DNS cache + with spoofed records for zones which were not DNSSEC-signed or if the + resolver was configured to not do DNSSEC validation. These issues were + assigned CVE-2025-40778 and have now been fixed. + + As an additional layer of protection, :iscman:`named` no longer + accepts DNAME records or extraneous NS records in the AUTHORITY + section unless these are received via spoofing-resistant transport + (TCP, UDP with DNS cookies, TSIG, or SIG(0)). + + ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin + Duan from Tsinghua University for bringing this vulnerability to our + attention. :gl:`#5414` + +- Cache-poisoning due to weak pseudo-random number generator. + :cve:`2025-40780` + + It was discovered during research for an upcoming academic paper that + a xoshiro128\*\* internal state can be recovered by an external 3rd + party, allowing the prediction of UDP ports and DNS IDs in outgoing + queries. This could lead to an attacker spoofing the DNS answers with + great efficiency and poisoning the DNS cache. + + The internal random generator has been changed to a cryptographically + secure pseudo-random generator. + + ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from + Hebrew University of Jerusalem for bringing this vulnerability to our + attention. :gl:`#5484` + +New Features +~~~~~~~~~~~~ + +- Add :any:`dnssec-policy` keys configuration check to + :iscman:`named-checkconf`. + + A new option :option:`-k ` was added to + :iscman:`named-checkconf` that allows checking the + :any:`dnssec-policy` :any:`keys` configuration against the configured + key stores. If the found key files are not in sync with the given + :any:`dnssec-policy`, the check will fail. + + This is useful to run before migrating to :any:`dnssec-policy`. + :gl:`#5486` + +- Add support for synthetic records. + + Add :iscman:`synthrecord` query plugin which, in "reverse" mode, + enables the server to build a synthesized response to a PTR query when + the PTR record requested is not found in the zone. + + The dynamically built name is constructed from a static prefix (passed + as a plugin parameter), the IP address (extracted from the query + name), and a suffix (also passed as a plugin parameter). An + ``allow-synth`` address-match list can be used to limit the network + addresses for which the plugin may generate responses. + + The plugin can also be used in "forward" mode, to build synthesized + A/AAAA records from names using the same format as the dynamically + built PTR names. The same parameters are used: the plugin reacts and + answers a query if the name matches the configured prefix and origin, + and encodes an IP address that is within ``allow-synth``. :gl:`#1586` + +- Support for zone-specific plugins. + + Query plugins can now be configured at the :any:`zone` level, as well + as globally or at the :any:`view` level. A plugin's hooks are then + called only while that specific zone's database is being used to + answer a query. + + This simplifies the implementation of plugins that are only needed for + specific namespaces for which the server is authoritative. It can also + enable quicker responses, since plugins are only called when they are + needed. :gl:`#5356` + +- Support for additional tokens in the zone file name template. + + See :any:`file` for a complete list of currently supported tokens. + :gl:`#85` + +Removed Features +~~~~~~~~~~~~~~~~ + +- Remove randomized RRset ordering. + + :any:`rrset-order` ``random`` did not offer uniform distribution of + all permutations and it was not superior to the ``cyclic`` order in + any way. ``random`` ordering is now an alias for ``cyclic`` ordering. + :gl:`#5513` + +Bug Fixes +~~~~~~~~~ + +- Missing DNSSEC information when CD bit is set in query. + + The RRSIGs for glue records were not being cached correctly for CD=1 + queries. This has been fixed. :gl:`#5502` + +- :option:`rndc sign` during ZSK rollover will now replace signatures. + + When performing a ZSK rollover, if the new DNSKEY is omnipresent, the + :option:`rndc sign` command now signs the zone completely with the + successor key, replacing all zone signatures from the predecessor key + with new ones. :gl:`#5483` + +- Add a check for ``chroot()`` to the build system. + + The Meson build procedure was not checking for the existence of the + ``chroot()`` function. This has been fixed. :gl:`#5519` + +- Use signer name when disabling DNSSEC algorithms. + + :any:`disable-algorithms` could cause DNSSEC validation failures when + the parent zone was signed with the algorithms that were being + disabled for the child zone. This has been fixed; + :any:`disable-algorithms` now works on a whole-of-zone basis. + + If the zone's name is at or below the :any:`disable-algorithms` name + the algorithm is disabled for that zone, using deepest match when + there are multiple :any:`disable-algorithms` clauses. :gl:`#5165` + +- Preserve cache when reload fails and reload the server again. + + This fixes an issue where failing to reconfigure/reload the server + would fail to preserve the views' caches for subsequent server + reconfigurations/reloads. :gl:`#5523` From 363416443b5f9661d1b580e928431d52d9b6ac76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicki=20K=C5=99=C3=AD=C5=BEek?= Date: Mon, 6 Oct 2025 17:45:07 +0200 Subject: [PATCH 15/16] Remove reuse annotations for unused m4 libtool files The files in question are no longer included in the git tree and distributed with the code. Remove the reuse annotations as they caused issues with reuse 6.0.0, as multiline annotation for SPDX-FileCopyrightText breaks the parsing. (cherry picked from commit e77f349240d1f71953cfe26cf0a1417e5c085493) --- REUSE.toml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index 72935a26c4..18b094d12b 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -149,18 +149,6 @@ precedence = "aggregate" SPDX-FileCopyrightText = "Internet Systems Consortium, Inc. (\"ISC\")" SPDX-License-Identifier = "MPL-2.0" -[[annotations]] -path = [ - "m4/libtool.m4", - "m4/ltoptions.m4", - "m4/ltsugar.m4", - "m4/ltversion.m4", - "m4/ltversion.m4", - "m4/lt~obsolete.m4" -] -precedence = "aggregate" -SPDX-FileCopyrightText = "Free Software Foundation, Inc.\n This file is free software; the Free Software Foundation gives unlimited\n permission to copy and/or distribute it, with or without modifications, as long\n as this notice is preserved." - [[annotations]] path = [ "**/.clang-format", From 537824f32eee1a138b4171497d471632f0c9ae21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Sat, 18 Oct 2025 11:48:52 +0200 Subject: [PATCH 16/16] Update BIND version for release --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index eb6f6afe99..640d6d3224 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,7 @@ project( 'bind', ['c'], - version: '9.21.13', + version: '9.21.14', meson_version: '>=0.61', license: 'MPL-2.0', default_options: [