Skip to content

Commit ac42c12

Browse files
jerome-pouillergregkh
authored andcommitted
staging: wfx: fix RCU usage between hif_join() and ieee80211_bss_get_ie()
Access to result of ieee80211_bss_get_ie() is protected by RCU. In other hand, function hif_join() can sleep and cannot be called with RCU locked. Provide a copy of "ssidie" to hif_join() to solve this behavior. Fixes: 9ced9b5 ("staging: wfx: simplify hif_join()") Signed-off-by: Jérôme Pouiller <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 046cc2e commit ac42c12

File tree

3 files changed

+15
-12
lines changed

3 files changed

+15
-12
lines changed

drivers/staging/wfx/hif_tx.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ int hif_stop_scan(struct wfx_vif *wvif)
290290
}
291291

292292
int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
293-
const struct ieee80211_channel *channel, const u8 *ssidie)
293+
struct ieee80211_channel *channel, const u8 *ssid, int ssidlen)
294294
{
295295
int ret;
296296
struct hif_msg *hif;
@@ -308,9 +308,9 @@ int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
308308
body->basic_rate_set =
309309
cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates));
310310
memcpy(body->bssid, conf->bssid, sizeof(body->bssid));
311-
if (!conf->ibss_joined && ssidie) {
312-
body->ssid_length = cpu_to_le32(ssidie[1]);
313-
memcpy(body->ssid, &ssidie[2], ssidie[1]);
311+
if (!conf->ibss_joined && ssid) {
312+
body->ssid_length = cpu_to_le32(ssidlen);
313+
memcpy(body->ssid, ssid, ssidlen);
314314
}
315315
wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body));
316316
ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);

drivers/staging/wfx/hif_tx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211,
4646
int chan_start, int chan_num);
4747
int hif_stop_scan(struct wfx_vif *wvif);
4848
int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
49-
const struct ieee80211_channel *channel, const u8 *ssidie);
49+
struct ieee80211_channel *channel, const u8 *ssid, int ssidlen);
5050
int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout);
5151
int hif_set_bss_params(struct wfx_vif *wvif,
5252
const struct hif_req_set_bss_params *arg);

drivers/staging/wfx/sta.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -491,9 +491,11 @@ static void wfx_set_mfp(struct wfx_vif *wvif,
491491
static void wfx_do_join(struct wfx_vif *wvif)
492492
{
493493
int ret;
494-
const u8 *ssidie;
495494
struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
496495
struct cfg80211_bss *bss = NULL;
496+
u8 ssid[IEEE80211_MAX_SSID_LEN];
497+
const u8 *ssidie = NULL;
498+
int ssidlen = 0;
497499

498500
wfx_tx_lock_flush(wvif->wdev);
499501

@@ -514,11 +516,14 @@ static void wfx_do_join(struct wfx_vif *wvif)
514516
if (!wvif->beacon_int)
515517
wvif->beacon_int = 1;
516518

517-
rcu_read_lock();
519+
rcu_read_lock(); // protect ssidie
518520
if (!conf->ibss_joined)
519521
ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
520-
else
521-
ssidie = NULL;
522+
if (ssidie) {
523+
ssidlen = ssidie[1];
524+
memcpy(ssid, &ssidie[2], ssidie[1]);
525+
}
526+
rcu_read_unlock();
522527

523528
wfx_tx_flush(wvif->wdev);
524529

@@ -527,10 +532,8 @@ static void wfx_do_join(struct wfx_vif *wvif)
527532

528533
wfx_set_mfp(wvif, bss);
529534

530-
/* Perform actual join */
531535
wvif->wdev->tx_burst_idx = -1;
532-
ret = hif_join(wvif, conf, wvif->channel, ssidie);
533-
rcu_read_unlock();
536+
ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
534537
if (ret) {
535538
ieee80211_connection_loss(wvif->vif);
536539
wvif->join_complete_status = -1;

0 commit comments

Comments
 (0)