diff options
author | Ralph Boehme <slow@samba.org> | 2018-08-29 17:19:29 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2018-09-05 13:35:27 +0200 |
commit | b7c659a4499dc7b62423ce930f7ce2128eded90e (patch) | |
tree | 29e2cfe15c0269c52651ca81510d2f36adc45d03 /source3/smbd | |
parent | 51253045e827c14b14d527d1c48d037d8002588f (diff) | |
download | samba-b7c659a4499dc7b62423ce930f7ce2128eded90e.tar.gz |
s3:smbd: let session logoff close files and tcons before deleting the session
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>
(cherry picked from commit 8f6edcc1645e0ed35eaec914bd0b672500ce986c)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/smbXsrv_session.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index f84d2a94ce1..7fe385c2047 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1651,6 +1651,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) { @@ -1710,29 +1733,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; } |