From: Ondřej Surý Date: Mon, 29 Jun 2026 06:48:03 +0000 (+0200) Subject: Stop leaking DNSSEC keys past the zone key limit X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a957dd13fa9daca5f4cb2d162550c12e3ebeaf98;p=thirdparty%2Fbind9.git Stop leaking DNSSEC keys past the zone key limit find_zone_keys() collects every matching private key into a local list, hands the first DNS_MAXZONEKEYS keys to the caller, and frees the rest. On overflow it destroyed only the first surplus key before breaking out of the loop, so any keys after it stayed linked on the local list and were lost when the function returned. Unlink and destroy every list entry, transferring a key to the caller only while under the limit. No entry is left behind, so a zone with more than DNS_MAXZONEKEYS matching keys no longer leaks memory on each signing attempt. --- diff --git a/lib/dns/update.c b/lib/dns/update.c index 528ccd2898f..c8e6542d139 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -932,26 +932,25 @@ find_zone_keys(dns_zone_t *zone, isc_mem_t *mctx, unsigned int maxkeys, /* Add new 'dnskeys' to 'keys' */ ISC_LIST_FOREACH(keylist, k, link) { - if (count >= maxkeys) { - ISC_LIST_UNLINK(keylist, k, link); - dns_dnsseckey_destroy(mctx, &k); - result = ISC_R_NOSPACE; - break; - } + if (count < maxkeys) { + /* Detect inactive keys */ + if (!dns_dnssec_keyactive(k->key, now)) { + dst_key_setinactive(k->key, true); + } - /* Detect inactive keys */ - if (!dns_dnssec_keyactive(k->key, now)) { - dst_key_setinactive(k->key, true); + keys[count] = k->key; + k->key = NULL; + count++; } - keys[count] = k->key; - k->key = NULL; - count++; - ISC_LIST_UNLINK(keylist, k, link); dns_dnsseckey_destroy(mctx, &k); } + if (count >= maxkeys) { + result = ISC_R_NOSPACE; + } + *nkeys = count; return result; }