]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix read UAF in BIND9 dns_client_resolve() via DNAME Response
authorOndřej Surý <ondrej@isc.org>
Fri, 20 Feb 2026 10:58:13 +0000 (11:58 +0100)
committerOndřej Surý <ondrej@isc.org>
Fri, 20 Feb 2026 10:58:13 +0000 (11:58 +0100)
An attacker controlling a malicious DNS server returns a DNAME record,
and the we stores a pointer to resp->foundname, frees the response
structure, then uses the dangling pointer in dns_name_fullcompare()
possibly causing invalid match.  Only the `delv`is affected.  This has
been fixed.

lib/dns/client.c

index 2097fa3ec58153e1d2691267b2b8253a8dcfe50c..6027c0d081070c82fc915f8e3194dd20a94201b2 100644 (file)
@@ -490,7 +490,7 @@ client_resfind(resctx_t *rctx, dns_fetchresponse_t *resp) {
        name = dns_fixedname_name(&rctx->name);
 
        do {
-               dns_name_t *fname = NULL;
+               dns_name_t *fname = dns_fixedname_initname(&foundname);
                dns_name_t *ansname = NULL;
                dns_db_t *db = NULL;
                dns_dbnode_t *node = NULL;
@@ -499,7 +499,6 @@ client_resfind(resctx_t *rctx, dns_fetchresponse_t *resp) {
                want_restart = false;
 
                if (resp == NULL) {
-                       fname = dns_fixedname_initname(&foundname);
                        INSIST(!dns_rdataset_isassociated(rctx->rdataset));
                        INSIST(rctx->sigrdataset == NULL ||
                               !dns_rdataset_isassociated(rctx->sigrdataset));
@@ -528,14 +527,13 @@ client_resfind(resctx_t *rctx, dns_fetchresponse_t *resp) {
                                goto done;
                        }
                } else {
-                       INSIST(resp != NULL);
                        INSIST(resp->fetch == rctx->fetch);
                        dns_resolver_destroyfetch(&rctx->fetch);
                        db = resp->cache;
                        node = resp->node;
                        result = resp->result;
                        vresult = resp->vresult;
-                       fname = resp->foundname;
+                       dns_name_copy(resp->foundname, fname);
                        INSIST(resp->rdataset == rctx->rdataset);
                        INSIST(resp->sigrdataset == rctx->sigrdataset);
                        dns_resolver_freefresp(&resp);