From fc678b19d9ff2ed1557aa62be2a323970a0f85c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= Date: Mon, 27 Dec 2021 15:41:04 +0100 Subject: [PATCH] Fix rare control channel socket reference leak Commit 9ee60e7a17bf34c7ef7f4d79e6a00ca45444ec8c enabled netmgr shutdown to cause read callbacks for active control channel sockets to be invoked with the ISC_R_SHUTTINGDOWN result code. However, control channel code only recognizes ISC_R_CANCELED as an indicator of an in-progress netmgr shutdown (which was correct before the above commit). This discrepancy enables the following scenario to happen in rare cases: 1. A control channel request is received and responded to. libuv manages to write the response to the TCP socket, but the completion callback (control_senddone()) is yet to be invoked. 2. Server shutdown is initiated. All TCP sockets are shut down, which i.a. causes control_recvmessage() to be invoked with the ISC_R_SHUTTINGDOWN result code. As the result code is not ISC_R_CANCELED, control_recvmessage() does not set listener->controls->shuttingdown to 'true'. 3. control_senddone() is called with the ISC_R_SUCCESS result code. As neither listener->controls->shuttingdown is 'true' nor is the result code ISC_R_CANCELED, reading is resumed on the control channel socket. However, this read can never be completed because the read callback on that socket was cleared when the TCP socket was shut down. This causes a reference on the socket's handle to be held indefinitely, leading to a hang upon shutdown. Ensure listener->controls->shuttingdown is also set to 'true' when control_recvmessage() is invoked with the ISC_R_SHUTTINGDOWN result code. This ensures the send completion callback does not resume reading after the control channel socket is shut down. --- bin/named/controlconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c index 63c4d272e4..7f50e4b03d 100644 --- a/bin/named/controlconf.c +++ b/bin/named/controlconf.c @@ -412,7 +412,7 @@ control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) { } if (result != ISC_R_SUCCESS) { - if (result == ISC_R_CANCELED) { + if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) { atomic_store_release(&listener->controls->shuttingdown, true); } else if (result != ISC_R_EOF) {