Issue: WCSWREL-119 Fix RCU warning when call ieee80211_bss_get_ie

[Description]
[  179.414989] =============================
[  179.419033] WARNING: suspicious RCU usage
[  179.428095] 5.11.0-rc1-next-20210104-04456-g31eb08622591 #1 Tainted: G           O
[  179.438042] -----------------------------
[  179.443768] net/wireless/util.c:911 suspicious rcu_dereference_check() usage!
[  179.453802]
[  179.453802] other info that might help us debug this:
[  179.453802]
[  179.463924]
[  179.463924] rcu_scheduler_active = 2, debug_locks = 1
[  179.472528] 3 locks held by wpa_supplicant/586:
[  179.477109]  #0: c18c5058 (cb_lock){++++}-{3:3}, at: genl_rcv+0x14/0x34
[  179.486226]  #1: c18be65c (rtnl_mutex){+.+.}-{3:3}, at: nl80211_pre_doit+0x104/0x1e8
[  179.496033]  #2: c8382da0 (&wdev->mtx){+.+.}-{3:3}, at: nl80211_connect+0x580/0x7ac
[  179.505687]
[  179.505687] stack backtrace:
[  179.511970] CPU: 0 PID: 586 Comm: wpa_supplicant Tainted: G           O      5.11.0-rc1-next-20210104-04456-g31eb08622591 #1
[  179.523233] Hardware name: Freescale i.MX6 SoloX (Device Tree)
[  179.529093] [<c0111814>] (unwind_backtrace) from [<c010bd5c>] (show_stack+0x10/0x14)
[  179.536883] [<c010bd5c>] (show_stack) from [<c0eeae24>] (dump_stack+0xcc/0xf4)
[  179.544142] [<c0eeae24>] (dump_stack) from [<c0ded2b4>] (ieee80211_bss_get_elem+0x84/0x98)
[  179.552443] [<c0ded2b4>] (ieee80211_bss_get_elem) from [<bf0e11bc>] (woal_cfg80211_assoc+0x50c/0x98c [moal])
[  179.562737] [<bf0e11bc>] (woal_cfg80211_assoc [moal]) from [<bf0e4e2c>] (woal_cfg80211_connect+0x174/0x584 [moal])
[  179.573748] [<bf0e4e2c>] (woal_cfg80211_connect [moal]) from [<c0e30450>] (cfg80211_connect+0x1d8/0x7fc)
[  179.583590] [<c0e30450>] (cfg80211_connect) from [<c0e02aac>] (nl80211_connect+0x59c/0x7ac)
[  179.591985] [<c0e02aac>] (nl80211_connect) from [<c0c21860>] (genl_rcv_msg+0x174/0x35c)
[  179.600029] [<c0c21860>] (genl_rcv_msg) from [<c0c20960>] (netlink_rcv_skb+0xbc/0x11c)
[  179.607975] [<c0c20960>] (netlink_rcv_skb) from [<c0c20fec>] (genl_rcv+0x20/0x34)
[  179.615486] [<c0c20fec>] (genl_rcv) from [<c0c20004>] (netlink_unicast+0x1ac/0x2e0)
[  179.623173] [<c0c20004>] (netlink_unicast) from [<c0c2030c>] (netlink_sendmsg+0x1d4/0x408)
[  179.631465] [<c0c2030c>] (netlink_sendmsg) from [<c0b9d080>] (____sys_sendmsg+0x1c4/0x274)
[  179.639764] [<c0b9d080>] (____sys_sendmsg) from [<c0b9ee08>] (___sys_sendmsg+0xa4/0xd8)
[  179.647803] [<c0b9ee08>] (___sys_sendmsg) from [<c0b9efe0>] (sys_sendmsg+0x50/0x94)
[  179.655491] [<c0b9efe0>] (sys_sendmsg) from [<c0100080>] (ret_fast_syscall+0x0/0x2c)
[  179.663265] Exception stack(0xc839bfa8 to 0xc839bff0)
[  179.668342] bfa0:                   01352b30 01351da0 00000005 bec05770 00000000 00000000
[  179.676545] bfc0: 01352b30 01351da0 b6f49550 00000128 bec05770 bec057e8 00000001 00000004
[  179.684744] bfe0: 00000128 bec05720 b6c24bbf b6ba4616
[  179.718172] wlan: Connected to bssid c0:XX:XX:XX:3e:85 successfully

[Analysis]
RCU warning is happened at rcu_dereference -> rcu_dereference_check, rcu_read_lock_held() is a condition check in it.
When rcu_read_lock_held() return false, warning will be printed.

[Fix]
When call ieee80211_bss_get_ie(), the code and related ie need be wrapped around by rcu_read_lock()/rcu_read_unlock().

Signed-off-by: longli <li.long@nxp.com>
Reviewed-by: Sherry Sun <sherry.sun@nxp.com>
This commit is contained in:
longli 2021-03-01 15:11:36 +08:00 committed by yang.tian
parent 840341b39d
commit cbc3b6bfd7

View file

@ -1535,8 +1535,10 @@ static int woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
mlan_status status = MLAN_STATUS_SUCCESS;
ENTER();
rcu_read_lock();
country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
if (!country_ie) {
rcu_read_unlock();
PRINTM(MIOCTL, "No country IE found!\n");
woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
LEAVE();
@ -1545,6 +1547,7 @@ static int woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
country_ie_len = country_ie[1];
if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
rcu_read_unlock();
PRINTM(MIOCTL, "Wrong Country IE length!\n");
woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT);
LEAVE();
@ -1554,6 +1557,7 @@ static int woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
priv->phandle->country_code[1] = country_ie[3];
priv->phandle->country_code[2] = ' ';
if (is_cfg80211_special_region_code(priv->phandle->country_code)) {
rcu_read_unlock();
PRINTM(MIOCTL, "Skip special region code in CountryIE");
LEAVE();
return 0;
@ -1565,6 +1569,7 @@ static int woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
/* Allocate an IOCTL request buffer */
req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
if (req == NULL) {
rcu_read_unlock();
PRINTM(MERROR, "Fail to allocate mlan_ds_11d_cfg buffer\n");
ret = MLAN_STATUS_FAILURE;
goto done;
@ -1599,6 +1604,8 @@ static int woal_process_country_ie(moal_private *priv, struct cfg80211_bss *bss)
PRINTM(MCMND, "11D: Country IE: %c%c band=%d no_of_sub_band=%d\n",
country_ie[2], country_ie[3], priv->phandle->band,
cfg_11d->param.domain_info.no_of_sub_band);
rcu_read_unlock();
/* Send domain info command to FW */
status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
if (status != MLAN_STATUS_SUCCESS) {
@ -2366,11 +2373,13 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
priv->auth_alg = 0xFFFF;
memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
rcu_read_lock();
ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
moal_memcpy_ext(priv->phandle, ssid_bssid.bssid, req->bss->bssid,
ETH_ALEN, sizeof(ssid_bssid.bssid));
if (!ssid_ie) {
rcu_read_unlock();
ret = -EINVAL;
goto done;
}
@ -2378,6 +2387,7 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,
moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid, ssid_ie + 2,
ssid_ie[1], sizeof(ssid_bssid.ssid.ssid));
ssid_bssid.ssid.ssid_len = ssid_ie[1];
rcu_read_unlock();
if (ssid_bssid.ssid.ssid_len > MW_ESSID_MAX_SIZE) {
PRINTM(MERROR, "Invalid SSID - aborting\n");