From: Witold Kręcicki Date: Wed, 13 Feb 2019 10:10:31 +0000 (+0100) Subject: Fix a race in fctx_cancelquery. X-Git-Tag: v9.15.0~97^2~1 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=56183a39173264854dbd3abe8d6b580a0058579e;p=thirdparty%2Fbind9.git Fix a race in fctx_cancelquery. 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. --- diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 86dad48ebc9..184cba1036e 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -1321,7 +1321,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. */