]> 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 18:18:30 +0000 (19:18 +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.

(cherry picked from commit 9135b71a7aca1a2dca994e959fad2e4f22e3f983)

lib/dns/client.c

index 5f9e5d0557adcd246fd8e08557fc6a3cae9e7bcc..a69bbab71c6dd25d31ddf636a48f2585ef4aa29c 100644 (file)
@@ -507,7 +507,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;
@@ -516,7 +516,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));
@@ -545,14 +544,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->db;
                        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);