]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a stack use-after-free in qpzone 11956/head
authorEvan Hunt <each@isc.org>
Mon, 4 May 2026 23:23:42 +0000 (16:23 -0700)
committerEvan Hunt <each@isc.org>
Tue, 5 May 2026 23:17:25 +0000 (16:17 -0700)
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.

lib/dns/qpzone.c

index 445f63f58ee342398e0b1c3cb5446f65ee8bad6c..1b6958715f9537d5ff7768fd39e9f804e9e9eb83 100644 (file)
@@ -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);
        }
 
        /*