]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Properly detect private records before copying
authorMark Andrews <marka@isc.org>
Wed, 8 Apr 2026 04:43:23 +0000 (14:43 +1000)
committerMark Andrews <marka@isc.org>
Thu, 2 Jul 2026 00:08:52 +0000 (10:08 +1000)
We were triggering an assertion when trying to copy a private record
to a buffer for modifying.  Extend the private type detection and
copy the contents after we have rejected invalid private records.

lib/dns/nsec3.c

index 64e49ad3f0fe30699d6592034ff53a1f374c6cb8..e889b877c29919fd9eb41d491491ce7b62917611 100644 (file)
@@ -1123,20 +1123,31 @@ try_private:
        DNS_RDATASET_FOREACH(&rdataset) {
                dns_rdata_t rdata = DNS_RDATA_INIT;
                dns_rdataset_current(&rdataset, &rdata);
-               INSIST(rdata.length <= sizeof(buf));
-               memmove(buf, rdata.data, rdata.length);
 
                /*
-                * Private NSEC3 record length >= 6.
-                * <0(1), hash(1), flags(1), iterations(2), saltlen(1)>
+                * Filter out non-private records.  Delete private records that
+                * were being used to creating NSEC3 chains and add private
+                * records to remove that chains that were in the process of
+                * being constructed.  If nonsec is set and there is a record
+                * saying to go insecure preserve it.
+                *
+                * Private records have 6 <= length <= 261 (6 + saltlen) and
+                * the following structure:
+                *
+                * <0(1), hash(1), flags(1), iterations(2), saltlen(1),
+                * salt(0..255)>
                 */
-               if (rdata.length < 6 || buf[0] != 0 ||
-                   (buf[2] & DNS_NSEC3FLAG_REMOVE) != 0 ||
-                   (nonsec && (buf[2] & DNS_NSEC3FLAG_NONSEC) != 0))
+               if (rdata.length < 6 || rdata.data[0] != 0 ||
+                   rdata.data[5] + 6 != rdata.length ||
+                   (rdata.data[2] & DNS_NSEC3FLAG_REMOVE) != 0 ||
+                   (nonsec && (rdata.data[2] & DNS_NSEC3FLAG_NONSEC) != 0))
                {
                        continue;
                }
 
+               INSIST(rdata.length <= sizeof(buf));
+               memmove(buf, rdata.data, rdata.length);
+
                dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, 0,
                                     &rdata, &tuple);
                CHECK(do_one_tuple(&tuple, db, ver, diff));