Skip to content

Commit 9a7d5a9

Browse files
aaptelsmfrench
authored andcommitted
cifs: fix possible uninitialized access and race on iface_list
iface[0] was accessed regardless of the count value and without locking. * check count before accessing any ifaces * make copy of iface list (it's a simple POD array) and use it without locking. Signed-off-by: Aurelien Aptel <[email protected]> Signed-off-by: Steve French <[email protected]> Reviewed-by: Paulo Alcantara (SUSE) <[email protected]>
1 parent 3345bb4 commit 9a7d5a9

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

fs/cifs/sess.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
7777
int i = 0;
7878
int rc = 0;
7979
int tries = 0;
80+
struct cifs_server_iface *ifaces = NULL;
81+
size_t iface_count;
8082

8183
if (left <= 0) {
8284
cifs_dbg(FYI,
@@ -90,6 +92,26 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
9092
return 0;
9193
}
9294

95+
/*
96+
* Make a copy of the iface list at the time and use that
97+
* instead so as to not hold the iface spinlock for opening
98+
* channels
99+
*/
100+
spin_lock(&ses->iface_lock);
101+
iface_count = ses->iface_count;
102+
if (iface_count <= 0) {
103+
spin_unlock(&ses->iface_lock);
104+
cifs_dbg(FYI, "no iface list available to open channels\n");
105+
return 0;
106+
}
107+
ifaces = kmemdup(ses->iface_list, iface_count*sizeof(*ifaces),
108+
GFP_ATOMIC);
109+
if (!ifaces) {
110+
spin_unlock(&ses->iface_lock);
111+
return 0;
112+
}
113+
spin_unlock(&ses->iface_lock);
114+
93115
/*
94116
* Keep connecting to same, fastest, iface for all channels as
95117
* long as its RSS. Try next fastest one if not RSS or channel
@@ -105,17 +127,17 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
105127
break;
106128
}
107129

108-
iface = &ses->iface_list[i];
130+
iface = &ifaces[i];
109131
if (is_ses_using_iface(ses, iface) && !iface->rss_capable) {
110-
i = (i+1) % ses->iface_count;
132+
i = (i+1) % iface_count;
111133
continue;
112134
}
113135

114136
rc = cifs_ses_add_channel(ses, iface);
115137
if (rc) {
116138
cifs_dbg(FYI, "failed to open extra channel on iface#%d rc=%d\n",
117139
i, rc);
118-
i = (i+1) % ses->iface_count;
140+
i = (i+1) % iface_count;
119141
continue;
120142
}
121143

@@ -124,6 +146,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
124146
left--;
125147
}
126148

149+
kfree(ifaces);
127150
return ses->chan_count - old_chan_count;
128151
}
129152

0 commit comments

Comments
 (0)