From nobody Wed Nov 26 16:13:41 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4dGl3n2zPtz6JGqj for ; Wed, 26 Nov 2025 16:13:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4dGl3n1Pdnz3ZcX for ; Wed, 26 Nov 2025 16:13:41 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764173621; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=IpZFGiMm1aLZfhmE5QLDI1eNyq2sFvNmDESMDdhdycI=; b=JgW6ff7GBFpVZx05xu4BfqPFBKfiKnv0j2Bc2bCan4gG7XkA9yKbe+2iJYQBlHUVYkiihx pISMhVHR5mW83IAREy8hwQF8wdpIYmO2OovSo/+cg5nWMAZc80mxDb+eAIZqigxXG4e82U ID57OkyBsgdeAaeIbECWtgAO9yMzVdef91CNUF8AW0/qBHP+FXYsmwk9HYmdSrTc26G4tW ExOzgvy5fv5USbUihFdk89l8jZiQ+wbTI7JPOCQ5iE66aBor/TbvA11v96o7qp0MMUKV/8 MH966h4e7JZKUUw+WNQrhPM9ELE2VNtGIlQsmQPXUJ4PonB4U5/Y4+kZLnWXyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764173621; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=IpZFGiMm1aLZfhmE5QLDI1eNyq2sFvNmDESMDdhdycI=; b=Exwl05iVYbFjDo4vVuidYbd1jX9yq9VOEcMiWz1KSdSMqgrlCPJwuG2+RCRDTs7egqcFqI XaV65giBUkaV8DMvry3zbDtNDZ3heHehtrjg3MxiJgZdA+zVWemvUi3G0PGm32nfpBZDNG LI9vpF00nO9jzYZ4DscLcsRvfrrxkGrYNlUhS+nZzrwu8Svc3s39ZkNAI9NNDrwTtRKVvd ct+RNZuD82Y9FFzHiBdn04kgPvPMzp08JIVDmCsisApWeLHZ77SQcsK2uHaMTV2kRWl52O wxA+5bOX6iUbtFr6RuzxN9UfEgQBBmR3lVe27AvIsJ/g8X6xzvyUFfgIOh8bWA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1764173621; a=rsa-sha256; cv=none; b=XZ65uDKApkMzXVuB5L/vRJKgz9Hvqg9fevGEF22fTS4jFRPzkCPtHPET5Lc0RVmvdIJEy4 MHiU3ySc4Gd3ePiO3I3PxhxgoCR2WMs1JL9GBpAMhygEfY4d89QOwyPJILdgYP0wxdIUYx FlmBkYNTmrGAWBGgZ9a+CAfC5DbrLm0pk/t4mq/lGEUwgU4zIoD0vTy+RxvcfrellUUoJI dRoPK6UDOBtF1UbEbR2ixMCyahATzgdFmJfKttumocheULJj1BGzi+nm1EgK9L5TkO7hso MnbVKJvTpAXA4t3S3SpDntYud0H/jckGa2yd8ZSB2V/R4xIVC0yV1q/RFaYkAw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4dGl3n0wF8ztbp for ; Wed, 26 Nov 2025 16:13:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33d75 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 26 Nov 2025 16:13:41 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Gordon Tetlow Subject: git: 9b0808259a8a - releng/13.5 - Add a fix to scrub unsolicited NS RRSets to prevent cache poisoning. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: gordon X-Git-Repository: src X-Git-Refname: refs/heads/releng/13.5 X-Git-Reftype: branch X-Git-Commit: 9b0808259a8a8dcd1236038378b8abe0617b0777 Auto-Submitted: auto-generated Date: Wed, 26 Nov 2025 16:13:41 +0000 Message-Id: <69272735.33d75.7ca3914c@gitrepo.freebsd.org> The branch releng/13.5 has been updated by gordon: URL: https://cgit.FreeBSD.org/src/commit/?id=9b0808259a8a8dcd1236038378b8abe0617b0777 commit 9b0808259a8a8dcd1236038378b8abe0617b0777 Author: Gordon Tetlow AuthorDate: 2025-11-26 16:09:36 +0000 Commit: Gordon Tetlow CommitDate: 2025-11-26 16:09:36 +0000 Add a fix to scrub unsolicited NS RRSets to prevent cache poisoning. Approved by: so Obtained from: NLnet Labs Security: FreeBSD-SA-25:10.unbound Security: CVE-2025-11411 --- contrib/unbound/iterator/iter_scrub.c | 55 ++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/contrib/unbound/iterator/iter_scrub.c b/contrib/unbound/iterator/iter_scrub.c index 49a5f5da19c2..b02b4dc484bf 100644 --- a/contrib/unbound/iterator/iter_scrub.c +++ b/contrib/unbound/iterator/iter_scrub.c @@ -418,12 +418,13 @@ shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count) * @param qinfo: original query. * @param region: where to allocate synthesized CNAMEs. * @param env: module env with config options. + * @param zonename: name of server zone. * @return 0 on error. */ static int scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, struct query_info* qinfo, struct regional* region, - struct module_env* env) + struct module_env* env, uint8_t* zonename) { uint8_t* sname = qinfo->qname; size_t snamelen = qinfo->qname_len; @@ -431,7 +432,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, int cname_length = 0; /* number of CNAMEs, or DNAMEs */ if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN) + FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN && + FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN) return 1; /* For the ANSWER section, remove all "irrelevant" records and add @@ -470,6 +472,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, &aliaslen, pkt)) { verbose(VERB_ALGO, "synthesized CNAME " "too long"); + if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) { + prev = rrset; + rrset = rrset->rrset_all_next; + continue; + } return 0; } cname_length++; @@ -634,6 +641,45 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, "RRset:", pkt, msg, prev, &rrset); continue; } + /* If the NS set is a promiscuous NS set, scrub that + * to remove potential for poisonous contents that + * affects other names in the same zone. Remove + * promiscuous NS sets in positive answers, that + * thus have records in the answer section. Nodata + * and nxdomain promiscuous NS sets have been removed + * already. Since the NS rrset is scrubbed, its + * address records are also not marked to be allowed + * and are removed later. */ + if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR && + msg->an_rrsets != 0 && + 1 /* env->cfg->iter_scrub_promiscuous */) { + remove_rrset("normalize: removing promiscuous " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + /* Also delete promiscuous NS for other RCODEs */ + if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR + && 1 /* env->cfg->iter_scrub_promiscuous */) { + remove_rrset("normalize: removing promiscuous " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + /* Also delete promiscuous NS for NOERROR with nodata + * for authoritative answers, not for delegations. + * NOERROR with an_rrsets!=0 already handled. + * Also NOERROR and soa_in_auth already handled. + * NOERROR with an_rrsets==0, and not a referral. + * referral is (NS not the zonename, noSOA). + */ + if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR + && msg->an_rrsets == 0 + && !(dname_pkt_compare(pkt, rrset->dname, + zonename) != 0 && !soa_in_auth(msg)) + && 1 /* env->cfg->iter_scrub_promiscuous */) { + remove_rrset("normalize: removing promiscuous " + "RRset:", pkt, msg, prev, &rrset); + continue; + } if(nsset == NULL) { nsset = rrset; } else { @@ -1044,7 +1090,8 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg, /* this is not required for basic operation but is a forgery * resistance (security) feature */ if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) && + FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN || + FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) && msg->qdcount == 0) return 0; @@ -1058,7 +1105,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg, } /* normalize the response, this cleans up the additional. */ - if(!scrub_normalize(pkt, msg, qinfo, region, env)) + if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename)) return 0; /* delete all out-of-zone information */ if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))