From: Ondřej Surý Date: Tue, 23 Jun 2020 11:02:21 +0000 (+0200) Subject: Don't continue opening a new rndc connection if we are shutting down X-Git-Tag: v9.17.3~24^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be6cc53ec27e4549bf166d2161bacce688151e79;p=thirdparty%2Fbind9.git Don't continue opening a new rndc connection if we are shutting down Due to lack of synchronization, whenever named was being requested to stop using rndc, controlconf.c module could be trying to access an already released pointer through named_g_server->interfacemgr in a separate thread. The race could only be triggered if named was being shutdown and more rndc connections were ocurring at the same time. This fix correctly checks if the server is shutting down before opening a new rndc connection. --- diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c index a3fda486d3d..bab50ae8e07 100644 --- a/bin/named/controlconf.c +++ b/bin/named/controlconf.c @@ -226,6 +226,7 @@ shutdown_listener(controllistener_t *listener) { if (listener->listening) { isc_socket_cancel(listener->sock, listener->task, ISC_SOCKCANCEL_ACCEPT); + return; } maybe_free_listener(listener); @@ -636,6 +637,8 @@ control_newconn(isc_task_t *task, isc_event_t *event) { UNUSED(task); + REQUIRE(listener->listening); + listener->listening = false; if (nevent->result != ISC_R_SUCCESS) { @@ -647,6 +650,14 @@ control_newconn(isc_task_t *task, isc_event_t *event) { } sock = nevent->newsocket; + + /* Is the server shutting down? */ + if (listener->controls->shuttingdown) { + isc_socket_detach(&sock); + shutdown_listener(listener); + goto cleanup; + } + isc_socket_setname(sock, "control", NULL); (void)isc_socket_getpeername(sock, &peeraddr); if (listener->type == isc_sockettype_tcp && @@ -1121,36 +1132,33 @@ add_listener(named_controls_t *cp, controllistener_t **listenerp, listener = isc_mem_get(mctx, sizeof(*listener)); - if (result == ISC_R_SUCCESS) { - listener->mctx = NULL; - isc_mem_attach(mctx, &listener->mctx); - listener->controls = cp; - listener->task = cp->server->task; - listener->address = *addr; - listener->sock = NULL; - listener->listening = false; - listener->exiting = false; - listener->acl = NULL; - listener->type = type; - listener->perm = 0; - listener->owner = 0; - listener->group = 0; - listener->readonly = false; - ISC_LINK_INIT(listener, link); - ISC_LIST_INIT(listener->keys); - ISC_LIST_INIT(listener->connections); + listener->mctx = NULL; + isc_mem_attach(mctx, &listener->mctx); + listener->controls = cp; + listener->task = cp->server->task; + listener->address = *addr; + listener->sock = NULL; + listener->listening = false; + listener->exiting = false; + listener->acl = NULL; + listener->type = type; + listener->perm = 0; + listener->owner = 0; + listener->group = 0; + listener->readonly = false; + ISC_LINK_INIT(listener, link); + ISC_LIST_INIT(listener->keys); + ISC_LIST_INIT(listener->connections); - /* - * Make the acl. - */ - if (control != NULL && type == isc_sockettype_tcp) { - allow = cfg_tuple_get(control, "allow"); - result = cfg_acl_fromconfig(allow, config, named_g_lctx, - aclconfctx, mctx, 0, - &new_acl); - } else { - result = dns_acl_any(mctx, &new_acl); - } + /* + * Make the acl. + */ + if (control != NULL && type == isc_sockettype_tcp) { + allow = cfg_tuple_get(control, "allow"); + result = cfg_acl_fromconfig(allow, config, named_g_lctx, + aclconfctx, mctx, 0, &new_acl); + } else { + result = dns_acl_any(mctx, &new_acl); } if ((result == ISC_R_SUCCESS) && (control != NULL)) {