[PATCH AUTOSEL for 4.9 108/190] mac80211: Fix possible sband related NULL pointer de-reference

2018-03-07 Thread Sasha Levin
From: Mohammed Shafi Shajakhan 

[ Upstream commit 21a8e9dd52b64f0170bad208293ef8c30c3c1403 ]

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]
[] (sta_info_alloc [mac80211])
[] (ieee80211_add_station [mac80211]))
[] (nl80211_new_station [cfg80211])

Unable to handle kernel NULL pointer dereference at virtual
address 0014
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]
[] (sta_info_alloc [mac80211])
[] (ieee80211_add_station [mac80211])
[] (nl80211_new_station [cfg80211]))

Cc: Michal Kazior 
Signed-off-by: Mohammed Shafi Shajakhan 
Signed-off-by: Johannes Berg 
Signed-off-by: Sasha Levin 
---
 net/mac80211/cfg.c | 30 +-
 net/mac80211/ibss.c|  6 +-
 net/mac80211/ieee80211_i.h | 36 +---
 net/mac80211/mesh.c| 29 -
 net/mac80211/mesh_plink.c  | 37 ++---
 net/mac80211/mlme.c| 14 --
 net/mac80211/rate.c|  4 +++-
 net/mac80211/sta_info.c| 13 +
 net/mac80211/tdls.c| 29 +++--
 net/mac80211/tx.c  |  5 -
 net/mac80211/util.c|  6 +++---
 11 files changed, 139 insertions(+), 70 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index dee60428c78c..efa2a2fcae72 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -620,10 +620,11 @@ void sta_set_rate_info_tx(struct sta_info *sta,
int shift = ieee80211_vif_get_shift(>sdata->vif);
u16 brate;
 
-   sband = sta->local->hw.wiphy->bands[
-   ieee80211_get_sdata_band(sta->sdata)];
-   brate = sband->bitrates[rate->idx].bitrate;
-   rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+   sband = ieee80211_get_sband(sta->sdata);
+   if (sband) {
+   brate = sband->bitrates[rate->idx].bitrate;
+   rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+   }
}
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rinfo->bw = RATE_INFO_BW_40;
@@ -1218,10 +1219,11 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
int ret = 0;
struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata;
-   enum nl80211_band band = ieee80211_get_sdata_band(sdata);
u32 mask, set;
 
-   sband = local->hw.wiphy->bands[band];
+   sband = ieee80211_get_sband(sdata);
+   if (!sband)
+   return -EINVAL;
 
mask = params->sta_flags_mask;
set = params->sta_flags_set;
@@ -1354,7 +1356,7 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
ieee80211_parse_bitrates(>vif.bss_conf.chandef,
 sband, params->supported_rates,
 params->supported_rates_len,
->sta.supp_rates[band]);
+>sta.supp_rates[sband->band]);
}
 
if 

[PATCH AUTOSEL for 4.9 108/190] mac80211: Fix possible sband related NULL pointer de-reference

2018-03-07 Thread Sasha Levin
From: Mohammed Shafi Shajakhan 

[ Upstream commit 21a8e9dd52b64f0170bad208293ef8c30c3c1403 ]

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]
[] (sta_info_alloc [mac80211])
[] (ieee80211_add_station [mac80211]))
[] (nl80211_new_station [cfg80211])

Unable to handle kernel NULL pointer dereference at virtual
address 0014
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]
[] (sta_info_alloc [mac80211])
[] (ieee80211_add_station [mac80211])
[] (nl80211_new_station [cfg80211]))

Cc: Michal Kazior 
Signed-off-by: Mohammed Shafi Shajakhan 
Signed-off-by: Johannes Berg 
Signed-off-by: Sasha Levin 
---
 net/mac80211/cfg.c | 30 +-
 net/mac80211/ibss.c|  6 +-
 net/mac80211/ieee80211_i.h | 36 +---
 net/mac80211/mesh.c| 29 -
 net/mac80211/mesh_plink.c  | 37 ++---
 net/mac80211/mlme.c| 14 --
 net/mac80211/rate.c|  4 +++-
 net/mac80211/sta_info.c| 13 +
 net/mac80211/tdls.c| 29 +++--
 net/mac80211/tx.c  |  5 -
 net/mac80211/util.c|  6 +++---
 11 files changed, 139 insertions(+), 70 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index dee60428c78c..efa2a2fcae72 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -620,10 +620,11 @@ void sta_set_rate_info_tx(struct sta_info *sta,
int shift = ieee80211_vif_get_shift(>sdata->vif);
u16 brate;
 
-   sband = sta->local->hw.wiphy->bands[
-   ieee80211_get_sdata_band(sta->sdata)];
-   brate = sband->bitrates[rate->idx].bitrate;
-   rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+   sband = ieee80211_get_sband(sta->sdata);
+   if (sband) {
+   brate = sband->bitrates[rate->idx].bitrate;
+   rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+   }
}
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
rinfo->bw = RATE_INFO_BW_40;
@@ -1218,10 +1219,11 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
int ret = 0;
struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata;
-   enum nl80211_band band = ieee80211_get_sdata_band(sdata);
u32 mask, set;
 
-   sband = local->hw.wiphy->bands[band];
+   sband = ieee80211_get_sband(sdata);
+   if (!sband)
+   return -EINVAL;
 
mask = params->sta_flags_mask;
set = params->sta_flags_set;
@@ -1354,7 +1356,7 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
ieee80211_parse_bitrates(>vif.bss_conf.chandef,
 sband, params->supported_rates,
 params->supported_rates_len,
->sta.supp_rates[band]);
+>sta.supp_rates[sband->band]);
}
 
if (params->ht_capa)
@@ -1370,8 +1372,8 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
/* returned value