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