diff mbox

[next,V2] brcmfmac: avoid writing channel out of allocated array

Message ID 20170103164930.29989-1-zajec5@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show

Commit Message

Rafał Miłecki Jan. 3, 2017, 4:49 p.m. UTC
From: Rafał Miłecki <rafal@milecki.pl>

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>
---
V2: Add extra comment in code for not-found channel.
    Make it clear this problem have never been seen so far
    Explain why it's safe to drop extra assignments
    Note & reason changing channel variable usage
---
 .../broadcom/brcm80211/brcmfmac/cfg80211.c         | 32 ++++++++++++----------
 1 file changed, 17 insertions(+), 15 deletions(-)

Comments

Arend van Spriel Jan. 4, 2017, 9:39 a.m. UTC | #1
On 3-1-2017 17:49, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> 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>
> ---
> V2: Add extra comment in code for not-found channel.
>     Make it clear this problem have never been seen so far
>     Explain why it's safe to drop extra assignments
>     Note & reason changing channel variable usage
> ---
>  .../broadcom/brcm80211/brcmfmac/cfg80211.c         | 32 ++++++++++++----------
>  1 file changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> index 9c2c128..a16dd7b 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> @@ -5825,7 +5825,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>  	u32 i, j;
>  	u32 total;
>  	u32 chaninfo;
> -	u32 index;
>  
>  	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
>  
> @@ -5873,33 +5872,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>  		    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("Firmware reported unexpected channel %d\n",
> +				  ch.control_ch_num);

Maybe rephrase to "Ignoring unexpected firmware channel %d\n" so
end-users are not alarmed by this error message. I think using
brcmf_err() is justified, but you may even consider chiming down to
brcmf_dbg(INFO, ...).

Regards,
Arend
Rafał Miłecki Jan. 4, 2017, 10:40 a.m. UTC | #2
On 4 January 2017 at 10:39, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 3-1-2017 17:49, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>>
>> 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>
>> ---
>> V2: Add extra comment in code for not-found channel.
>>     Make it clear this problem have never been seen so far
>>     Explain why it's safe to drop extra assignments
>>     Note & reason changing channel variable usage
>> ---
>>  .../broadcom/brcm80211/brcmfmac/cfg80211.c         | 32 ++++++++++++----------
>>  1 file changed, 17 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>> index 9c2c128..a16dd7b 100644
>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>> @@ -5825,7 +5825,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>       u32 i, j;
>>       u32 total;
>>       u32 chaninfo;
>> -     u32 index;
>>
>>       pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
>>
>> @@ -5873,33 +5872,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>                   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("Firmware reported unexpected channel %d\n",
>> +                               ch.control_ch_num);
>
> Maybe rephrase to "Ignoring unexpected firmware channel %d\n" so
> end-users are not alarmed by this error message. I think using
> brcmf_err() is justified, but you may even consider chiming down to
> brcmf_dbg(INFO, ...).

Can you suggest a better error message? It seems I'm too brave and I
don't find this one alarming, so I need suggestion.
Arend van Spriel Jan. 4, 2017, 10:48 a.m. UTC | #3
On 4-1-2017 11:40, Rafał Miłecki wrote:
> On 4 January 2017 at 10:39, Arend Van Spriel
> <arend.vanspriel@broadcom.com> wrote:
>> On 3-1-2017 17:49, Rafał Miłecki wrote:
>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>
>>> 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>
>>> ---
>>> V2: Add extra comment in code for not-found channel.
>>>     Make it clear this problem have never been seen so far
>>>     Explain why it's safe to drop extra assignments
>>>     Note & reason changing channel variable usage
>>> ---
>>>  .../broadcom/brcm80211/brcmfmac/cfg80211.c         | 32 ++++++++++++----------
>>>  1 file changed, 17 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>> index 9c2c128..a16dd7b 100644
>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>> @@ -5825,7 +5825,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>>       u32 i, j;
>>>       u32 total;
>>>       u32 chaninfo;
>>> -     u32 index;
>>>
>>>       pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
>>>
>>> @@ -5873,33 +5872,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>>                   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("Firmware reported unexpected channel %d\n",
>>> +                               ch.control_ch_num);
>>
>> Maybe rephrase to "Ignoring unexpected firmware channel %d\n" so
>> end-users are not alarmed by this error message. I think using
>> brcmf_err() is justified, but you may even consider chiming down to
>> brcmf_dbg(INFO, ...).
> 
> Can you suggest a better error message? It seems I'm too brave and I
> don't find this one alarming, so I need suggestion.

Uhm. There is a suggestion above. :-p

Regards,
Arend
Rafał Miłecki Jan. 4, 2017, 11:04 a.m. UTC | #4
On 4 January 2017 at 11:48, Arend Van Spriel
<arend.vanspriel@broadcom.com> wrote:
> On 4-1-2017 11:40, Rafał Miłecki wrote:
>> On 4 January 2017 at 10:39, Arend Van Spriel
>> <arend.vanspriel@broadcom.com> wrote:
>>> On 3-1-2017 17:49, Rafał Miłecki wrote:
>>>> From: Rafał Miłecki <rafal@milecki.pl>
>>>>
>>>> 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>
>>>> ---
>>>> V2: Add extra comment in code for not-found channel.
>>>>     Make it clear this problem have never been seen so far
>>>>     Explain why it's safe to drop extra assignments
>>>>     Note & reason changing channel variable usage
>>>> ---
>>>>  .../broadcom/brcm80211/brcmfmac/cfg80211.c         | 32 ++++++++++++----------
>>>>  1 file changed, 17 insertions(+), 15 deletions(-)
>>>>
>>>> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>>> index 9c2c128..a16dd7b 100644
>>>> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>>> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
>>>> @@ -5825,7 +5825,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>>>       u32 i, j;
>>>>       u32 total;
>>>>       u32 chaninfo;
>>>> -     u32 index;
>>>>
>>>>       pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
>>>>
>>>> @@ -5873,33 +5872,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
>>>>                   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("Firmware reported unexpected channel %d\n",
>>>> +                               ch.control_ch_num);
>>>
>>> Maybe rephrase to "Ignoring unexpected firmware channel %d\n" so
>>> end-users are not alarmed by this error message. I think using
>>> brcmf_err() is justified, but you may even consider chiming down to
>>> brcmf_dbg(INFO, ...).
>>
>> Can you suggest a better error message? It seems I'm too brave and I
>> don't find this one alarming, so I need suggestion.
>
> Uhm. There is a suggestion above. :-p

... sorry, it seems I should take a break ;)
diff mbox

Patch

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 9c2c128..a16dd7b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -5825,7 +5825,6 @@  static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
 	u32 i, j;
 	u32 total;
 	u32 chaninfo;
-	u32 index;
 
 	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
 
@@ -5873,33 +5872,36 @@  static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
 		    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("Firmware reported unexpected 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;
@@ -5907,11 +5909,11 @@  static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
 						       &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;
 			}
 		}