]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a race between socket closing and incoming event.
authorWitold Kręcicki <wpk@isc.org>
Wed, 3 Oct 2018 20:39:39 +0000 (20:39 +0000)
committerWitold Kręcicki <wpk@isc.org>
Tue, 6 Nov 2018 11:25:09 +0000 (11:25 +0000)
lib/isc/unix/socket.c

index 1b06919ed165fb8767a7f8a04ce37146d93f2433..8cda44f583c684f7cbe6e9a0d8b1dae71eaa0832 100644 (file)
@@ -2701,6 +2701,7 @@ isc_socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) {
        REQUIRE(socketp != NULL && *socketp == NULL);
 
        LOCK(&sock->lock);
+       REQUIRE(sock->references > 0);
        sock->references++;
        UNLOCK(&sock->lock);
 
@@ -2744,7 +2745,6 @@ isc_socket_close(isc_socket_t *sock0) {
 
        LOCK(&sock->lock);
 
-       REQUIRE(sock->references == 1);
        REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
 
        INSIST(!sock->connecting);
@@ -3235,32 +3235,29 @@ process_fd(isc__socketthread_t *thread, int fd, bool readable,
                unwatch_write = writeable;
                goto unlock_fd;
        }
+       if (SOCK_DEAD(sock)) { /* Sock is being closed, bail */
+               UNLOCK(&sock->lock);
+               UNLOCK(&thread->fdlock[lockid]);
+               return;
+       }
 
        LOCK(&sock->lock);
        sock->references++;
        UNLOCK(&sock->lock);
 
        if (readable) {
-               if (!SOCK_DEAD(sock)) {
-                       if (sock->listener)
-                               internal_accept(sock);
-                       else
-                               internal_recv(sock);
-               }
+               if (sock->listener)
+                       internal_accept(sock);
+               else
+                       internal_recv(sock);
                unwatch_read = true;
        }
 
        if (writeable) {
-               if (sock == NULL) {
-                       unwatch_write = true;
-                       goto unlock_fd;
-               }
-               if (!SOCK_DEAD(sock)) {
-                       if (sock->connecting)
-                               internal_connect(sock);
-                       else
-                               internal_send(sock);
-               }
+               if (sock->connecting)
+                       internal_connect(sock);
+               else
+                       internal_send(sock);
                unwatch_write = true;
        }