s3:smbd: let session logoff close files and tcons before deleting the session
authorRalph Boehme <slow@samba.org>
Wed, 29 Aug 2018 15:19:29 +0000 (17:19 +0200)
committerJeremy Allison <jra@samba.org>
Fri, 31 Aug 2018 20:22:23 +0000 (22:22 +0200)
This avoids a race in durable handle reconnects if the reconnect comes
in while the old session is still in the tear-down phase.

The new session is supposed to rendezvous with and wait for destruction
of the old session, which is internally implemented with
dbwrap_watch_send() on the old session record.

If the old session deletes the session record before calling
file_close_user() which marks all file handles as disconnected, the
durable handle reconnect in the new session will fail as the records are
not yet marked as disconnected which is a prerequisite.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/samba3.blackbox [deleted file]
source3/smbd/smbXsrv_session.c

diff --git a/selftest/knownfail.d/samba3.blackbox b/selftest/knownfail.d/samba3.blackbox
deleted file mode 100644 (file)
index b03a1ac..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.blackbox.durable_v2_delay.durable_v2_delay\(simpleserver:local\)
index af47f4aa8c3c17a832cae8a4092a2e8d797353e6..1193b4a3bea2dd800d18db2034187b2a0ef1761a 100644 (file)
@@ -1663,6 +1663,29 @@ NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
        session->client = NULL;
        session->status = NT_STATUS_USER_SESSION_DELETED;
 
+       if (session->compat) {
+               file_close_user(sconn, session->compat->vuid);
+       }
+
+       if (session->tcon_table != NULL) {
+               /*
+                * Note: We only have a tcon_table for SMB2.
+                */
+               status = smb2srv_tcon_disconnect_all(session);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
+                                 "smb2srv_tcon_disconnect_all() failed: %s\n",
+                                 session->global->session_global_id,
+                                 nt_errstr(status)));
+                       error = status;
+               }
+       }
+
+       if (session->compat) {
+               invalidate_vuid(sconn, session->compat->vuid);
+               session->compat = NULL;
+       }
+
        global_rec = session->global->db_rec;
        session->global->db_rec = NULL;
        if (global_rec == NULL) {
@@ -1722,29 +1745,6 @@ NTSTATUS smbXsrv_session_logoff(struct smbXsrv_session *session)
        }
        session->db_rec = NULL;
 
-       if (session->compat) {
-               file_close_user(sconn, session->compat->vuid);
-       }
-
-       if (session->tcon_table != NULL) {
-               /*
-                * Note: We only have a tcon_table for SMB2.
-                */
-               status = smb2srv_tcon_disconnect_all(session);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0, ("smbXsrv_session_logoff(0x%08x): "
-                                 "smb2srv_tcon_disconnect_all() failed: %s\n",
-                                 session->global->session_global_id,
-                                 nt_errstr(status)));
-                       error = status;
-               }
-       }
-
-       if (session->compat) {
-               invalidate_vuid(sconn, session->compat->vuid);
-               session->compat = NULL;
-       }
-
        return error;
 }