]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Reject an RRSIG that covers a signature type
authorOndřej Surý <ondrej@isc.org>
Thu, 2 Jul 2026 08:05:30 +0000 (10:05 +0200)
committerOndřej Surý <ondrej@isc.org>
Thu, 2 Jul 2026 11:26:48 +0000 (13:26 +0200)
An RRSIG whose Type-Covered field is RRSIG is not a meta-type, so it
passed the message parser, and for an insecure domain the resolver
cached it as a standalone signature. The QP cache pairs every RRSIG
header with the non-signature header it covers and never expects the
covered type to itself be a signature, so a signature covering a
signature broke that invariant and aborted named on a crafted response.
Reject the record in the parser, and tighten the cache precondition so
a positive signature header must cover a non-signature type.

lib/dns/message.c
lib/dns/qpcache.c

index 424a11ff2d52393305415c1a1df7924742aefab8..0f7e6733af5c738fd55ef28e3c4c3942e9d08558 100644 (file)
@@ -1264,7 +1264,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
                        covers = dns_rdata_covers(rdata);
                        /* A signature can only cover a real rdata type */
                        if (covers == dns_rdatatype_none ||
-                           dns_rdatatype_ismeta(covers))
+                           dns_rdatatype_ismeta(covers) ||
+                           dns_rdatatype_issig(covers))
                        {
                                DO_ERROR(DNS_R_FORMERR);
                        }
index 2ced865b8338a8ce8a75e494e9893434e92c3d99..1a0d0f129d1562ed9c9108cde1e9fc81e13e7486 100644 (file)
@@ -2283,8 +2283,12 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode, dns_slabheader_t *newheader,
 
        REQUIRE(rdtype != dns_rdatatype_none);
        if (dns_rdatatype_issig(rdtype)) {
-               /* signature must be either negative or cover something */
-               REQUIRE(NEGATIVE(newheader) || covers != dns_rdatatype_none);
+               /*
+                * signature must be either negative or cover something
+                * that's not a signature
+                */
+               REQUIRE(NEGATIVE(newheader) || (covers != dns_rdatatype_none &&
+                                               !dns_rdatatype_issig(covers)));
        } else {
                /* non-signature it must cover nothing */
                REQUIRE(covers == dns_rdatatype_none);