]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a race in fctx_cancelquery.
authorWitold Kręcicki <wpk@culm.net>
Wed, 13 Feb 2019 10:10:31 +0000 (11:10 +0100)
committerEvan Hunt <each@isc.org>
Tue, 12 Mar 2019 19:59:02 +0000 (12:59 -0700)
When sending an udp query (resquery_send) we first issue an asynchronous
isc_socket_connect and increment query->connects, then isc_socket_sendto2
and increment query->sends.
If we happen to cancel this query (fctx_cancelquery) we need to cancel
all operations we might have issued on this socket. If we are under very high
load the callback from isc_socket_connect (resquery_udpconnected) might have
not yet been fired. In this case we only cancel the CONNECT event on socket,
and ignore the SEND that's waiting there (as there is an `else if`).
Then we call dns_dispatch_removeresponse which kills the dispatcher socket
and calls isc_socket_close - but if system is under very high load, the send
we issued earlier might still not be complete - which triggers an assertion
because we're trying to close a socket that's still in use.

The fix is to always check if we have incomplete sends on the socket and cancel
them if we do.

(cherry picked from commit 56183a39173264854dbd3abe8d6b580a0058579e)

lib/dns/resolver.c

index 03b8248fdddc34f51c1a7f1bc6b483ea4f2ed04d..2a6e69c5a68764a2af9169099a0aa132c24a5ab4 100644 (file)
@@ -1323,7 +1323,8 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
                                isc_socket_cancel(sock, NULL,
                                                  ISC_SOCKCANCEL_CONNECT);
                }
-       } else if (RESQUERY_SENDING(query)) {
+       }
+       if (RESQUERY_SENDING(query)) {
                /*
                 * Cancel the pending send.
                 */