bcb1e2
From b1871274cd2c97b63f3b90d608b7f8936d4ff3c5 Mon Sep 17 00:00:00 2001
bcb1e2
From: Mark Andrews <marka@isc.org>
bcb1e2
Date: Wed, 24 Aug 2022 12:21:50 +1000
bcb1e2
Subject: [PATCH] Have dns_zt_apply lock the zone table
bcb1e2
bcb1e2
There where a number of places where the zone table should have
bcb1e2
been locked, but wasn't, when dns_zt_apply was called.
bcb1e2
bcb1e2
Added a isc_rwlocktype_t type parameter to dns_zt_apply and adjusted
bcb1e2
all calls to using it.  Removed locks in callers.
bcb1e2
bcb1e2
Modified upstream commit for v9_16
bcb1e2
---
bcb1e2
 bin/named/server.c       | 12 +++++++-----
bcb1e2
 bin/named/statschannel.c | 12 +++++++-----
bcb1e2
 lib/dns/include/dns/zt.h |  3 ++-
bcb1e2
 lib/dns/tests/zt_test.c  |  4 ++--
bcb1e2
 lib/dns/view.c           |  3 ++-
bcb1e2
 lib/dns/zt.c             | 29 ++++++++++++++++++-----------
bcb1e2
 6 files changed, 38 insertions(+), 25 deletions(-)
bcb1e2
bcb1e2
diff --git a/bin/named/server.c b/bin/named/server.c
bcb1e2
index 860ccae..c2a5887 100644
bcb1e2
--- a/bin/named/server.c
bcb1e2
+++ b/bin/named/server.c
bcb1e2
@@ -9458,7 +9458,8 @@ cleanup:
bcb1e2
 		if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0)
bcb1e2
 		{
bcb1e2
 			dns_view_setviewrevert(view);
bcb1e2
-			(void)dns_zt_apply(view->zonetable, false, NULL,
bcb1e2
+			(void)dns_zt_apply(view->zonetable,
bcb1e2
+					   isc_rwlocktype_read, false, NULL,
bcb1e2
 					   removed, view);
bcb1e2
 		}
bcb1e2
 		dns_view_detach(&view);
bcb1e2
@@ -10901,8 +10902,8 @@ add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
bcb1e2
 	ISC_LIST_INIT(vle->zonelist);
bcb1e2
 	ISC_LIST_APPEND(dctx->viewlist, vle, link);
bcb1e2
 	if (dctx->dumpzones) {
bcb1e2
-		result = dns_zt_apply(view->zonetable, true, NULL,
bcb1e2
-				      add_zone_tolist, dctx);
bcb1e2
+		result = dns_zt_apply(view->zonetable, isc_rwlocktype_read,
bcb1e2
+				      true, NULL, add_zone_tolist, dctx);
bcb1e2
 	}
bcb1e2
 	return (result);
bcb1e2
 }
bcb1e2
@@ -12248,8 +12249,9 @@ named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
bcb1e2
 		for (view = ISC_LIST_HEAD(server->viewlist); view != NULL;
bcb1e2
 		     view = ISC_LIST_NEXT(view, link))
bcb1e2
 		{
bcb1e2
-			result = dns_zt_apply(view->zonetable, false, NULL,
bcb1e2
-					      synczone, &cleanup);
bcb1e2
+			result = dns_zt_apply(view->zonetable,
bcb1e2
+					      isc_rwlocktype_none, false,
bcb1e2
+					      NULL, synczone, &cleanup);
bcb1e2
 			if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS)
