]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Fix use-after-free from exit_server_common()
authorVolker Lendecke <vl@samba.org>
Wed, 31 Jul 2019 12:17:02 +0000 (14:17 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 1 Aug 2019 15:39:12 +0000 (15:39 +0000)
We need to keep the smbXsrv_connection structures around until all
pending requests have had their chance to clean up behind them. If you
look at srv_send_smb(), it's exactly prepared already to just drop
anything on the floor when the transport has been declared dead:

if (!NT_STATUS_IS_OK(xconn->transport.status)) {
/*
 * we're not supposed to do any io
 */
return true;
}

Bug: https://bugzilla.samba.org/show_bug.cgi?id=14064

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Thu Aug  1 15:39:13 UTC 2019 on sn-devel-184

source3/smbd/server_exit.c

index ba5e6c7ff1e09af04f286373d2e4499abc767c74..d51b73d5131db2aeca746a1057f5509a3699f904 100644 (file)
@@ -93,7 +93,6 @@ static void exit_server_common(enum server_exit_reason how,
 {
        struct smbXsrv_client *client = global_smbXsrv_client;
        struct smbXsrv_connection *xconn = NULL;
-       struct smbXsrv_connection *xconn_next = NULL;
        struct smbd_server_connection *sconn = NULL;
        struct messaging_context *msg_ctx = global_messaging_context();
 
@@ -112,10 +111,7 @@ static void exit_server_common(enum server_exit_reason how,
        /*
         * Here we typically have just one connection
         */
-       for (; xconn != NULL; xconn = xconn_next) {
-               xconn_next = xconn->next;
-               DLIST_REMOVE(client->connections, xconn);
-
+       for (; xconn != NULL; xconn = xconn->next) {
                /*
                 * This is typically the disconnect for the only
                 * (or with multi-channel last) connection of the client
@@ -130,8 +126,6 @@ static void exit_server_common(enum server_exit_reason how,
                                break;
                        }
                }
-
-               TALLOC_FREE(xconn);
                DO_PROFILE_INC(disconnect);
        }
 
@@ -174,6 +168,20 @@ static void exit_server_common(enum server_exit_reason how,
 
        change_to_root_user();
 
+       if (client != NULL) {
+               struct smbXsrv_connection *xconn_next = NULL;
+
+               for (xconn = client->connections;
+                    xconn != NULL;
+                    xconn = xconn_next) {
+                       xconn_next = xconn->next;
+                       DLIST_REMOVE(client->connections, xconn);
+                       TALLOC_FREE(xconn);
+               }
+       }
+
+       change_to_root_user();
+
        /* 3 second timeout. */
        print_notify_send_messages(msg_ctx, 3);