]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
netmgr: fix a non-thread-safe access to libuv structures
authorWitold Kręcicki <wpk@isc.org>
Thu, 16 Jan 2020 11:13:28 +0000 (12:13 +0100)
committerWitold Kręcicki <wpk@isc.org>
Mon, 20 Jan 2020 21:28:36 +0000 (22:28 +0100)
In tcp and udp stoplistening code we accessed libuv structures
from a different thread, which caused a shutdown crash when named
was under load. Also added additional DbC checks making sure we're
in a proper thread when accessing uv_ functions.

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/tcp.c
lib/isc/netmgr/udp.c

index f309ab5131827473fae41b7dba758d30cabf9452..7dfa8872e64ef4a1c8585974d9d4fba2bc047911 100644 (file)
@@ -606,8 +606,8 @@ isc__nmsocket_prep_destroy(isc_nmsocket_t *sock);
 bool
 isc__nmsocket_active(isc_nmsocket_t *sock);
 /*%<
- * Check is socket 'sock' is active - by checking either sock->active or
- * sock->parent->active;
+ * Determine whether 'sock' is active by checking 'sock->active'
+ * or, for child sockets, 'sock->parent->active'.
  */
 
 void
index 17a97cda3837b602b43e9bdc4f3ba8ff0509bbb7..e0c566e176cbffc5a9caea2c30a21adb04ab1b53 100644 (file)
@@ -419,7 +419,7 @@ stoplistening(isc_nmsocket_t *sock) {
                event = isc__nm_get_ievent(sock->mgr, netievent_tcpchildstop);
                isc_nmsocket_attach(&sock->children[i], &event->sock);
 
-               if (i == sock->tid) {
+               if (isc_nm_tid() == sock->children[i].tid) {
                        isc__nm_async_tcpchildstop(&sock->mgr->workers[i],
                                                   (isc__netievent_t *) event);
                        isc__nm_put_ievent(sock->mgr, event);
index 0bad9ceaf5d6fbf374370622f7d2b8c925fa2e0c..936fa963d9c82d5af1418589a8ac81f0769e4b69 100644 (file)
@@ -122,6 +122,7 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        REQUIRE(sock->type == isc_nm_udpsocket);
        REQUIRE(sock->iface != NULL);
        REQUIRE(sock->parent != NULL);
+       REQUIRE(sock->tid == isc_nm_tid());
 
        uv_udp_init(&worker->loop, &sock->uv_handle.udp);
        uv_handle_set_data(&sock->uv_handle.handle, NULL);
@@ -164,7 +165,8 @@ udp_close_cb(uv_handle_t *handle) {
 
 static void
 stop_udp_child(isc_nmsocket_t *sock) {
-       INSIST(sock->type == isc_nm_udpsocket);
+       REQUIRE(sock->type == isc_nm_udpsocket);
+       REQUIRE(sock->tid == isc_nm_tid());
 
        uv_udp_recv_stop(&sock->uv_handle.udp);
        uv_close((uv_handle_t *) &sock->uv_handle.udp, udp_close_cb);
@@ -179,13 +181,15 @@ stop_udp_child(isc_nmsocket_t *sock) {
 
 static void
 stoplistening(isc_nmsocket_t *sock) {
-       INSIST(sock->type == isc_nm_udplistener);
+       REQUIRE(sock->type == isc_nm_udplistener);
+
        /*
         * Socket is already closing; there's nothing to do.
         */
        if (!isc__nmsocket_active(sock)) {
                return;
        }
+
        /*
         * Mark it inactive now so that all sends will be ignored
         * and we won't try to stop listening again.
@@ -195,7 +199,7 @@ stoplistening(isc_nmsocket_t *sock) {
        for (int i = 0; i < sock->nchildren; i++) {
                isc__netievent_udpstop_t *event = NULL;
 
-               if (i == sock->tid) {
+               if (isc_nm_tid() == sock->children[i].tid) {
                        stop_udp_child(&sock->children[i]);
                        continue;
                }