bind9+unbound: 5-MOAD scan; 2 defects (bind9-0001 CWE-407 zone_registerinclude O(N^2), unbound-0001 CWE-407 rdata_duplicate O(R^2))

This commit is contained in:
russell@unturf.com 2026-03-31 21:38:43 -04:00
parent d9d4b30def
commit 3aae5093e5
6 changed files with 488 additions and 0 deletions

View file

@ -0,0 +1,79 @@
# UNDF:
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -302,6 +302,7 @@ struct dns_zone {
const FILE *stream; /* loading from a stream? */
ISC_LIST(dns_include_t) includes; /* Include files */
ISC_LIST(dns_include_t) newincludes; /* Loading */
+ isc_ht_t *newincludes_ht; /* O(1) dup-check during loading */
unsigned int nincludes;
@@ -1165,6 +1166,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, isc_loopmgr_t *loopmgr) {
.includes = ISC_LIST_INITIALIZER,
.newincludes = ISC_LIST_INITIALIZER,
+ .newincludes_ht = NULL,
.nincludes = 0,
@@ -2703,6 +2704,26 @@ zone_registerinclude(const char *filename, void *arg) {
REQUIRE(DNS_ZONE_VALID(zone));
if (filename == NULL) {
return;
}
+ /*
+ * On first call, create a hash table for O(1) duplicate detection.
+ * Without this, the ISC_LIST_FOREACH scan below is O(N) per call,
+ * making the total zone-load cost O(N^2) in the number of $INCLUDE
+ * directives. CWE-407.
+ */
+ if (zone->newincludes_ht == NULL) {
+ isc_ht_init(&zone->newincludes_ht, zone->mctx, 4,
+ ISC_HT_CASE_SENSITIVE);
+ }
+
+ if (zone->newincludes_ht != NULL) {
+ void *found = NULL;
+ uint32_t flen = (uint32_t)strlen(filename);
+ if (isc_ht_find(zone->newincludes_ht,
+ (const unsigned char *)filename, flen,
+ &found) == ISC_R_SUCCESS) {
+ return; /* duplicate */
+ }
/*
* Suppress duplicates.
- */
- ISC_LIST_FOREACH (zone->newincludes, inc, link) {
- if (strcmp(filename, inc->name) == 0) {
- return;
- }
- }
+ * (keep list append below; list is still needed for iteration) */
+ }
dns_include_t *inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
inc->name = isc_mem_strdup(zone->mctx, filename);
@@ -2730,6 +2751,12 @@ zone_registerinclude(const char *filename, void *arg) {
isc_time_settoepoch(&inc->filetime);
}
+ if (zone->newincludes_ht != NULL) {
+ uint32_t flen = (uint32_t)strlen(filename);
+ (void)isc_ht_add(zone->newincludes_ht,
+ (const unsigned char *)inc->name, flen, inc);
+ }
+
ISC_LIST_APPEND(zone->newincludes, inc, link);
}
@@ -5695,6 +5722,11 @@ zone_loaddone(void *arg, isc_result_t result) {
ISC_LIST_FOREACH (zone->includes, inc, link) {
ISC_LIST_UNLINK(zone->includes, inc, link);
...
+ if (zone->newincludes_ht != NULL) {
+ isc_ht_destroy(&zone->newincludes_ht);
+ zone->newincludes_ht = NULL;
+ }
+
zone->nincludes = 0;
ISC_LIST_FOREACH (zone->newincludes, inc, link) {