From 16e7e2732879ab53d3620705807f5cbd0aace43e Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Fri, 21 Aug 2020 15:50:57 +1000
Subject: [PATCH] Address data races between socket bitfields

* address data race between sock->pending_recv and sock->connected
* address data race between sock->bound and sock->pending_recv

==================
WARNING: ThreadSanitizer: data race (pid=1985)
  Read of size 2 at 0x7b54000c07c0 by thread T6:
    #0 isc__socket_sendto /builds/isc-projects/bind9/lib/isc/unix/socket.c:5291:2 (libisc.so.1107+0x65a00)
    #1 isc__socket_send /builds/isc-projects/bind9/lib/isc/unix/socket.c:5270:10 (libisc.so.1107+0x65944)
    #2 isc_socket_send /builds/isc-projects/bind9/lib/isc/unix/./../socket_api.c:329:10 (libisc.so.1107+0x6b3c9)
    #3 sendstream /builds/isc-projects/bind9/bin/named/xfrout.c:1548:3 (named+0x555038)
    #4 ns_xfr_start /builds/isc-projects/bind9/bin/named/xfrout.c:1132:2 (named+0x553147)
    #5 ns_query_start /builds/isc-projects/bind9/bin/named/query.c:9572:4 (named+0x4f3329)
    #6 client_request /builds/isc-projects/bind9/bin/named/client.c:3115:3 (named+0x4de6af)
    #7 dispatch /builds/isc-projects/bind9/lib/isc/task.c:1157:7 (libisc.so.1107+0x50845)
    #8 run /builds/isc-projects/bind9/lib/isc/task.c:1331:2 (libisc.so.1107+0x4d799)

  Previous write of size 2 at 0x7b54000c07c0 by thread T14 (mutexes: write M57, write M855819529908651432):
    #0 dispatch_recv /builds/isc-projects/bind9/lib/isc/unix/socket.c:3353:21 (libisc.so.1107+0x6c601)
    #1 process_fd /builds/isc-projects/bind9/lib/isc/unix/socket.c:4048:5 (libisc.so.1107+0x6c1be)
    #2 process_fds /builds/isc-projects/bind9/lib/isc/unix/socket.c:4161:3 (libisc.so.1107+0x6bfc0)
    #3 watcher /builds/isc-projects/bind9/lib/isc/unix/socket.c:4407:10 (libisc.so.1107+0x64398)
Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/16e7e2732879ab53d3620705807f5cbd0aace43e
---
 lib/isc/unix/socket.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index 2b034d1762..0ebdf4c345 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -5175,7 +5175,6 @@ socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 	    unsigned int flags)
 {
 	int io_state;
-	bool have_lock = false;
 	isc_task_t *ntask = NULL;
 	isc_result_t result = ISC_R_SUCCESS;
 
@@ -5201,12 +5200,10 @@ socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 		}
 	}
 
-	if (sock->type == isc_sockettype_udp)
+	LOCK(&sock->lock);
+	if (sock->type == isc_sockettype_udp) {
 		io_state = doio_send(sock, dev);
-	else {
-		LOCK(&sock->lock);
-		have_lock = true;
-
+	} else {
 		if (ISC_LIST_EMPTY(sock->send_list))
 			io_state = doio_send(sock, dev);
 		else
@@ -5223,11 +5220,6 @@ socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 			isc_task_attach(task, &ntask);
 			dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
 
-			if (!have_lock) {
-				LOCK(&sock->lock);
-				have_lock = true;
-			}
-
 			/*
 			 * Enqueue the request.  If the socket was previously
 			 * not being watched, poke the watcher to start
@@ -5257,8 +5249,7 @@ socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 		break;
 	}
 
-	if (have_lock)
-		UNLOCK(&sock->lock);
+	UNLOCK(&sock->lock);
 
 	return (result);
 }
@@ -5291,7 +5282,9 @@ isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region,
 	manager = sock->manager;
 	REQUIRE(VALID_MANAGER(manager));
 
+	LOCK(&sock->lock);
 	INSIST(sock->bound);
+	UNLOCK(&sock->lock);
 
 	dev = allocate_socketevent(manager->mctx, sock,
 				   ISC_SOCKEVENT_SENDDONE, action, arg);
-- 
2.23.0