bcb1e2
 			{
bcb1e2
 				tresult = result;
bcb1e2
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
bcb1e2
index 8ff2567..832ce93 100644
bcb1e2
--- a/bin/named/statschannel.c
bcb1e2
+++ b/bin/named/statschannel.c
bcb1e2
@@ -2296,8 +2296,9 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
bcb1e2
 		if ((flags & STATS_XML_ZONES) != 0) {
bcb1e2
 			TRY0(xmlTextWriterStartElement(writer,
bcb1e2
 						       ISC_XMLCHAR "zones"));
bcb1e2
-			result = dns_zt_apply(view->zonetable, true, NULL,
bcb1e2
-					      zone_xmlrender, writer);
bcb1e2
+			result = dns_zt_apply(view->zonetable,
bcb1e2
+					      isc_rwlocktype_read, true,
bcb1e2
+					      NULL, zone_xmlrender, writer);
bcb1e2
 			if (result != ISC_R_SUCCESS) {
bcb1e2
 				goto error;
bcb1e2
 			}
bcb1e2
@@ -3069,9 +3070,10 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
bcb1e2
 			CHECKMEM(za);
bcb1e2
 
bcb1e2
 			if ((flags & STATS_JSON_ZONES) != 0) {
bcb1e2
-				result = dns_zt_apply(view->zonetable, true,
bcb1e2
-						      NULL, zone_jsonrender,
bcb1e2
-						      za);
bcb1e2
+				result = dns_zt_apply(view->zonetable,
bcb1e2
+						      isc_rwlocktype_read,
bcb1e2
+						      true, NULL,
bcb1e2
+						      zone_jsonrender, za);
bcb1e2
 				if (result != ISC_R_SUCCESS) {
bcb1e2
 					goto error;
bcb1e2
 				}
bcb1e2
diff --git a/lib/dns/include/dns/zt.h b/lib/dns/include/dns/zt.h
bcb1e2
index 4a1b263..1c6c789 100644
bcb1e2
--- a/lib/dns/include/dns/zt.h
bcb1e2
+++ b/lib/dns/include/dns/zt.h
bcb1e2
@@ -168,7 +168,8 @@ dns_zt_freezezones(dns_zt_t *zt, dns_view_t *view, bool freeze);
bcb1e2
  */
bcb1e2
 
bcb1e2
 isc_result_t
bcb1e2
-dns_zt_apply(dns_zt_t *zt, bool stop, isc_result_t *sub,
bcb1e2
+dns_zt_apply(dns_zt_t *zt, isc_rwlocktype_t lock, bool stop,
bcb1e2
+	     isc_result_t *sub,
bcb1e2
 	     isc_result_t (*action)(dns_zone_t *, void *), void *uap);
bcb1e2
 /*%<
bcb1e2
  * Apply a given 'action' to all zone zones in the table.
bcb1e2
diff --git a/lib/dns/tests/zt_test.c b/lib/dns/tests/zt_test.c
bcb1e2
index 7945a0b..bfacb94 100644
bcb1e2
--- a/lib/dns/tests/zt_test.c
bcb1e2
+++ b/lib/dns/tests/zt_test.c
bcb1e2
@@ -136,8 +136,8 @@ apply(void **state) {
bcb1e2
 	assert_non_null(view->zonetable);
bcb1e2
 
bcb1e2
 	assert_int_equal(nzones, 0);
bcb1e2
-	result = dns_zt_apply(view->zonetable, false, NULL, count_zone,
bcb1e2
-			      &nzones);
bcb1e2
+	result = dns_zt_apply(view->zonetable, isc_rwlocktype_read, false,
bcb1e2
+			      NULL, count_zone, &nzones);
bcb1e2
 	assert_int_equal(result, ISC_R_SUCCESS);
bcb1e2
 	assert_int_equal(nzones, 1);
bcb1e2
 
bcb1e2
diff --git a/lib/dns/view.c b/lib/dns/view.c
bcb1e2
index 8c7e40a..dcb0f18 100644
bcb1e2
--- a/lib/dns/view.c
bcb1e2
+++ b/lib/dns/view.c
bcb1e2
@@ -704,7 +704,8 @@ dns_view_dialup(dns_view_t *view) {
bcb1e2
 	REQUIRE(DNS_VIEW_VALID(view));
bcb1e2
 	REQUIRE(view->zonetable != NULL);
bcb1e2
 
bcb1e2
-	(void)dns_zt_apply(view->zonetable, false, NULL, dialup, NULL);
bcb1e2
+	(void)dns_zt_apply(view->zonetable, isc_rwlocktype_read, false,
bcb1e2
+			   NULL, dialup, NULL);
bcb1e2
 }
bcb1e2
 
bcb1e2
 void
bcb1e2
diff --git a/lib/dns/zt.c b/lib/dns/zt.c
bcb1e2
index 8ca9cd6..1bfc308 100644
bcb1e2
--- a/lib/dns/zt.c
bcb1e2
+++ b/lib/dns/zt.c
bcb1e2
@@ -223,7 +223,8 @@ flush(dns_zone_t *zone, void *uap) {
bcb1e2
 static void
bcb1e2
 zt_destroy(dns_zt_t *zt) {
bcb1e2
 	if (atomic_load_acquire(&zt->flush)) {
bcb1e2
-		(void)dns_zt_apply(zt, false, NULL, flush, NULL);
bcb1e2
+		(void)dns_zt_apply(zt, isc_rwlocktype_none, false, NULL,
bcb1e2
+				   flush, NULL);
bcb1e2
 	}
bcb1e2
 	dns_rbt_destroy(&zt->table);
bcb1e2
 	isc_rwlock_destroy(&zt->rwlock);
bcb1e2
@@ -265,9 +266,8 @@ dns_zt_load(dns_zt_t *zt, bool stop, bool newonly) {
bcb1e2
 	struct zt_load_params params;
bcb1e2
 	REQUIRE(VALID_ZT(zt));
bcb1e2
 	params.newonly = newonly;
bcb1e2
-	RWLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
-	result = dns_zt_apply(zt, stop, NULL, load, &params);
bcb1e2
-	RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
+	result = dns_zt_apply(zt, isc_rwlocktype_read, stop, NULL, load,
bcb1e2
+			      &params);
bcb1e2
 	return (result);
bcb1e2
 }
bcb1e2
 
bcb1e2
@@ -338,9 +338,8 @@ dns_zt_asyncload(dns_zt_t *zt, bool newonly, dns_zt_allloaded_t alldone,
bcb1e2
 	zt->loaddone = alldone;
bcb1e2
 	zt->loaddone_arg = arg;
bcb1e2
 
bcb1e2
-	RWLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
-	result = dns_zt_apply(zt, false, NULL, asyncload, zt);
bcb1e2
-	RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
+	result = dns_zt_apply(zt, isc_rwlocktype_read, false, NULL,
bcb1e2
+			      asyncload, zt);
bcb1e2
 
bcb1e2
 	/*
bcb1e2
 	 * Have all the loads completed?
bcb1e2
@@ -386,9 +385,8 @@ dns_zt_freezezones(dns_zt_t *zt, dns_view_t *view, bool freeze) {
bcb1e2
 
bcb1e2
 	REQUIRE(VALID_ZT(zt));
bcb1e2
 
bcb1e2
-	RWLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
-	result = dns_zt_apply(zt, false, &tresult, freezezones, &params);
bcb1e2
-	RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
bcb1e2
+	result = dns_zt_apply(zt, isc_rwlocktype_read, false, &tresult,
bcb1e2
+			      freezezones, &params);
bcb1e2
 	if (tresult == ISC_R_NOTFOUND) {
bcb1e2
 		tresult = ISC_R_SUCCESS;
bcb1e2
 	}
bcb1e2
@@ -522,7 +520,8 @@ dns_zt_setviewrevert(dns_zt_t *zt) {
bcb1e2
 }
bcb1e2
 
bcb1e2
 isc_result_t
bcb1e2
-dns_zt_apply(dns_zt_t *zt, bool stop, isc_result_t *sub,
bcb1e2
+dns_zt_apply(dns_zt_t *zt, isc_rwlocktype_t lock, bool stop,
bcb1e2
+	     isc_result_t *sub,
bcb1e2
 	     isc_result_t (*action)(dns_zone_t *, void *), void *uap) {
bcb1e2
 	dns_rbtnode_t *node;
bcb1e2
 	dns_rbtnodechain_t chain;
bcb1e2
@@ -532,6 +531,10 @@ dns_zt_apply(dns_zt_t *zt, bool stop, isc_result_t *sub,
bcb1e2
 	REQUIRE(VALID_ZT(zt));
bcb1e2
 	REQUIRE(action != NULL);
bcb1e2
 
bcb1e2
+	if (lock != isc_rwlocktype_none) {
bcb1e2
+		RWLOCK(&zt->rwlock, lock);
bcb1e2
+	}
bcb1e2
+
bcb1e2
 	dns_rbtnodechain_init(&chain);
bcb1e2
 	result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
bcb1e2
 	if (result == ISC_R_NOTFOUND) {
bcb1e2
@@ -568,6 +571,10 @@ cleanup:
bcb1e2
 		*sub = tresult;
bcb1e2
 	}
bcb1e2
 
bcb1e2
+	if (lock != isc_rwlocktype_none) {
bcb1e2
+		RWUNLOCK(&zt->rwlock, lock);
bcb1e2
+	}
bcb1e2
+
bcb1e2
 	return (result);
bcb1e2
 }
bcb1e2
 
bcb1e2
-- 
bcb1e2
2.39.2
bcb1e2