From 1d736cf451034c27041feafa96eb74ad4098e8e6 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 24 May 2023 14:26:04 +0000 Subject: [PATCH] Fix an interfacemgr use-after-free error in zoneconf.c:isself() The 'named_g_server->interfacemgr' pointer is saved in the zone structure using dns_zone_setisself(), as a void* argument to be passed to the isself() callback, so there is no attach/detach, and when shutting down, the interface manager can be destroyed by the shutdown_server(), running in exclusive mode, and causing isself() to crash when trying to use the pointer. Instead of keeping the interface manager pointer in the zone structure, just check and use the 'named_g_server->interfacemgr' itself, as it was implemented originally in the 3aca8e5bf3740bbcc3bb13dde242d7cc369abb27 commit. Later, in the 8eb88aafee951859264e36c315b1289cd8c2088b commit, the code was changed to pass the interface manager pointer using the additional void* argument, but the commit message doesn't mention if there was any practical reason for that. Additionally, don't pass the interfacemgr pointer to the ns_interfacemgr_getaclenv() function before it is checked against NULL. (cherry picked from commit 64d69e4adc1f4c4dfb51f6880eb7b48d76d38792) --- bin/named/zoneconf.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 8b731adbb2..e4d73ebcd9 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -777,23 +777,27 @@ checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, static bool isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) { - ns_interfacemgr_t *interfacemgr = (ns_interfacemgr_t *)arg; - dns_aclenv_t *env = ns_interfacemgr_getaclenv(interfacemgr); - dns_view_t *view; + dns_aclenv_t *env = NULL; + dns_view_t *view = NULL; dns_tsigkey_t *key = NULL; isc_netaddr_t netsrc; isc_netaddr_t netdst; - if (interfacemgr == NULL) { + UNUSED(arg); + + /* interfacemgr can be destroyed only in exclusive mode. */ + if (named_g_server->interfacemgr == NULL) { return (true); } - if (!ns_interfacemgr_listeningon(interfacemgr, dstaddr)) { + if (!ns_interfacemgr_listeningon(named_g_server->interfacemgr, dstaddr)) + { return (false); } isc_netaddr_fromsockaddr(&netsrc, srcaddr); isc_netaddr_fromsockaddr(&netdst, dstaddr); + env = ns_interfacemgr_getaclenv(named_g_server->interfacemgr); for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) @@ -1315,7 +1319,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, cfg_obj_asboolean(obj)); - dns_zone_setisself(zone, isself, named_g_server->interfacemgr); + dns_zone_setisself(zone, isself, NULL); CHECK(configure_zone_acl( zconfig, vconfig, config, allow_transfer, ac, zone,