1a4de8
From 651fc773a6e154466998424e975bce3fdb8566d8 Mon Sep 17 00:00:00 2001
1a4de8
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
1a4de8
Date: Wed, 27 Nov 2019 17:06:28 +0000
1a4de8
Subject: [PATCH 3/4] Merge branch
1a4de8
 '1350-threadsanitizer-data-race-rbt-c-1312-in-dns_rbt_addnode-v9_11' into
1a4de8
 'v9_11'
1a4de8
1a4de8
Resolve "ThreadSanitizer: data race rbt.c:1312 in dns_rbt_addnode"
1a4de8
1a4de8
See merge request isc-projects/bind9!2651
1a4de8
1a4de8
(cherry picked from commit a5fb8c812728cb5fc923f60d6707d953d704719f)
1a4de8
---
1a4de8
 lib/dns/rbtdb.c | 24 +++++++++++++++++++++---
1a4de8
 1 file changed, 21 insertions(+), 3 deletions(-)
1a4de8
1a4de8
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
1a4de8
index 738aa203ec..d3bb8d7fe7 100644
1a4de8
--- a/lib/dns/rbtdb.c
1a4de8
+++ b/lib/dns/rbtdb.c
1a4de8
@@ -1972,6 +1972,9 @@ clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
1a4de8
 		node->dirty = 0;
1a4de8
 }
1a4de8
 
1a4de8
+/*
1a4de8
+ * tree_lock(write) must be held.
1a4de8
+ */
1a4de8
 static void
1a4de8
 delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
1a4de8
 	dns_rbtnode_t *nsecnode;
1a4de8
@@ -2955,6 +2958,8 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
1a4de8
  * E.g. if the wildcard name is "*.sub.example." then we
1a4de8
  * must ensure that "sub.example." exists and is marked as
1a4de8
  * a wildcard level.
1a4de8
+ *
1a4de8
+ * tree_lock(write) must be held.
1a4de8
  */
1a4de8
 static isc_result_t
1a4de8
 add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
1a4de8
@@ -2979,6 +2984,9 @@ add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
1a4de8
 	return (ISC_R_SUCCESS);
1a4de8
 }
1a4de8
 
1a4de8
+/*
1a4de8
+ * tree_lock(write) must be held.
1a4de8
+ */
1a4de8
 static isc_result_t
1a4de8
 add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
1a4de8
 	isc_result_t result;
1a4de8
@@ -6756,13 +6764,16 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1a4de8
 	REQUIRE(VALID_RBTDB(rbtdb));
1a4de8
 	INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb);
1a4de8
 
1a4de8
-	if (rbtdb->common.methods == &zone_methods)
1a4de8
+	if (rbtdb->common.methods == &zone_methods) {
1a4de8
+		RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
 		REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 &&
1a4de8
 			  (rdataset->type == dns_rdatatype_nsec3 ||
1a4de8
 			   rdataset->covers == dns_rdatatype_nsec3)) ||
1a4de8
 			 (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 &&
1a4de8
 			   rdataset->type != dns_rdatatype_nsec3 &&
1a4de8
 			   rdataset->covers != dns_rdatatype_nsec3)));
1a4de8
+		RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
+	}
1a4de8
 
1a4de8
 	if (rbtversion == NULL) {
1a4de8
 		if (now == 0)
1a4de8
@@ -6854,11 +6865,15 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1a4de8
 	/*
1a4de8
 	 * Add to the auxiliary NSEC tree if we're adding an NSEC record.
1a4de8
 	 */
1a4de8
+	RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
 	if (rbtnode->nsec != DNS_RBT_NSEC_HAS_NSEC &&
1a4de8
 	    rdataset->type == dns_rdatatype_nsec)
1a4de8
+	{
1a4de8
 		newnsec = true;
1a4de8
-	else
1a4de8
+	} else {
1a4de8
 		newnsec = false;
1a4de8
+	}
1a4de8
+	RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
 
1a4de8
 	/*
1a4de8
 	 * If we're adding a delegation type, adding to the auxiliary NSEC tree,
1a4de8
@@ -6959,13 +6974,16 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1a4de8
 	REQUIRE(VALID_RBTDB(rbtdb));
1a4de8
 	REQUIRE(rbtversion != NULL && rbtversion->rbtdb == rbtdb);
1a4de8
 
1a4de8
-	if (rbtdb->common.methods == &zone_methods)
1a4de8
+	if (rbtdb->common.methods == &zone_methods) {
1a4de8
+		RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
 		REQUIRE(((rbtnode->nsec == DNS_RBT_NSEC_NSEC3 &&
1a4de8
 			  (rdataset->type == dns_rdatatype_nsec3 ||
1a4de8
 			   rdataset->covers == dns_rdatatype_nsec3)) ||
1a4de8
 			 (rbtnode->nsec != DNS_RBT_NSEC_NSEC3 &&
1a4de8
 			   rdataset->type != dns_rdatatype_nsec3 &&
1a4de8
 			   rdataset->covers != dns_rdatatype_nsec3)));
1a4de8
+		RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
1a4de8
+	}
1a4de8
 
1a4de8
 	result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
1a4de8
 					    &region, sizeof(rdatasetheader_t));
1a4de8
-- 
1a4de8
2.21.0
1a4de8