smbd: make sure that xconn is alive for the lifetime of smbXsrv_connection_shutdown_s...
authorStefan Metzmacher <metze@samba.org>
Wed, 23 Sep 2020 11:07:20 +0000 (13:07 +0200)
committerJeremy Allison <jra@samba.org>
Sat, 6 Mar 2021 02:20:05 +0000 (02:20 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14533

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/smb2.lease.timeout-disconnect [deleted file]
source3/smbd/globals.h
source3/smbd/smb2_server.c

diff --git a/selftest/knownfail.d/smb2.lease.timeout-disconnect b/selftest/knownfail.d/smb2.lease.timeout-disconnect
deleted file mode 100644 (file)
index a277ef4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.smb2.lease.timeout-disconnect
index 4685b6971d313059b1e15adc0a241c4caa8f7297..dd3d58f8509c1c9b7a5d0dfcd44cf19a6d94cbbe 100644 (file)
@@ -367,6 +367,7 @@ struct smbXsrv_connection {
 
        struct {
                NTSTATUS status;
+               bool terminating;
                int sock;
                struct tevent_fd *fde;
 
index 1322cf3ba0831d6ad005d9a143c9a8efc5cf14a3..bd0eab00606634231d689d5393b0ff665c7b357c 100644 (file)
@@ -1500,6 +1500,7 @@ size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client)
 
 struct smbXsrv_connection_shutdown_state {
        struct tevent_queue *wait_queue;
+       struct smbXsrv_connection *xconn;
 };
 
 static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq);
@@ -1520,6 +1521,7 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
         * smbXsrv_connection_disconnect_transport() before.
         */
        SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status));
+       SMB_ASSERT(xconn->transport.terminating);
 
        req = tevent_req_create(mem_ctx, &state,
                                struct smbXsrv_connection_shutdown_state);
@@ -1527,6 +1529,9 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
+       state->xconn = xconn;
+       tevent_req_defer_callback(req, ev);
+
        status = smbXsrv_session_disconnect_xconn(xconn);
        if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
@@ -1590,15 +1595,33 @@ static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq)
        struct tevent_req *req =
                tevent_req_callback_data(subreq,
                struct tevent_req);
+       struct smbXsrv_connection_shutdown_state *state =
+               tevent_req_data(req,
+               struct smbXsrv_connection_shutdown_state);
+       struct smbXsrv_connection *xconn = state->xconn;
 
        tevent_queue_wait_recv(subreq);
        TALLOC_FREE(subreq);
 
        tevent_req_done(req);
+       /*
+        * make sure the xconn pointer is still valid,
+        * it should as we used tevent_req_defer_callback()
+        */
+       SMB_ASSERT(xconn->transport.terminating);
 }
 
 static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req)
 {
+       struct smbXsrv_connection_shutdown_state *state =
+               tevent_req_data(req,
+               struct smbXsrv_connection_shutdown_state);
+       struct smbXsrv_connection *xconn = state->xconn;
+       /*
+        * make sure the xconn pointer is still valid,
+        * it should as we used tevent_req_defer_callback()
+        */
+       SMB_ASSERT(xconn->transport.terminating);
        return tevent_req_simple_recv_ntstatus(req);
 }
 
@@ -1637,6 +1660,14 @@ void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn,
 
        num_ok = smbXsrv_client_valid_connections(client);
 
+       if (xconn->transport.terminating) {
+               DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n",
+                         smbXsrv_connection_dbg(xconn), num_ok,
+                         reason, location);
+               return;
+       }
+       xconn->transport.terminating = true;
+
        DBG_DEBUG("conn[%s] num_ok[%zu] reason[%s] at %s\n",
                  smbXsrv_connection_dbg(xconn), num_ok,
                  reason, location);