Fix CVE-2026-13204: assertion failure on malformed NSEC/NSEC3 responses
Add patch for CVE-2026-13204 to prevent an assertion failure
(RUNTIME_CHECK crash) when processing malformed NSEC/NSEC3
responses. The upstream fix (commit 48f5aa5fb3) was adapted
for the bind-9.18 branch by replacing the undefined CHECK()
macro in lib/ns/query.c with its inline equivalent, ensuring
the error is handled gracefully via the cleanup path.
CVE: CVE-2026-13204
Upstream patches:
- 48f5aa5fb3.patch
Resolves: RHEL-213482
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
This commit is contained in:
parent
0d395adab1
commit
d8c000ca87
186
bind-9.18-CVE-2026-13204.patch
Normal file
186
bind-9.18-CVE-2026-13204.patch
Normal file
@ -0,0 +1,186 @@
|
||||
From d190532c319cf4e3b84000f4e389596f2af98fd4 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Hunt <each@isc.org>
|
||||
Date: Wed, 13 May 2026 20:45:57 -0700
|
||||
Subject: [PATCH 1/2] dns_rdataset_addnoqname() could find unsigned NSEC/NSEC3
|
||||
|
||||
The dns_rdatalist addnoqname() implementation searches for the first
|
||||
NSEC or NSEC3 record in a message, then for the first RRSIG covering
|
||||
that type in the same message. Previously, if no RRSIG for the type was
|
||||
found, the function accepted the unsigned record. Now, it will instead
|
||||
continue searching until an NSEC or NSEC3 that does have a matching
|
||||
signature is found.
|
||||
|
||||
When this function is called from validated() in resolver.c, a
|
||||
non-success return code is now treated as an error instead of triggering
|
||||
an assertion failure.
|
||||
|
||||
Fixes: isc-projects/bind9#5985
|
||||
(cherry picked from commit 57cba571ee31311e54d8a11cb38094d439f04e09)
|
||||
---
|
||||
lib/dns/rbtdb.c | 10 +++++++---
|
||||
lib/dns/rdatalist.c | 33 ++++++++++++++++-----------------
|
||||
lib/dns/resolver.c | 4 +++-
|
||||
lib/ns/query.c | 3 +--
|
||||
4 files changed, 27 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
|
||||
index a341b007c7..dadb273bec 100644
|
||||
--- a/lib/dns/rbtdb.c
|
||||
+++ b/lib/dns/rbtdb.c
|
||||
@@ -6906,7 +6906,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
static isc_result_t
|
||||
addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||||
uint32_t maxrrperset, dns_rdataset_t *rdataset) {
|
||||
- struct noqname *noqname;
|
||||
+ struct noqname *noqname = NULL;
|
||||
isc_mem_t *mctx = rbtdb->common.mctx;
|
||||
dns_name_t name;
|
||||
dns_rdataset_t neg, negsig;
|
||||
@@ -6918,7 +6918,9 @@ addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||||
dns_rdataset_init(&negsig);
|
||||
|
||||
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
|
||||
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
noqname = isc_mem_get(mctx, sizeof(*noqname));
|
||||
dns_name_init(&noqname->name, NULL);
|
||||
@@ -6944,7 +6946,9 @@ addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||||
cleanup:
|
||||
dns_rdataset_disassociate(&neg);
|
||||
dns_rdataset_disassociate(&negsig);
|
||||
- free_noqname(mctx, &noqname);
|
||||
+ if (noqname != NULL) {
|
||||
+ free_noqname(mctx, &noqname);
|
||||
+ }
|
||||
return result;
|
||||
}
|
||||
|
||||
diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c
|
||||
index 971e4e656c..c6d77c75dd 100644
|
||||
--- a/lib/dns/rdatalist.c
|
||||
+++ b/lib/dns/rdatalist.c
|
||||
@@ -192,6 +192,7 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, const dns_name_t *name) {
|
||||
dns_rdataset_t *neg = NULL;
|
||||
dns_rdataset_t *negsig = NULL;
|
||||
dns_rdataset_t *rdset;
|
||||
+ dns_rdataset_t *sigset;
|
||||
dns_ttl_t ttl;
|
||||
|
||||
REQUIRE(rdataset != NULL);
|
||||
@@ -199,30 +200,27 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, const dns_name_t *name) {
|
||||
for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
|
||||
rdset = ISC_LIST_NEXT(rdset, link))
|
||||
{
|
||||
- if (rdset->rdclass != rdataset->rdclass) {
|
||||
- continue;
|
||||
- }
|
||||
- if (rdset->type == dns_rdatatype_nsec ||
|
||||
- rdset->type == dns_rdatatype_nsec3)
|
||||
+ if (rdset->rdclass != rdataset->rdclass ||
|
||||
+ (rdset->type != dns_rdatatype_nsec &&
|
||||
+ rdset->type != dns_rdatatype_nsec3))
|
||||
{
|
||||
- neg = rdset;
|
||||
+ continue;
|
||||
}
|
||||
- }
|
||||
- if (neg == NULL) {
|
||||
- return ISC_R_NOTFOUND;
|
||||
- }
|
||||
|
||||
- for (rdset = ISC_LIST_HEAD(name->list); rdset != NULL;
|
||||
- rdset = ISC_LIST_NEXT(rdset, link))
|
||||
- {
|
||||
- if (rdset->type == dns_rdatatype_rrsig &&
|
||||
- rdset->covers == neg->type)
|
||||
+ for (sigset = ISC_LIST_HEAD(name->list); sigset != NULL;
|
||||
+ sigset = ISC_LIST_NEXT(sigset, link))
|
||||
{
|
||||
- negsig = rdset;
|
||||
+ if (sigset->type == dns_rdatatype_rrsig &&
|
||||
+ sigset->covers == rdset->type)
|
||||
+ {
|
||||
+ neg = rdset;
|
||||
+ negsig = sigset;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
- if (negsig == NULL) {
|
||||
+ if (neg == NULL || negsig == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
/*
|
||||
@@ -238,6 +236,7 @@ isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, const dns_name_t *name) {
|
||||
rdataset->ttl = neg->ttl = negsig->ttl = ttl;
|
||||
rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
|
||||
rdataset->private6 = name;
|
||||
+
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
|
||||
index 1326cb3428..a4efc9a847 100644
|
||||
--- a/lib/dns/resolver.c
|
||||
+++ b/lib/dns/resolver.c
|
||||
@@ -5831,7 +5831,9 @@ validated(isc_task_t *task, isc_event_t *event) {
|
||||
result = dns_rdataset_addnoqname(
|
||||
vevent->rdataset,
|
||||
vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
|
||||
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ goto noanswer_response;
|
||||
+ }
|
||||
INSIST(vevent->sigrdataset != NULL);
|
||||
vevent->sigrdataset->ttl = vevent->rdataset->ttl;
|
||||
if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
|
||||
diff --git a/lib/ns/query.c b/lib/ns/query.c
|
||||
index f7f0623713..f0239b20b9 100644
|
||||
--- a/lib/ns/query.c
|
||||
+++ b/lib/ns/query.c
|
||||
@@ -7936,8 +7936,7 @@ query_addnoqnameproof(query_ctx_t *qctx) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- result = dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig);
|
||||
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
+ CHECK(dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig));
|
||||
|
||||
query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
|
||||
DNS_SECTION_AUTHORITY);
|
||||
|
||||
From 8051316fde01f4a4368e8a4cba24e6d2d483e5ce Mon Sep 17 00:00:00 2001
|
||||
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
|
||||
Date: Thu, 23 Jul 2026 10:26:08 +0000
|
||||
Subject: [PATCH 2/2] Fix: replace CHECK macro with inline equivalent in
|
||||
query.c
|
||||
|
||||
The CHECK macro is not defined in lib/ns/query.c (it is only defined
|
||||
locally in some other source files). Replace with inline equivalent
|
||||
that checks the result and goes to the cleanup label on failure.
|
||||
This preserves the security fix semantics: instead of crashing with
|
||||
RUNTIME_CHECK on error, gracefully jump to cleanup.
|
||||
---
|
||||
lib/ns/query.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/ns/query.c b/lib/ns/query.c
|
||||
index f0239b20b9..f265abfcef 100644
|
||||
--- a/lib/ns/query.c
|
||||
+++ b/lib/ns/query.c
|
||||
@@ -7936,7 +7936,10 @@ query_addnoqnameproof(query_ctx_t *qctx) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- CHECK(dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig));
|
||||
+ result = dns_rdataset_getnoqname(qctx->noqname, fname, neg, negsig);
|
||||
+ if (result != ISC_R_SUCCESS) {
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
query_addrrset(qctx, &fname, &neg, &negsig, dbuf,
|
||||
DNS_SECTION_AUTHORITY);
|
||||
@ -80,7 +80,7 @@ License: MPL-2.0 AND ISC AND MIT AND BSD-3-Clause AND BSD-2-Clause
|
||||
# Before rebasing bind, ensure bind-dyndb-ldap is ready to be rebuild and use side-tag with it.
|
||||
# Updating just bind will cause freeipa-dns-server package to be uninstallable.
|
||||
Version: 9.18.33
|
||||
Release: 19%{?dist}
|
||||
Release: 20%{?dist}
|
||||
Epoch: 32
|
||||
Url: https://www.isc.org/downloads/bind/
|
||||
#
|
||||
@ -170,6 +170,8 @@ Patch233: bind-9.18-CVE-2026-1519-test.patch
|
||||
Patch234: bind-9.18-CVE-2026-3039.patch
|
||||
# https://gitlab.isc.org/isc-projects/bind9/-/commit/7ce6ce37b1b04af0953ed2d3211587465085600e
|
||||
Patch235: bind-9.18-CVE-2026-5946.patch
|
||||
# https://github.com/isc-projects/bind9/commit/48f5aa5fb3746d6194edcc57e8792a8b3cc3b454
|
||||
Patch236: bind-9.18-CVE-2026-13204.patch
|
||||
|
||||
%{?systemd_ordering}
|
||||
# https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers
|
||||
@ -971,6 +973,10 @@ fi;
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Jul 23 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 32:9.18.33-20
|
||||
- Fix assertion failure on malformed NSEC/NSEC3 responses
|
||||
(CVE-2026-13204)
|
||||
|
||||
* Mon May 25 2026 Petr Menšík <pemensik@redhat.com> - 32:9.18.33-19
|
||||
- Fix GSS-API resource leak (CVE-2026-3039)
|
||||
- Invalid handling of CLASS != IN (CVE-2026-5946)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user