From 674a21946613ac624e22482ac8c66000fcc00792 Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Wed, 26 Aug 2020 15:50:53 +1000
Subject: [PATCH] Address data race in dns_adbentry_overquota

  Read of size 4 at 0x7b440003da70 by thread T8:
    #0 dns_adbentry_overquota /builds/isc-projects/bind9/lib/dns/adb.c:4797:39 (libdns.so.1110+0x4da82)
    #1 fctx_try /builds/isc-projects/bind9/lib/dns/resolver.c:3838:10 (libdns.so.1110+0x17e229)
    #2 fctx_start /builds/isc-projects/bind9/lib/dns/resolver.c:4219:4 (libdns.so.1110+0x1787a3)
    #3 dispatch /builds/isc-projects/bind9/lib/isc/task.c:1157:7 (libisc.so.1107+0x507f5)
    #4 run /builds/isc-projects/bind9/lib/isc/task.c:1331:2 (libisc.so.1107+0x4d749)

  Previous write of size 4 at 0x7b440003da70 by thread T12 (mutexes: write M549293692588722840):
    #0 dns_adb_beginudpfetch /builds/isc-projects/bind9/lib/dns/adb.c:4811:21 (libdns.so.1110+0x4db82)
    #1 fctx_query /builds/isc-projects/bind9/lib/dns/resolver.c:1901:3 (libdns.so.1110+0x1814ee)
    #2 fctx_try /builds/isc-projects/bind9/lib/dns/resolver.c:3863:11 (libdns.so.1110+0x17e2fa)
    #3 fctx_start /builds/isc-projects/bind9/lib/dns/resolver.c:4219:4 (libdns.so.1110+0x1787a3)
    #4 dispatch /builds/isc-projects/bind9/lib/isc/task.c:1157:7 (libisc.so.1107+0x507f5)
    #5 run /builds/isc-projects/bind9/lib/isc/task.c:1331:2 (libisc.so.1107+0x4d749)
Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/674a21946613ac624e22482ac8c66000fcc00792
---
 lib/dns/adb.c             | 10 +++++++++-
 lib/dns/include/dns/adb.h |  2 +-
 lib/dns/resolver.c        |  6 +++---
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index 5021a17fba..d6f56fa6d3 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -4791,10 +4791,18 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq,
 }
 
 bool
-dns_adbentry_overquota(dns_adbentry_t *entry) {
+dns_adbentry_overquota(dns_adb_t *adb, dns_adbentry_t *entry) {
+	int bucket;
 	bool block;
+
 	REQUIRE(DNS_ADBENTRY_VALID(entry));
+
+	bucket = entry->lock_bucket;
+
+	LOCK(&adb->entrylocks[bucket]);
 	block = (entry->quota != 0 && entry->active >= entry->quota);
+	UNLOCK(&adb->entrylocks[bucket]);
+
 	return (block);
 }
 
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
index edf6e54935..9e328ef5ad 100644
--- a/lib/dns/include/dns/adb.h
+++ b/lib/dns/include/dns/adb.h
@@ -815,7 +815,7 @@ dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq,
  */
 
 bool
-dns_adbentry_overquota(dns_adbentry_t *entry);
+dns_adbentry_overquota(dns_adb_t *adb, dns_adbentry_t *entry);
 /*%<
  * Returns true if the specified ADB has too many active fetches.
  *
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index cf6c00100c..5984e00ab8 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -1894,7 +1894,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
 		query->connects++;
 		QTRACE("connecting via TCP");
 	} else {
-		if (dns_adbentry_overquota(addrinfo->entry))
+		if (dns_adbentry_overquota(fctx->adb, addrinfo->entry))
 			goto cleanup_dispatch;
 
 		/* Inform the ADB that we're starting a UDP fetch */
@@ -3809,7 +3809,7 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
 	addrinfo = fctx_nextaddress(fctx);
 
 	/* Try to find an address that isn't over quota */
-	while (addrinfo != NULL && dns_adbentry_overquota(addrinfo->entry))
+	while (addrinfo != NULL && dns_adbentry_overquota(fctx->adb, addrinfo->entry))
 		addrinfo = fctx_nextaddress(fctx);
 
 	if (addrinfo == NULL) {
@@ -3835,7 +3835,7 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
 		addrinfo = fctx_nextaddress(fctx);
 
 		while (addrinfo != NULL &&
-		       dns_adbentry_overquota(addrinfo->entry))
+		       dns_adbentry_overquota(fctx->adb, addrinfo->entry))
 			addrinfo = fctx_nextaddress(fctx);
 
 		/*
-- 
2.23.0

