From: Evan Hunt Date: Mon, 4 May 2026 23:23:42 +0000 (-0700) Subject: Fix a stack use-after-free in qpzone X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e31dc535391ddf465323034d9900d02e1b96281;p=thirdparty%2Fbind9.git Fix a stack use-after-free in qpzone In previous_closest_nsec(), a new qpreader was opened to search the NSEC tree. It was possible for that to be used to update a QP iterator object owned by the caller, and then be destroyed when the function returned. This has been addressed by having the caller open the NSEC qpreader instead. --- diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 445f63f58ee..1b6958715f9 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -269,6 +269,7 @@ typedef struct { qpzonedb_t *qpdb; qpz_version_t *version; dns_qpread_t qpr; + dns_qpread_t nqpr; uint32_t serial; unsigned int options; dns_qpchain_t chain; @@ -2969,7 +2970,6 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, dns_name_t *name, qpznode_t **nodep, dns_qpiter_t *nit, bool *firstp) { isc_result_t result; - dns_qpread_t qpr; REQUIRE(nodep != NULL && *nodep == NULL); REQUIRE(type == dns_rdatatype_nsec3 || firstp != NULL); @@ -2980,8 +2980,6 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, return result; } - dns_qpmulti_query(search->qpdb->nsec, &qpr); - for (;;) { if (*firstp) { /* @@ -2989,8 +2987,8 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, * It is the first node sought in the NSEC tree. */ *firstp = false; - result = dns_qp_lookup(&qpr, name, NULL, nit, NULL, - NULL, NULL); + result = dns_qp_lookup(&search->nqpr, name, NULL, nit, + NULL, NULL, NULL); INSIST(result != ISC_R_NOTFOUND); if (result == ISC_R_SUCCESS) { /* @@ -3044,7 +3042,6 @@ previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search, } } - dns_qpread_destroy(search->qpdb->nsec, &qpr); return result; } @@ -3398,6 +3395,7 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, nsec3 = true; } else { dns_qpmulti_query(qpdb->tree, &search.qpr); + dns_qpmulti_query(qpdb->nsec, &search.nqpr); } /* @@ -3846,6 +3844,7 @@ tree_exit: dns_qpread_destroy(qpdb->nsec3, &search.qpr); } else { dns_qpread_destroy(qpdb->tree, &search.qpr); + dns_qpread_destroy(qpdb->nsec, &search.nqpr); } /*