From: Colin Vidal Date: Thu, 2 Apr 2026 07:17:17 +0000 (+0200) Subject: fix NULL dereference in dns_view_bestzonecut() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc03a876ae38ce16e8029878d31581fc46e7388e;p=thirdparty%2Fbind9.git fix NULL dereference in dns_view_bestzonecut() When `dns_view_bestzonecut()` is called with a NULL `delegsetp`, it calls `bestzonecut_zone()` with a NULL `rdataset` pointer but there is a non-guarded de-reference of the `rdataset` pointer in `bestzonecut_zone()`. In practice, the only current situation where `dns_view_bestzonecut()` is called with NULL `delegsetp` is from a case of `seek_ds()` _and_ the non-guarded dereference occurs only if there is a static-stub local zone matching the zonecut `seek_ds()` is looking for. It's unclear if such flow is actually possible. The `rdataset` is now always valid inside `dns_view_bestzonecut()`. (It was initially set only if `delegsetp` was set to avoid extra works in the qpzone, which can be skipped when `rdataset` is NULL, but this doesn't really make a difference, considering we are in a slow path considering the result wasn't found in this case.) --- diff --git a/lib/dns/view.c b/lib/dns/view.c index 2e4853d928b..eca63fae9ea 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -1140,19 +1140,14 @@ dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name, unsigned int options, bool usehints, bool usecache, dns_delegset_t **delegsetp) { isc_result_t result; - dns_rdataset_t rdatasetdata = DNS_RDATASET_INIT; - dns_rdataset_t *rdataset = NULL; + dns_rdataset_t rdataset = DNS_RDATASET_INIT; REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(view->frozen); - - if (delegsetp != NULL) { - REQUIRE(*delegsetp == NULL); - rdataset = &rdatasetdata; - } + REQUIRE(delegsetp == NULL || *delegsetp == NULL); result = bestzonecut_zone(view, name, fname, dcname, now, options, - rdataset); + &rdataset); if (result == DNS_R_NXDOMAIN && usecache) { /* @@ -1167,14 +1162,14 @@ dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name, * cache can have a more precise delegation. */ bestzonecut_zoneorcache(view, name, fname, dcname, now, options, - rdataset, delegsetp); + &rdataset, delegsetp); } /* * No local zone nor cache match. Last attempt with the hints. */ if (result == DNS_R_NXDOMAIN && usehints) { - result = bestzonecut_hints(view, fname, dcname, now, rdataset); + result = bestzonecut_hints(view, fname, dcname, now, &rdataset); } if (result != ISC_R_SUCCESS) { @@ -1190,10 +1185,10 @@ dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name, * the same, and this avoid adding extra code here to extract * A/AAAA rdataset if any. */ - dns_delegset_fromnsrdataset(rdataset, delegsetp); + dns_delegset_fromnsrdataset(&rdataset, delegsetp); } - dns_rdataset_cleanup(rdataset); + dns_rdataset_cleanup(&rdataset); return result; }