Skip to content

Commit 88b024f

Browse files
sprasad-microsoftSteve French
authored andcommitted
cifs: protect all accesses to chan_* with chan_lock
A spin lock called chan_lock was introduced recently. But not all accesses were protected. Doing that with this change. To make sure that a channel is not freed when in use, we need to introduce a ref count. But today, we don't ever free channels. Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent a05885c commit 88b024f

File tree

5 files changed

+22
-5
lines changed

5 files changed

+22
-5
lines changed

fs/cifs/connect.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1831,7 +1831,6 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
18311831

18321832
spin_lock(&ses->chan_lock);
18331833
chan_count = ses->chan_count;
1834-
spin_unlock(&ses->chan_lock);
18351834

18361835
/* close any extra channels */
18371836
if (chan_count > 1) {
@@ -1848,6 +1847,7 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
18481847
ses->chans[i].server = NULL;
18491848
}
18501849
}
1850+
spin_unlock(&ses->chan_lock);
18511851

18521852
sesInfoFree(ses);
18531853
cifs_put_tcp_session(server, 0);
@@ -2123,8 +2123,10 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
21232123
mutex_unlock(&ses->session_mutex);
21242124

21252125
/* each channel uses a different signing key */
2126+
spin_lock(&ses->chan_lock);
21262127
memcpy(ses->chans[0].signkey, ses->smb3signingkey,
21272128
sizeof(ses->smb3signingkey));
2129+
spin_unlock(&ses->chan_lock);
21282130

21292131
if (rc)
21302132
goto get_ses_fail;

fs/cifs/sess.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
6565
return false;
6666
}
6767

68+
/* channel helper functions. assumed that chan_lock is held by caller. */
69+
6870
unsigned int
6971
cifs_ses_get_chan_index(struct cifs_ses *ses,
7072
struct TCP_Server_Info *server)
@@ -134,10 +136,10 @@ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
134136
left = ses->chan_max - ses->chan_count;
135137

136138
if (left <= 0) {
139+
spin_unlock(&ses->chan_lock);
137140
cifs_dbg(FYI,
138141
"ses already at max_channels (%zu), nothing to open\n",
139142
ses->chan_max);
140-
spin_unlock(&ses->chan_lock);
141143
return 0;
142144
}
143145

@@ -369,12 +371,14 @@ void cifs_ses_mark_for_reconnect(struct cifs_ses *ses)
369371
{
370372
int i;
371373

374+
spin_lock(&cifs_tcp_ses_lock);
375+
spin_lock(&ses->chan_lock);
372376
for (i = 0; i < ses->chan_count; i++) {
373-
spin_lock(&cifs_tcp_ses_lock);
374377
if (ses->chans[i].server->tcpStatus != CifsExiting)
375378
ses->chans[i].server->tcpStatus = CifsNeedReconnect;
376-
spin_unlock(&cifs_tcp_ses_lock);
377379
}
380+
spin_unlock(&ses->chan_lock);
381+
spin_unlock(&cifs_tcp_ses_lock);
378382
}
379383

380384
static __u32 cifs_ssetup_hdr(struct cifs_ses *ses,

fs/cifs/smb2pdu.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,10 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
244244
spin_unlock(&ses->chan_lock);
245245
return 0;
246246
}
247+
spin_unlock(&ses->chan_lock);
247248
cifs_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d",
248249
tcon->ses->chans_need_reconnect,
249250
tcon->need_reconnect);
250-
spin_unlock(&ses->chan_lock);
251251

252252
nls_codepage = load_nls_default();
253253

@@ -3835,11 +3835,13 @@ void smb2_reconnect_server(struct work_struct *work)
38353835
* binding session, but tcon is healthy (some other channel
38363836
* is active)
38373837
*/
3838+
spin_lock(&ses->chan_lock);
38383839
if (!tcon_selected && cifs_chan_needs_reconnect(ses, server)) {
38393840
list_add_tail(&ses->rlist, &tmp_ses_list);
38403841
ses_selected = ses_exist = true;
38413842
ses->ses_count++;
38423843
}
3844+
spin_unlock(&ses->chan_lock);
38433845
}
38443846
/*
38453847
* Get the reference to server struct to be sure that the last call of

fs/cifs/smb2transport.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
100100
goto out;
101101

102102
found:
103+
spin_lock(&ses->chan_lock);
103104
if (cifs_chan_needs_reconnect(ses, server) &&
104105
!CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
105106
/*
@@ -108,6 +109,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
108109
* session key
109110
*/
110111
memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
112+
spin_unlock(&ses->chan_lock);
111113
goto out;
112114
}
113115

@@ -119,9 +121,11 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
119121
chan = ses->chans + i;
120122
if (chan->server == server) {
121123
memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
124+
spin_unlock(&ses->chan_lock);
122125
goto out;
123126
}
124127
}
128+
spin_unlock(&ses->chan_lock);
125129

126130
cifs_dbg(VFS,
127131
"%s: Could not find channel signing key for session 0x%llx\n",
@@ -430,8 +434,10 @@ generate_smb3signingkey(struct cifs_ses *ses,
430434
return rc;
431435

432436
/* safe to access primary channel, since it will never go away */
437+
spin_lock(&ses->chan_lock);
433438
memcpy(ses->chans[0].signkey, ses->smb3signingkey,
434439
SMB3_SIGN_KEY_SIZE);
440+
spin_unlock(&ses->chan_lock);
435441

436442
rc = generate_key(ses, ptriplet->encryption.label,
437443
ptriplet->encryption.context,

fs/cifs/transport.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,10 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
10491049

10501050
/* round robin */
10511051
index = (uint)atomic_inc_return(&ses->chan_seq);
1052+
1053+
spin_lock(&ses->chan_lock);
10521054
index %= ses->chan_count;
1055+
spin_unlock(&ses->chan_lock);
10531056

10541057
return ses->chans[index].server;
10551058
}

0 commit comments

Comments
 (0)