]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix use-after-free in resolver SIG(0) async verification path
authorOndřej Surý <ondrej@isc.org>
Tue, 17 Mar 2026 03:45:16 +0000 (04:45 +0100)
committerMichał Kępień <michal@isc.org>
Thu, 7 May 2026 11:09:18 +0000 (13:09 +0200)
When a SIG(0)-signed response triggers async ECDSA verification via
dns_message_checksig_async(), the respctx_t holds a raw pointer to
the resquery_t. If the fetch context is shut down while verification
is in flight (e.g. due to recursive-clients quota exhaustion), the
query is destroyed and the callback dereferences a dangling pointer.

Take a reference on the resquery_t when initializing the respctx_t,
and release it in both cleanup paths. The query's own reference to
the fetch context keeps the fctx alive transitively.

(cherry picked from commit 5b58caf5a2cd39d57a51b7b0373bfbc4877a96f9)

lib/dns/resolver.c

index 8b76b7da238e72f7068f8c2a4c9efa41ce7978c6..87f423a69b2be02894522f217f2793b5a8ae1ef1 100644 (file)
@@ -7632,6 +7632,7 @@ resquery_response(isc_result_t eresult, isc_region_t *region, void *arg) {
        return;
 
 cleanup:
+       resquery_detach(&rctx->query);
        isc_mem_putanddetach(&rctx->mctx, rctx, sizeof(*rctx));
 }
 
@@ -7981,6 +7982,7 @@ resquery_response_continue(void *arg, isc_result_t result) {
        rctx_done(rctx, result);
 
 cleanup:
+       resquery_detach(&rctx->query);
        isc_mem_putanddetach(&rctx->mctx, rctx, sizeof(*rctx));
 }
 
@@ -7994,7 +7996,7 @@ static void
 rctx_respinit(resquery_t *query, fetchctx_t *fctx, isc_result_t result,
              isc_region_t *region, respctx_t *rctx) {
        *rctx = (respctx_t){ .result = result,
-                            .query = query,
+                            .query = resquery_ref(query),
                             .fctx = fctx,
                             .broken_type = badns_response,
                             .retryopts = query->options };