]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
netmgr: handle errors properly in accept_connection.
authorWitold Krecicki <wpk@isc.org>
Tue, 14 Jan 2020 10:00:41 +0000 (11:00 +0100)
committerWitold Krecicki <wpk@isc.org>
Tue, 14 Jan 2020 10:03:06 +0000 (11:03 +0100)
If a connection was closed early (right after accept()) an assertion
that assumed that the connection was still alive could be triggered
in accept_connection. Handle those errors properly and not with
assertions, free all the resources afterwards.

lib/isc/netmgr/tcp.c

index c4dd1a31e885c850b6c1dd4bd4958662dbf1093c..b884772e7b260fbdacd46c00dd7cf6939f19c8f3 100644 (file)
@@ -709,27 +709,36 @@ accept_connection(isc_nmsocket_t *ssock) {
 
        r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream);
        if (r != 0) {
-               if (csock->quota != NULL) {
-                       isc_quota_detach(&csock->quota);
-               }
-               isc_mem_put(ssock->mgr->mctx, csock, sizeof(isc_nmsocket_t));
-
-               return (isc__nm_uverr2result(r));
+               result = isc__nm_uverr2result(r);
+               goto error;
        }
 
-       isc_nmsocket_attach(ssock, &csock->server);
-
-       uv_tcp_getpeername(&csock->uv_handle.tcp, (struct sockaddr *) &ss,
-                          &(int){sizeof(ss)});
+       r = uv_tcp_getpeername(&csock->uv_handle.tcp, (struct sockaddr *) &ss,
+                              &(int){sizeof(ss)});
+       if (r != 0) {
+               result = isc__nm_uverr2result(r);
+               goto error;
+       }
 
        result = isc_sockaddr_fromsockaddr(&csock->peer,
                                           (struct sockaddr *) &ss);
-       RUNTIME_CHECK(result == ISC_R_SUCCESS);
-       uv_tcp_getsockname(&csock->uv_handle.tcp, (struct sockaddr *) &ss,
-                          &(int){sizeof(ss)});
+       if (result != ISC_R_SUCCESS) {
+               goto error;
+       }
+
+       r = uv_tcp_getsockname(&csock->uv_handle.tcp, (struct sockaddr *) &ss,
+                              &(int){sizeof(ss)});
+       if (r != 0) {
+               result = isc__nm_uverr2result(r);
+               goto error;
+       }
        result = isc_sockaddr_fromsockaddr(&local,
                                           (struct sockaddr *) &ss);
-       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+       if (result != ISC_R_SUCCESS) {
+               goto error;
+       }
+
+       isc_nmsocket_attach(ssock, &csock->server);
 
        handle = isc__nmhandle_get(csock, NULL, &local);
 
@@ -739,6 +748,18 @@ accept_connection(isc_nmsocket_t *ssock) {
        isc_nmsocket_detach(&csock);
 
        return (ISC_R_SUCCESS);
+
+error:
+       /*
+        * Detach it early to make room for other connections, otherwise
+        * it'd be detached later asynchronously clogging the quota.
+        */
+       if (csock->quota != NULL) {
+               isc_quota_detach(&csock->quota);
+       }
+       /* We need to detach it properly to make sure uv_close is called. */
+       isc_nmsocket_detach(&csock);
+       return (result);
 }
 
 static void
@@ -906,7 +927,9 @@ tcp_close_direct(isc_nmsocket_t *sock) {
                uv_timer_stop(&sock->timer);
                uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
        } else {
-               isc_nmsocket_detach(&sock->server);
+               if (sock->server != NULL) {
+                       isc_nmsocket_detach(&sock->server);
+               }
                uv_close(&sock->uv_handle.handle, tcp_close_cb);
        }
 }