|
Jiri Slaby |
ba7816 |
From: Shyam Prasad N <sprasad@microsoft.com>
|
|
Jiri Slaby |
ba7816 |
Date: Mon, 20 Mar 2023 06:08:19 +0000
|
|
Jiri Slaby |
ba7816 |
Subject: [PATCH] cifs: avoid race conditions with parallel reconnects
|
|
Jiri Slaby |
ba7816 |
References: bsc#1012628
|
|
Jiri Slaby |
ba7816 |
Patch-mainline: 6.2.10
|
|
Jiri Slaby |
ba7816 |
Git-commit: bc962159e8e326af634a506508034a375bf2b858
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
[ Upstream commit bc962159e8e326af634a506508034a375bf2b858 ]
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
When multiple processes/channels do reconnects in parallel
|
|
Jiri Slaby |
ba7816 |
we used to return success immediately
|
|
Jiri Slaby |
ba7816 |
negotiate/session-setup/tree-connect, causing race conditions
|
|
Jiri Slaby |
ba7816 |
between processes that enter the function in parallel.
|
|
Jiri Slaby |
ba7816 |
This caused several errors related to session not found to
|
|
Jiri Slaby |
ba7816 |
show up during parallel reconnects.
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
|
|
Jiri Slaby |
ba7816 |
Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
|
|
Jiri Slaby |
ba7816 |
Cc: stable@vger.kernel.org
|
|
Jiri Slaby |
ba7816 |
Signed-off-by: Steve French <stfrench@microsoft.com>
|
|
Jiri Slaby |
ba7816 |
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
|
Jiri Slaby |
ba7816 |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
ba7816 |
---
|
|
Jiri Slaby |
ba7816 |
fs/cifs/connect.c | 48 ++++++++++++++++++++++++++++++-----------
|
|
Jiri Slaby |
ba7816 |
fs/cifs/smb2pdu.c | 44 +++++++++++++++++++++----------------
|
|
Jiri Slaby |
ba7816 |
fs/cifs/smb2transport.c | 17 ++++++++++++---
|
|
Jiri Slaby |
ba7816 |
3 files changed, 76 insertions(+), 33 deletions(-)
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
|
Jiri Slaby |
ba7816 |
index f53837f4..985e962c 100644
|
|
Jiri Slaby |
ba7816 |
--- a/fs/cifs/connect.c
|
|
Jiri Slaby |
ba7816 |
+++ b/fs/cifs/connect.c
|
|
Jiri Slaby |
ba7816 |
@@ -244,31 +244,42 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
|
|
Jiri Slaby |
ba7816 |
cifs_chan_update_iface(ses, server);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server))
|
|
Jiri Slaby |
ba7816 |
- goto next_session;
|
|
Jiri Slaby |
ba7816 |
+ if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ continue;
|
|
Jiri Slaby |
ba7816 |
+ }
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
if (mark_smb_session)
|
|
Jiri Slaby |
ba7816 |
CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
else
|
|
Jiri Slaby |
ba7816 |
cifs_chan_set_need_reconnect(ses, server);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+ cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
|
|
Jiri Slaby |
ba7816 |
+ __func__, ses->chans_need_reconnect);
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
/* If all channels need reconnect, then tcon needs reconnect */
|
|
Jiri Slaby |
ba7816 |
- if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses))
|
|
Jiri Slaby |
ba7816 |
- goto next_session;
|
|
Jiri Slaby |
ba7816 |
+ if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ continue;
|
|
Jiri Slaby |
ba7816 |
+ }
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
ses->ses_status = SES_NEED_RECON;
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
|
|
Jiri Slaby |
ba7816 |
tcon->need_reconnect = true;
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&tcon->tc_lock);
|
|
Jiri Slaby |
ba7816 |
tcon->status = TID_NEED_RECON;
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&tcon->tc_lock);
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
if (ses->tcon_ipc) {
|
|
Jiri Slaby |
ba7816 |
ses->tcon_ipc->need_reconnect = true;
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->tcon_ipc->tc_lock);
|
|
Jiri Slaby |
ba7816 |
ses->tcon_ipc->status = TID_NEED_RECON;
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->tcon_ipc->tc_lock);
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
-
|
|
Jiri Slaby |
ba7816 |
-next_session:
|
|
Jiri Slaby |
ba7816 |
- spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&cifs_tcp_ses_lock);
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
@@ -3703,11 +3714,19 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/* only send once per connect */
|
|
Jiri Slaby |
ba7816 |
spin_lock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
- if (!server->ops->need_neg(server) ||
|
|
Jiri Slaby |
ba7816 |
+ if (server->tcpStatus != CifsGood &&
|
|
Jiri Slaby |
ba7816 |
+ server->tcpStatus != CifsNew &&
|
|
Jiri Slaby |
ba7816 |
server->tcpStatus != CifsNeedNegotiate) {
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
+ return -EHOSTDOWN;
|
|
Jiri Slaby |
ba7816 |
+ }
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
+ if (!server->ops->need_neg(server) &&
|
|
Jiri Slaby |
ba7816 |
+ server->tcpStatus == CifsGood) {
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
return 0;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
server->tcpStatus = CifsInNegotiate;
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
@@ -3741,23 +3760,28 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
|
|
Jiri Slaby |
ba7816 |
bool is_binding = false;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
+ cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
|
|
Jiri Slaby |
ba7816 |
+ __func__, ses->chans_need_reconnect);
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
if (ses->ses_status != SES_GOOD &&
|
|
Jiri Slaby |
ba7816 |
ses->ses_status != SES_NEW &&
|
|
Jiri Slaby |
ba7816 |
ses->ses_status != SES_NEED_RECON) {
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
- return 0;
|
|
Jiri Slaby |
ba7816 |
+ return -EHOSTDOWN;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/* only send once per connect */
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- if (CIFS_ALL_CHANS_GOOD(ses) ||
|
|
Jiri Slaby |
ba7816 |
- cifs_chan_in_reconnect(ses, server)) {
|
|
Jiri Slaby |
ba7816 |
+ if (CIFS_ALL_CHANS_GOOD(ses)) {
|
|
Jiri Slaby |
ba7816 |
+ if (ses->ses_status == SES_NEED_RECON)
|
|
Jiri Slaby |
ba7816 |
+ ses->ses_status = SES_GOOD;
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
return 0;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
cifs_chan_set_in_reconnect(ses, server);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
if (!is_binding)
|
|
Jiri Slaby |
ba7816 |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
|
|
Jiri Slaby |
ba7816 |
index 83d04cd2..f0b1ae08 100644
|
|
Jiri Slaby |
ba7816 |
--- a/fs/cifs/smb2pdu.c
|
|
Jiri Slaby |
ba7816 |
+++ b/fs/cifs/smb2pdu.c
|
|
Jiri Slaby |
ba7816 |
@@ -199,6 +199,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+again:
|
|
Jiri Slaby |
ba7816 |
rc = cifs_wait_for_server_reconnect(server, tcon->retry);
|
|
Jiri Slaby |
ba7816 |
if (rc)
|
|
Jiri Slaby |
ba7816 |
return rc;
|
|
Jiri Slaby |
ba7816 |
@@ -217,6 +218,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
nls_codepage = load_nls_default();
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+ mutex_lock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
/*
|
|
Jiri Slaby |
ba7816 |
* Recheck after acquire mutex. If another thread is negotiating
|
|
Jiri Slaby |
ba7816 |
* and the server never sends an answer the socket will be closed
|
|
Jiri Slaby |
ba7816 |
@@ -225,6 +227,11 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
spin_lock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
if (server->tcpStatus == CifsNeedReconnect) {
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&server->srv_lock);
|
|
Jiri Slaby |
ba7816 |
+ mutex_unlock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
+ if (tcon->retry)
|
|
Jiri Slaby |
ba7816 |
+ goto again;
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
rc = -EHOSTDOWN;
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
@@ -234,19 +241,22 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
* need to prevent multiple threads trying to simultaneously
|
|
Jiri Slaby |
ba7816 |
* reconnect the same SMB session
|
|
Jiri Slaby |
ba7816 |
*/
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- if (!cifs_chan_needs_reconnect(ses, server)) {
|
|
Jiri Slaby |
ba7816 |
+ if (!cifs_chan_needs_reconnect(ses, server) &&
|
|
Jiri Slaby |
ba7816 |
+ ses->ses_status == SES_GOOD) {
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
-
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
/* this means that we only need to tree connect */
|
|
Jiri Slaby |
ba7816 |
if (tcon->need_reconnect)
|
|
Jiri Slaby |
ba7816 |
goto skip_sess_setup;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+ mutex_unlock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
- mutex_lock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
rc = cifs_negotiate_protocol(0, ses, server);
|
|
Jiri Slaby |
ba7816 |
if (!rc) {
|
|
Jiri Slaby |
ba7816 |
rc = cifs_setup_session(0, ses, server, nls_codepage);
|
|
Jiri Slaby |
ba7816 |
@@ -262,10 +272,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
mutex_unlock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
- mutex_unlock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
skip_sess_setup:
|
|
Jiri Slaby |
ba7816 |
- mutex_lock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
if (!tcon->need_reconnect) {
|
|
Jiri Slaby |
ba7816 |
mutex_unlock(&ses->session_mutex);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
@@ -280,7 +288,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
Jiri Slaby |
ba7816 |
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
|
|
Jiri Slaby |
ba7816 |
if (rc) {
|
|
Jiri Slaby |
ba7816 |
/* If sess reconnected but tcon didn't, something strange ... */
|
|
Jiri Slaby |
ba7816 |
- pr_warn_once("reconnect tcon failed rc = %d\n", rc);
|
|
Jiri Slaby |
ba7816 |
+ cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
@@ -1252,9 +1260,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
|
|
Jiri Slaby |
ba7816 |
if (rc)
|
|
Jiri Slaby |
ba7816 |
return rc;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
- spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
- spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
if (is_binding) {
|
|
Jiri Slaby |
ba7816 |
req->hdr.SessionId = cpu_to_le64(ses->Suid);
|
|
Jiri Slaby |
ba7816 |
@@ -1412,9 +1420,9 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
|
|
Jiri Slaby |
ba7816 |
goto out_put_spnego_key;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
- spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
- spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/* keep session key if binding */
|
|
Jiri Slaby |
ba7816 |
if (!is_binding) {
|
|
Jiri Slaby |
ba7816 |
@@ -1538,9 +1546,9 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
- spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
- spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/* keep existing ses id and flags if binding */
|
|
Jiri Slaby |
ba7816 |
if (!is_binding) {
|
|
Jiri Slaby |
ba7816 |
@@ -1606,9 +1614,9 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
- spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
- spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/* keep existing ses id and flags if binding */
|
|
Jiri Slaby |
ba7816 |
if (!is_binding) {
|
|
Jiri Slaby |
ba7816 |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
|
|
Jiri Slaby |
ba7816 |
index d827b754..790acf65 100644
|
|
Jiri Slaby |
ba7816 |
--- a/fs/cifs/smb2transport.c
|
|
Jiri Slaby |
ba7816 |
+++ b/fs/cifs/smb2transport.c
|
|
Jiri Slaby |
ba7816 |
@@ -81,6 +81,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
Jiri Slaby |
ba7816 |
struct cifs_ses *ses = NULL;
|
|
Jiri Slaby |
ba7816 |
int i;
|
|
Jiri Slaby |
ba7816 |
int rc = 0;
|
|
Jiri Slaby |
ba7816 |
+ bool is_binding = false;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
spin_lock(&cifs_tcp_ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
@@ -97,9 +98,12 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
found:
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- if (cifs_chan_needs_reconnect(ses, server) &&
|
|
Jiri Slaby |
ba7816 |
- !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (cifs_chan_needs_reconnect(ses, server) &&
|
|
Jiri Slaby |
ba7816 |
+ ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+ if (is_binding) {
|
|
Jiri Slaby |
ba7816 |
/*
|
|
Jiri Slaby |
ba7816 |
* If we are in the process of binding a new channel
|
|
Jiri Slaby |
ba7816 |
* to an existing session, use the master connection
|
|
Jiri Slaby |
ba7816 |
@@ -107,6 +111,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
Jiri Slaby |
ba7816 |
*/
|
|
Jiri Slaby |
ba7816 |
memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
@@ -119,10 +124,12 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
|
|
Jiri Slaby |
ba7816 |
if (chan->server == server) {
|
|
Jiri Slaby |
ba7816 |
memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
goto out;
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
}
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
cifs_dbg(VFS,
|
|
Jiri Slaby |
ba7816 |
"%s: Could not find channel signing key for session 0x%llx\n",
|
|
Jiri Slaby |
ba7816 |
@@ -392,11 +399,15 @@ generate_smb3signingkey(struct cifs_ses *ses,
|
|
Jiri Slaby |
ba7816 |
bool is_binding = false;
|
|
Jiri Slaby |
ba7816 |
int chan_index = 0;
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
+ spin_lock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
spin_lock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
- is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
|
|
Jiri Slaby |
ba7816 |
+ is_binding = (cifs_chan_needs_reconnect(ses, server) &&
|
|
Jiri Slaby |
ba7816 |
+ ses->ses_status == SES_GOOD);
|
|
Jiri Slaby |
ba7816 |
+
|
|
Jiri Slaby |
ba7816 |
chan_index = cifs_ses_get_chan_index(ses, server);
|
|
Jiri Slaby |
ba7816 |
/* TODO: introduce ref counting for channels when the can be freed */
|
|
Jiri Slaby |
ba7816 |
spin_unlock(&ses->chan_lock);
|
|
Jiri Slaby |
ba7816 |
+ spin_unlock(&ses->ses_lock);
|
|
Jiri Slaby |
ba7816 |
|
|
Jiri Slaby |
ba7816 |
/*
|
|
Jiri Slaby |
ba7816 |
* All channels use the same encryption/decryption keys but
|
|
Jiri Slaby |
ba7816 |
--
|
|
Jiri Slaby |
ba7816 |
2.35.3
|
|
Jiri Slaby |
ba7816 |
|