From 18d374bb85ceb9c4831303d44e89cb336617c7e3 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Wed, 15 Apr 2026 00:23:53 -0400 Subject: [PATCH] import UBI bind-9.16.23-34.el9_7.2 --- SOURCES/bind-9.16-CVE-2026-1519.patch | 250 ++++++++++++++++++++++++++ SPECS/bind.spec | 8 +- 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 SOURCES/bind-9.16-CVE-2026-1519.patch diff --git a/SOURCES/bind-9.16-CVE-2026-1519.patch b/SOURCES/bind-9.16-CVE-2026-1519.patch new file mode 100644 index 0000000..9887efe --- /dev/null +++ b/SOURCES/bind-9.16-CVE-2026-1519.patch @@ -0,0 +1,250 @@ +From 16c75b53b9f76011ae64378046f66dc0c2ad7526 Mon Sep 17 00:00:00 2001 +From: Matthijs Mekking +Date: Tue, 3 Mar 2026 10:40:36 +0100 +Subject: [PATCH] Check iterations in isdelegation() + +When looking up an NSEC3 as part of an insecurity proof, check the +number of iterations. If this is too high, treat the answer as insecure +by marking the answer with trust level "answer", indicating that they +did not validate, but could be cached as insecure. + +(cherry picked from commit 988040a5e02f86f4a8cdb0704e8d501f9082a89c) +(cherry picked from commit 0e636fb6c21a165b1bab67636d6f380f20e8b012) + +Don't verify already trusted rdatasets + +If we already marked an rdataset as secure (or it has even stronger +trust), there is no need to cryptographically verify it again. + +(cherry picked from commit 0ec08c212022d08c9717f2bc6bd3e8ebd6f034ce) +(cherry picked from commit e307735073b207a2e1635703511df55f6583d18e) + +Check RRset trust in validate_neg_rrset() + +In many places we only create a validator if the RRset has too low +trust (the RRset is pending validation, or could not be validated +before). This check was missing prior to validating negative response +data. + +(cherry picked from commit 6ca67f65cd685cf8699540a852c1e3775bd48d64) +(cherry picked from commit 5828874d13870bce651eb84fdfc95d581f66927c) +--- + lib/dns/include/dns/types.h | 1 + + lib/dns/validator.c | 89 ++++++++++++++++++++++++++++--------- + 2 files changed, 70 insertions(+), 20 deletions(-) + +diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h +index 8781875651..8878ac7bd9 100644 +--- a/lib/dns/include/dns/types.h ++++ b/lib/dns/include/dns/types.h +@@ -354,6 +354,7 @@ enum { + ((x) == dns_trust_additional || (x) == dns_trust_pending_additional) + #define DNS_TRUST_GLUE(x) ((x) == dns_trust_glue) + #define DNS_TRUST_ANSWER(x) ((x) == dns_trust_answer) ++#define DNS_TRUST_SECURE(x) ((x) >= dns_trust_secure) + + /*% + * Name checking severities. +diff --git a/lib/dns/validator.c b/lib/dns/validator.c +index e416cc9b5c..d571539a7d 100644 +--- a/lib/dns/validator.c ++++ b/lib/dns/validator.c +@@ -249,12 +249,25 @@ exit_check(dns_validator_t *val) { + } + + /*% +- * Look in the NSEC record returned from a DS query to see if there is +- * a NS RRset at this name. If it is found we are at a delegation point. ++ * The isdelegation() function is called as part of seeking the DS record. ++ * Look in the NSEC or NSEC3 record returned from a DS query to see if the ++ * record has the NS bitmap set. If so, we are at a delegation point. ++ * ++ * If the response contains NSEC3 records with too high iterations, we cannot ++ * (or rather we are not going to) validate the insecurity proof. Instead we ++ * are going to treat the message as insecure and just assume the DS was at ++ * the delegation. ++ * ++ * Returns: ++ *\li #ISC_R_SUCCESS the NS bitmap was set in the NSEC or NSEC3 record, or ++ * the NSEC3 covers the name (in case of opt-out), or ++ * we cannot validate the insecurity proof and are going ++ * to treat the message as isnecure. ++ *\li #ISC_R_NOTFOUND the NS bitmap was not set, + */ +-static bool +-isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, +- isc_result_t dbresult) { ++static isc_result_t ++isdelegation(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset, ++ isc_result_t dbresult, const char *caller) { + dns_fixedname_t fixed; + dns_label_t hashlabel; + dns_name_t nsec3name; +@@ -282,7 +295,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, + goto trynsec3; + } + if (result != ISC_R_SUCCESS) { +- return (false); ++ return (ISC_R_NOTFOUND); + } + } + +@@ -296,7 +309,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, + dns_rdata_reset(&rdata); + } + dns_rdataset_disassociate(&set); +- return (found); ++ return (found ? ISC_R_SUCCESS : ISC_R_NOTFOUND); + + trynsec3: + /* +@@ -332,6 +345,18 @@ trynsec3: + if (nsec3.hash != 1) { + continue; + } ++ /* ++ * If there are too many iterations assume bad things ++ * are happening and bail out early. Treat as if the ++ * DS was at the delegation. ++ */ ++ if (nsec3.iterations > DNS_NSEC3_MAXITERATIONS) { ++ validator_log(val, ISC_LOG_DEBUG(3), ++ "%s: too many iterations", ++ caller); ++ dns_rdataset_disassociate(&set); ++ return (ISC_R_SUCCESS); ++ } + length = isc_iterated_hash( + hash, nsec3.hash, nsec3.iterations, nsec3.salt, + nsec3.salt_length, name->ndata, name->length); +@@ -343,7 +368,7 @@ trynsec3: + found = dns_nsec3_typepresent(&rdata, + dns_rdatatype_ns); + dns_rdataset_disassociate(&set); +- return (found); ++ return (found ? ISC_R_SUCCESS : ISC_R_NOTFOUND); + } + if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0) { + continue; +@@ -359,12 +384,12 @@ trynsec3: + memcmp(hash, nsec3.next, length) < 0))) + { + dns_rdataset_disassociate(&set); +- return (true); ++ return (ISC_R_SUCCESS); + } + } + dns_rdataset_disassociate(&set); + } +- return (found); ++ return (found ? ISC_R_SUCCESS : ISC_R_NOTFOUND); + } + + /*% +@@ -576,8 +601,10 @@ fetch_callback_ds(isc_task_t *task, isc_event_t *event) { + } else if (eresult == DNS_R_SERVFAIL) { + goto unexpected; + } else if (eresult != DNS_R_CNAME && +- isdelegation(dns_fixedname_name(&devent->foundname), +- &val->frdataset, eresult)) ++ isdelegation(val, ++ dns_fixedname_name(&devent->foundname), ++ &val->frdataset, eresult, ++ "fetch_callback_ds") == ISC_R_SUCCESS) + { + /* + * Failed to find a DS while trying to prove +@@ -736,10 +763,13 @@ validator_callback_ds(isc_task_t *task, isc_event_t *event) { + dns_trust_totext(val->frdataset.trust)); + have_dsset = (val->frdataset.type == dns_rdatatype_ds); + name = dns_fixedname_name(&val->fname); ++ + if ((val->attributes & VALATTR_INSECURITY) != 0 && + val->frdataset.covers == dns_rdatatype_ds && + NEGATIVE(&val->frdataset) && +- isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) ++ isdelegation(val, name, &val->frdataset, ++ DNS_R_NCACHENXRRSET, ++ "validator_callback_ds") == ISC_R_SUCCESS) + { + result = markanswer(val, "validator_callback_ds", + "no DS and this is a delegation"); +@@ -1433,6 +1463,13 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, + bool ignore = false; + dns_name_t *wild; + ++ if (DNS_TRUST_SECURE(val->event->rdataset->trust)) { ++ /* ++ * This RRset was already verified before. ++ */ ++ return ISC_R_SUCCESS; ++ } ++ + val->attributes |= VALATTR_TRIEDVERIFY; + wild = dns_fixedname_initname(&fixed); + again: +@@ -2355,6 +2392,17 @@ validate_neg_rrset(dns_validator_t *val, dns_name_t *name, + } + } + ++ if (rdataset->type != dns_rdatatype_nsec && ++ DNS_TRUST_SECURE(rdataset->trust)) ++ { ++ /* ++ * The negative response data is already verified. ++ * We skip NSEC records, because they require special ++ * processing in validator_callback_nsec(). ++ */ ++ return DNS_R_CONTINUE; ++ } ++ + val->currentset = rdataset; + result = create_validator(val, name, rdataset->type, rdataset, + sigrdataset, validator_callback_nsec, +@@ -2464,11 +2512,9 @@ validate_ncache(dns_validator_t *val, bool resume) { + } + + result = validate_neg_rrset(val, name, rdataset, sigrdataset); +- if (result == DNS_R_CONTINUE) { +- continue; ++ if (result != DNS_R_CONTINUE) { ++ return (result); + } +- +- return (result); + } + if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; +@@ -2517,7 +2563,8 @@ validate_nx(dns_validator_t *val, bool resume) { + result = findnsec3proofs(val); + if (result == DNS_R_NSEC3ITERRANGE) { + validator_log(val, ISC_LOG_DEBUG(3), +- "too many iterations"); ++ "%s: too many iterations", ++ __func__); + markanswer(val, "validate_nx (3)", NULL); + return (ISC_R_SUCCESS); + } +@@ -2553,7 +2600,7 @@ validate_nx(dns_validator_t *val, bool resume) { + result = findnsec3proofs(val); + if (result == DNS_R_NSEC3ITERRANGE) { + validator_log(val, ISC_LOG_DEBUG(3), +- "too many iterations"); ++ "%s: too many iterations", __func__); + markanswer(val, "validate_nx (4)", NULL); + return (ISC_R_SUCCESS); + } +@@ -2770,7 +2817,9 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) { + return (ISC_R_COMPLETE); + } + +- if (isdelegation(tname, &val->frdataset, result)) { ++ result = isdelegation(val, tname, &val->frdataset, result, ++ "seek_ds"); ++ if (result == ISC_R_SUCCESS) { + *resp = markanswer(val, "proveunsecure (4)", + "this is a delegation"); + return (ISC_R_COMPLETE); +-- +2.53.0 + diff --git a/SPECS/bind.spec b/SPECS/bind.spec index be722a3..45967cb 100644 --- a/SPECS/bind.spec +++ b/SPECS/bind.spec @@ -56,7 +56,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv Name: bind License: MPLv2.0 Version: 9.16.23 -Release: 34%{?dist}.1 +Release: 34%{?dist}.2 Epoch: 32 Url: https://www.isc.org/downloads/bind/ # @@ -199,6 +199,8 @@ Patch224: bind-9.16-CVE-2025-40780.patch # https://gitlab.isc.org/isc-projects/bind9/commit/50479358efdf432d690415131b74b5df158a9d69 # https://gitlab.isc.org/isc-projects/bind9/commit/33a7db1fe964e55b76b4ac003ecc56cc67028bd9 Patch225: bind-9.16-CVE-2025-40778.patch +# https://gitlab.isc.org/isc-projects/bind9/-/commit/a5e8d2354385d4f42a58113b16960d85ec306b09 +Patch226: bind-9.16-CVE-2026-1519.patch %{?systemd_ordering} Requires: coreutils @@ -1243,6 +1245,10 @@ fi; %endif %changelog +* Fri Mar 27 2026 Petr Menšík - 32:9.16.23-34.2 +- Prevent Denial of Service via maliciously crafted DNSSEC-validated zone + (CVE-2026-1519) + * Wed Oct 29 2025 Petr Menšík - 32:9.16.23-34.1 - Prevent cache poisoning due to weak PRNG (CVE-2025-40780) - Replace downstream fixes with upstream changes