summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorMohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>2017-04-27 03:15:38 -0400
committerJohannes Berg <johannes.berg@intel.com>2017-04-28 06:28:44 -0400
commit21a8e9dd52b64f0170bad208293ef8c30c3c1403 (patch)
treeaf61429b6f3d3f06f3c1a47690aa31dbcff23ee3 /net/mac80211/mlme.c
parent5fe49a9d11644f4aa9034c7eedbcfc6e52373e10 (diff)
mac80211: Fix possible sband related NULL pointer de-reference
Existing API 'ieee80211_get_sdata_band' returns default 2 GHz band even if the channel context configuration is NULL. This crashes for chipsets which support 5 Ghz alone when it tries to access members of 'sband'. Channel context configuration can be NULL in multivif case and when channel switch is in progress (or) when it fails. Fix this by replacing the API 'ieee80211_get_sdata_band' with 'ieee80211_get_sband' which returns a NULL pointer for sband when the channel configuration is NULL. An example scenario is as below: In multivif mode (AP + STA) with drivers like ath10k, when we do a channel switch in the AP vif (which has a number of clients connected) and a STA vif which is connected to some other AP, when the channel switch in AP vif fails, while the STA vifs tries to connect to the other AP, there is a window where the channel context is NULL/invalid and this results in a crash while the clients connected to the AP vif tries to reconnect and this race is very similar to the one investigated by Michal in https://patchwork.kernel.org/patch/3788161/ and this does happens with hardware that supports 5Ghz alone after long hours of testing with continuous channel switch on the AP vif ieee80211 phy0: channel context reservation cannot be finalized because some interfaces aren't switching wlan0: failed to finalize CSA, disconnecting wlan0-1: deauthenticating from 8c:fd:f0:01:54:9c by local choice (Reason: 3=DEAUTH_LEAVING) WARNING: CPU: 1 PID: 19032 at net/mac80211/ieee80211_i.h:1013 sta_info_alloc+0x374/0x3fc [mac80211] [<bf77272c>] (sta_info_alloc [mac80211]) [<bf78776c>] (ieee80211_add_station [mac80211])) [<bf73cc50>] (nl80211_new_station [cfg80211]) Unable to handle kernel NULL pointer dereference at virtual address 00000014 pgd = d5f4c000 Internal error: Oops: 17 [#1] PREEMPT SMP ARM PC is at sta_info_alloc+0x380/0x3fc [mac80211] LR is at sta_info_alloc+0x37c/0x3fc [mac80211] [<bf772738>] (sta_info_alloc [mac80211]) [<bf78776c>] (ieee80211_add_station [mac80211]) [<bf73cc50>] (nl80211_new_station [cfg80211])) Cc: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 24d69bcf71ad..45d80fe61c5f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1855,11 +1855,16 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
1855 u16 capab, bool erp_valid, u8 erp) 1855 u16 capab, bool erp_valid, u8 erp)
1856{ 1856{
1857 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 1857 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1858 struct ieee80211_supported_band *sband;
1858 u32 changed = 0; 1859 u32 changed = 0;
1859 bool use_protection; 1860 bool use_protection;
1860 bool use_short_preamble; 1861 bool use_short_preamble;
1861 bool use_short_slot; 1862 bool use_short_slot;
1862 1863
1864 sband = ieee80211_get_sband(sdata);
1865 if (!sband)
1866 return changed;
1867
1863 if (erp_valid) { 1868 if (erp_valid) {
1864 use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0; 1869 use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0;
1865 use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0; 1870 use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0;
@@ -1869,7 +1874,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
1869 } 1874 }
1870 1875
1871 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); 1876 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
1872 if (ieee80211_get_sdata_band(sdata) == NL80211_BAND_5GHZ) 1877 if (sband->band == NL80211_BAND_5GHZ)
1873 use_short_slot = true; 1878 use_short_slot = true;
1874 1879
1875 if (use_protection != bss_conf->use_cts_prot) { 1880 if (use_protection != bss_conf->use_cts_prot) {
@@ -3004,7 +3009,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
3004 goto out; 3009 goto out;
3005 } 3010 }
3006 3011
3007 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; 3012 sband = ieee80211_get_sband(sdata);
3013 if (!sband) {
3014 mutex_unlock(&sdata->local->sta_mtx);
3015 ret = false;
3016 goto out;
3017 }
3008 3018
3009 /* Set up internal HT/VHT capabilities */ 3019 /* Set up internal HT/VHT capabilities */
3010 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) 3020 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))