]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Don't continue opening a new rndc connection if we are shutting down
authorOndřej Surý <ondrej@isc.org>
Tue, 23 Jun 2020 11:02:21 +0000 (13:02 +0200)
committerOndřej Surý <ondrej@isc.org>
Wed, 1 Jul 2020 10:52:51 +0000 (12:52 +0200)
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.

(cherry picked from commit be6cc53ec27e4549bf166d2161bacce688151e79)

bin/named/controlconf.c

index 4c0127b7a69cbdccdf0472ef9a7e7e190896d202..26f80423f2933e79c04038c0669731a707017477 100644 (file)
@@ -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)) {