2017-01-10 16:18:01 +00:00
|
|
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
|
|
|
Date: Wed, 4 Jan 2017 12:09:41 +0100
|
|
|
|
Subject: [PATCH] brcmfmac: avoid writing channel out of allocated array
|
|
|
|
MIME-Version: 1.0
|
|
|
|
Content-Type: text/plain; charset=UTF-8
|
|
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
|
|
|
|
Our code was assigning number of channels to the index variable by
|
|
|
|
default. If firmware reported channel we didn't predict this would
|
|
|
|
result in using that initial index value and writing out of array. This
|
|
|
|
never happened so far (we got a complete list of supported channels) but
|
|
|
|
it means possible memory corruption so we should handle it anyway.
|
|
|
|
|
|
|
|
This patch simply detects unexpected channel and ignores it.
|
|
|
|
|
|
|
|
As we don't try to create new entry now, it's also safe to drop hw_value
|
|
|
|
and center_freq assignment. For known channels we have these set anyway.
|
|
|
|
|
|
|
|
I decided to fix this issue by assigning NULL or a target channel to the
|
|
|
|
channel variable. This was one of possible ways, I prefefred this one as
|
|
|
|
it also avoids using channel[index] over and over.
|
|
|
|
|
|
|
|
Fixes: 58de92d2f95e ("brcmfmac: use static superset of channels for wiphy bands")
|
|
|
|
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
|
|
|
|
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
|
2017-01-17 21:41:18 +00:00
|
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
2017-01-10 16:18:01 +00:00
|
|
|
---
|
|
|
|
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
|
|
@@ -5913,7 +5913,6 @@ static int brcmf_construct_chaninfo(stru
|
|
|
|
u32 i, j;
|
|
|
|
u32 total;
|
|
|
|
u32 chaninfo;
|
|
|
|
- u32 index;
|
|
|
|
|
|
|
|
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
|
|
|
|
|
|
|
|
@@ -5961,33 +5960,36 @@ static int brcmf_construct_chaninfo(stru
|
|
|
|
ch.bw == BRCMU_CHAN_BW_80)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
- channel = band->channels;
|
|
|
|
- index = band->n_channels;
|
|
|
|
+ channel = NULL;
|
|
|
|
for (j = 0; j < band->n_channels; j++) {
|
|
|
|
- if (channel[j].hw_value == ch.control_ch_num) {
|
|
|
|
- index = j;
|
|
|
|
+ if (band->channels[j].hw_value == ch.control_ch_num) {
|
|
|
|
+ channel = &band->channels[j];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
- channel[index].center_freq =
|
|
|
|
- ieee80211_channel_to_frequency(ch.control_ch_num,
|
|
|
|
- band->band);
|
|
|
|
- channel[index].hw_value = ch.control_ch_num;
|
|
|
|
+ if (!channel) {
|
|
|
|
+ /* It seems firmware supports some channel we never
|
|
|
|
+ * considered. Something new in IEEE standard?
|
|
|
|
+ */
|
|
|
|
+ brcmf_err("Ignoring unexpected firmware channel %d\n",
|
|
|
|
+ ch.control_ch_num);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/* assuming the chanspecs order is HT20,
|
|
|
|
* HT40 upper, HT40 lower, and VHT80.
|
|
|
|
*/
|
|
|
|
if (ch.bw == BRCMU_CHAN_BW_80) {
|
|
|
|
- channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
|
|
|
|
+ channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
|
|
|
|
} else if (ch.bw == BRCMU_CHAN_BW_40) {
|
|
|
|
- brcmf_update_bw40_channel_flag(&channel[index], &ch);
|
|
|
|
+ brcmf_update_bw40_channel_flag(channel, &ch);
|
|
|
|
} else {
|
|
|
|
/* enable the channel and disable other bandwidths
|
|
|
|
* for now as mentioned order assure they are enabled
|
|
|
|
* for subsequent chanspecs.
|
|
|
|
*/
|
|
|
|
- channel[index].flags = IEEE80211_CHAN_NO_HT40 |
|
|
|
|
- IEEE80211_CHAN_NO_80MHZ;
|
|
|
|
+ channel->flags = IEEE80211_CHAN_NO_HT40 |
|
|
|
|
+ IEEE80211_CHAN_NO_80MHZ;
|
|
|
|
ch.bw = BRCMU_CHAN_BW_20;
|
|
|
|
cfg->d11inf.encchspec(&ch);
|
|
|
|
chaninfo = ch.chspec;
|
|
|
|
@@ -5995,11 +5997,11 @@ static int brcmf_construct_chaninfo(stru
|
|
|
|
&chaninfo);
|
|
|
|
if (!err) {
|
|
|
|
if (chaninfo & WL_CHAN_RADAR)
|
|
|
|
- channel[index].flags |=
|
|
|
|
+ channel->flags |=
|
|
|
|
(IEEE80211_CHAN_RADAR |
|
|
|
|
IEEE80211_CHAN_NO_IR);
|
|
|
|
if (chaninfo & WL_CHAN_PASSIVE)
|
|
|
|
- channel[index].flags |=
|
|
|
|
+ channel->flags |=
|
|
|
|
IEEE80211_CHAN_NO_IR;
|
|
|
|
}
|
|
|
|
}
|