2012-08-20 16:54:06

by Sergei Poselenov

[permalink] [raw]
Subject: [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On our system (ARM Cortex-M3 SOC running linux-2.6.33 with
compat-wireless-3.4-rc3-1 modules configured for rt2x00) frequent
crashes were observed in rt2800usb module because of the invalid
length of the received packet (3392, 46920...). This patch adds
the sanity check on the packet legth. In case of the bad length,
mark the packet as with CRC error.

The fix was also tested on the latest
compat-wireless-3.5.1-1-snpc.tar.bz2, applies cleanly.

Cc: [email protected]
Signed-off-by: Sergei Poselenov <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
index 001735f..6776ec8 100644
--- a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -662,13 +662,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);

/*
- * Remove the RXINFO structure from the sbk.
+ * Remove the RXINFO structure from the skb.
*/
skb_pull(entry->skb, RXINFO_DESC_SIZE);

/*
- * FIXME: we need to check for rx_pkt_len validity
+ * Check for rx_pkt_len validity, mark as failed.
*/
+ if (rx_pkt_len > entry->skb->len) {
+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
+ goto procrxwi;
+ }
+
rxd = (__le32 *)(entry->skb->data + rx_pkt_len);

/*
@@ -713,6 +718,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
*/
skb_trim(entry->skb, rx_pkt_len);

+procrxwi:
/*
* Process the RXWI structure.
*/


2012-08-22 09:27:34

by Stanislaw Gruszka

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On Tue, Aug 21, 2012 at 10:07:03PM +0200, Gertjan van Wingerde wrote:
> >>>> + if (rx_pkt_len > entry->skb->len) {
> >>>> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
> >>>> + goto procrxwi;
> >>>
> >>> I would rather prefer something like
> >>>
> >>> if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
> >>> /* Process error in rt2x00lib_rxdone() */
> >>> rxdesc->size = rx_pkt_len;
> >>> return;
> >>> }
> >>
> >> But how do you know the packet is correct then?
> > Non zero rx_pkt_len smaller than data_size indicate correct package.
>
> To be honest, I think the original approach of Sergei is better. Not touching rxdesc beyond setting the flag will ensure that rt2x00lib_rxdone will simply bounce the skb without handing an invalid packet over to mac80211. That said, it isn't necessary to set the flag. Just returning from the function is good enough.
>
> However, the check that Sergei does is not correct either. The real check that should be done is checking whether the skb has enough data to hold both rx_pkt_len bytes + the size of the rxd, which is 1 word (4 bytes). If only rx_pkt_len are left we don't have an rxd, and is the usb packet invalid as well.

Yes, but there is also usb alignment on skb->len, so is better to use
queue->data_size to validate rx_pkt (data) length IMHO.

> >> Obviously something is wrong,
> >> so just resetting the rxdesc->size wouldn't be a solution right?
> >
> > rt2x00lib_rxdone has rxdesc->size check too, if ->size is bad it
> > prints warning, and requeue skb.
> >
> > Perhaps this could be coded in some cleaner way (avoid double check),
> > but basically this should do the job.
>
> As I mentioned above, simply bailing out if rt2800usb_fill_rxdone without doing anything (not even setting a flag) should do the trick and IMHO is the cleanest approach.

IIRC this is basically what I proposed, except without setting
rxdesc->size, unlikely() and rx_pkt_len == 0 check. It will work as
rxdesc->size will be 0. But I think it would be better, if WARNING on
rt2x00lib_rxdone() will print actual corrupted size instead of 0.
Having unlikely is good too - this must be unlikely situation.

BTW: would be good to fix reason of that corruption if possible
(as long this is not a H/W or F/W bug). But for now, let just
stop kernel crashing. Printing WARNING on this situation will
help to identify there is something wrong if someone will observe
performance problems or similar.

Thanks
Stanislaw

2012-08-22 21:16:50

by Stanislaw Gruszka

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

Hi Gertjan

On Wed, Aug 22, 2012 at 10:41:42PM +0200, Gertjan van Wingerde wrote:
> > IIRC this is basically what I proposed, except without setting
> > rxdesc->size, unlikely() and rx_pkt_len == 0 check. It will work as
> > rxdesc->size will be 0. But I think it would be better, if WARNING on
> > rt2x00lib_rxdone() will print actual corrupted size instead of 0.
> > Having unlikely is good too - this must be unlikely situation.
>
> OK, I agree with the use of unlikely(). An rx_pkt_len of 0 doesn't seem to happen in practice, so testing for it seems superfluous, but may be providing some extra safety. Don't really care about that. I really don't think we should set rxdesc->size, as we cannot determine it. If we want to print the value, then do it in this function. Adding a hack to having it printed somewhere else doesn't seem right to me.
> Also, it should be an error log message, not a WARNING. There's no need to have a stack trace as the buffer is filled by HW, not by some other function. So, the use of WARNING, with its stack dumping functionality is overkill.
>
>
> >
> > BTW: would be good to fix reason of that corruption if possible
> > (as long this is not a H/W or F/W bug). But for now, let just
> > stop kernel crashing. Printing WARNING on this situation will
> > help to identify there is something wrong if someone will observe
> > performance problems or similar.
>
> I think this is a HW issue. As mentioned above, I believe a WARNING here is overkill, as we don't need the stack trace.

I was talking about this WARNING in rt2x00lib_rxdone() (which is not
WARN_ON() or WARN() - so no stactrace):

/*
* Check for valid size in case we get corrupted descriptor from
* hardware.
*/
if (unlikely(rxdesc.size == 0 ||
rxdesc.size > entry->queue->data_size)) {
WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
rxdesc.size, entry->queue->data_size);
dev_kfree_skb(entry->skb);
goto renew_skb;
}


I agree that using ERROR is better.

> Anyway, Sergei, would you be able to modify the patch along the lines of the discussion?

I hope so :-)

Thanks
Stanislaw

2012-08-21 14:19:03

by Stanislaw Gruszka

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On Tue, Aug 21, 2012 at 03:39:41PM +0200, Ivo Van Doorn wrote:
> On Tue, Aug 21, 2012 at 1:43 PM, Stanislaw Gruszka <[email protected]> wrote:
> > On Mon, Aug 20, 2012 at 08:53:55PM +0400, Sergei Poselenov wrote:
> >> On our system (ARM Cortex-M3 SOC running linux-2.6.33 with
> >> compat-wireless-3.4-rc3-1 modules configured for rt2x00) frequent
> > Please remove compat-wireless reference here and in the subject.
> >
> >> crashes were observed in rt2800usb module because of the invalid
> >> length of the received packet (3392, 46920...). This patch adds
> >> the sanity check on the packet legth. In case of the bad length,
> >> mark the packet as with CRC error.
> >>
> >> The fix was also tested on the latest
> >> compat-wireless-3.5.1-1-snpc.tar.bz2, applies cleanly.
> >>
> >> Cc: [email protected]
> >> Signed-off-by: Sergei Poselenov <[email protected]>
> >> ---
> >> drivers/net/wireless/rt2x00/rt2800usb.c | 10 ++++++++--
> >> 1 files changed, 8 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> >> index 001735f..6776ec8 100644
> >> --- a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> >> +++ b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> >> @@ -662,13 +662,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
> >> rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
> >>
> >> /*
> >> - * Remove the RXINFO structure from the sbk.
> >> + * Remove the RXINFO structure from the skb.
> >> */
> >> skb_pull(entry->skb, RXINFO_DESC_SIZE);
> > Would be great if you could post this as separate patch.
> >
> >> /*
> >> - * FIXME: we need to check for rx_pkt_len validity
> >> + * Check for rx_pkt_len validity, mark as failed.
> >> */
> >> + if (rx_pkt_len > entry->skb->len) {
> >> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
> >> + goto procrxwi;
> >
> > I would rather prefer something like
> >
> > if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
> > /* Process error in rt2x00lib_rxdone() */
> > rxdesc->size = rx_pkt_len;
> > return;
> > }
>
> But how do you know the packet is correct then?
Non zero rx_pkt_len smaller than data_size indicate correct package.

> Obviously something is wrong,
> so just resetting the rxdesc->size wouldn't be a solution right?

rt2x00lib_rxdone has rxdesc->size check too, if ->size is bad it
prints warning, and requeue skb.

Perhaps this could be coded in some cleaner way (avoid double check),
but basically this should do the job.

Stanislaw

2012-08-23 05:46:42

by Sergei Poselenov

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

Hello guys,

On Wed, 2012-08-22 at 22:41 +0200, Gertjan van Wingerde wrote:
>
> Anyway, Sergei, would you be able to modify the patch along the lines
> of the discussion?

Yes, I've been watching your discussion. I hope I'll be able to come up
with a new version shortly.

Regards,
Sergei


2012-08-26 13:53:33

by Sergei Poselenov

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

Stanislaw,

On Tue, 2012-08-21 at 13:43 +0200, Stanislaw Gruszka wrote:
> > /*
> > - * Remove the RXINFO structure from the sbk.
> > + * Remove the RXINFO structure from the skb.
> > */
> > skb_pull(entry->skb, RXINFO_DESC_SIZE);
> Would be great if you could post this as separate patch.

I'm sending the patch for this typo in the follow-up email.

Regards,
Sergei


2012-08-22 20:41:48

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

Hi Stanislaw,

On 22 aug. 2012, at 11:27, Stanislaw Gruszka <[email protected]> wrote:

> On Tue, Aug 21, 2012 at 10:07:03PM +0200, Gertjan van Wingerde wrote:
>>>>>> + if (rx_pkt_len > entry->skb->len) {
>>>>>> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
>>>>>> + goto procrxwi;
>>>>>
>>>>> I would rather prefer something like
>>>>>
>>>>> if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
>>>>> /* Process error in rt2x00lib_rxdone() */
>>>>> rxdesc->size = rx_pkt_len;
>>>>> return;
>>>>> }
>>>>
>>>> But how do you know the packet is correct then?
>>> Non zero rx_pkt_len smaller than data_size indicate correct package.
>>
>> To be honest, I think the original approach of Sergei is better. Not touching rxdesc beyond setting the flag will ensure that rt2x00lib_rxdone will simply bounce the skb without handing an invalid packet over to mac80211. That said, it isn't necessary to set the flag. Just returning from the function is good enough.
>>
>> However, the check that Sergei does is not correct either. The real check that should be done is checking whether the skb has enough data to hold both rx_pkt_len bytes + the size of the rxd, which is 1 word (4 bytes). If only rx_pkt_len are left we don't have an rxd, and is the usb packet invalid as well.
>
> Yes, but there is also usb alignment on skb->len, so is better to use
> queue->data_size to validate rx_pkt (data) length IMHO.

Oh, well it's an (almost) equivalent test anyway, so I guess I don't care.

>
>>>> Obviously something is wrong,
>>>> so just resetting the rxdesc->size wouldn't be a solution right?
>>>
>>> rt2x00lib_rxdone has rxdesc->size check too, if ->size is bad it
>>> prints warning, and requeue skb.
>>>
>>> Perhaps this could be coded in some cleaner way (avoid double check),
>>> but basically this should do the job.
>>
>> As I mentioned above, simply bailing out if rt2800usb_fill_rxdone without doing anything (not even setting a flag) should do the trick and IMHO is the cleanest approach.
>
> IIRC this is basically what I proposed, except without setting
> rxdesc->size, unlikely() and rx_pkt_len == 0 check. It will work as
> rxdesc->size will be 0. But I think it would be better, if WARNING on
> rt2x00lib_rxdone() will print actual corrupted size instead of 0.
> Having unlikely is good too - this must be unlikely situation.

OK, I agree with the use of unlikely(). An rx_pkt_len of 0 doesn't seem to happen in practice, so testing for it seems superfluous, but may be providing some extra safety. Don't really care about that. I really don't think we should set rxdesc->size, as we cannot determine it. If we want to print the value, then do it in this function. Adding a hack to having it printed somewhere else doesn't seem right to me.
Also, it should be an error log message, not a WARNING. There's no need to have a stack trace as the buffer is filled by HW, not by some other function. So, the use of WARNING, with its stack dumping functionality is overkill.


>
> BTW: would be good to fix reason of that corruption if possible
> (as long this is not a H/W or F/W bug). But for now, let just
> stop kernel crashing. Printing WARNING on this situation will
> help to identify there is something wrong if someone will observe
> performance problems or similar.

I think this is a HW issue. As mentioned above, I believe a WARNING here is overkill, as we don't need the stack trace.

Anyway, Sergei, would you be able to modify the patch along the lines of the discussion?

---
Gertjan

2012-08-21 20:07:05

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On 21 aug. 2012, at 16:18, Stanislaw Gruszka <[email protected]> wrote:

> On Tue, Aug 21, 2012 at 03:39:41PM +0200, Ivo Van Doorn wrote:
>> On Tue, Aug 21, 2012 at 1:43 PM, Stanislaw Gruszka <[email protected]> wrote:
>>> On Mon, Aug 20, 2012 at 08:53:55PM +0400, Sergei Poselenov wrote:
>>>> On our system (ARM Cortex-M3 SOC running linux-2.6.33 with
>>>> compat-wireless-3.4-rc3-1 modules configured for rt2x00) frequent
>>> Please remove compat-wireless reference here and in the subject.
>>>
>>>> crashes were observed in rt2800usb module because of the invalid
>>>> length of the received packet (3392, 46920...). This patch adds
>>>> the sanity check on the packet legth. In case of the bad length,
>>>> mark the packet as with CRC error.
>>>>
>>>> The fix was also tested on the latest
>>>> compat-wireless-3.5.1-1-snpc.tar.bz2, applies cleanly.
>>>>
>>>> Cc: [email protected]
>>>> Signed-off-by: Sergei Poselenov <[email protected]>
>>>> ---
>>>> drivers/net/wireless/rt2x00/rt2800usb.c | 10 ++++++++--
>>>> 1 files changed, 8 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>>>> index 001735f..6776ec8 100644
>>>> --- a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>>>> +++ b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>>>> @@ -662,13 +662,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
>>>> rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
>>>>
>>>> /*
>>>> - * Remove the RXINFO structure from the sbk.
>>>> + * Remove the RXINFO structure from the skb.
>>>> */
>>>> skb_pull(entry->skb, RXINFO_DESC_SIZE);
>>> Would be great if you could post this as separate patch.
>>>
>>>> /*
>>>> - * FIXME: we need to check for rx_pkt_len validity
>>>> + * Check for rx_pkt_len validity, mark as failed.
>>>> */
>>>> + if (rx_pkt_len > entry->skb->len) {
>>>> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
>>>> + goto procrxwi;
>>>
>>> I would rather prefer something like
>>>
>>> if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
>>> /* Process error in rt2x00lib_rxdone() */
>>> rxdesc->size = rx_pkt_len;
>>> return;
>>> }
>>
>> But how do you know the packet is correct then?
> Non zero rx_pkt_len smaller than data_size indicate correct package.

To be honest, I think the original approach of Sergei is better. Not touching rxdesc beyond setting the flag will ensure that rt2x00lib_rxdone will simply bounce the skb without handing an invalid packet over to mac80211. That said, it isn't necessary to set the flag. Just returning from the function is good enough.

However, the check that Sergei does is not correct either. The real check that should be done is checking whether the skb has enough data to hold both rx_pkt_len bytes + the size of the rxd, which is 1 word (4 bytes). If only rx_pkt_len are left we don't have an rxd, and is the usb packet invalid as well.

>
>> Obviously something is wrong,
>> so just resetting the rxdesc->size wouldn't be a solution right?
>
> rt2x00lib_rxdone has rxdesc->size check too, if ->size is bad it
> prints warning, and requeue skb.
>
> Perhaps this could be coded in some cleaner way (avoid double check),
> but basically this should do the job.

As I mentioned above, simply bailing out if rt2800usb_fill_rxdone without doing anything (not even setting a flag) should do the trick and IMHO is the cleanest approach.

---
Gertjan

2012-08-26 13:19:18

by Sergei Poselenov

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

All,

On Wed, 2012-08-22 at 22:41 +0200, Gertjan van Wingerde wrote:
> Hi Stanislaw,
>
> On 22 aug. 2012, at 11:27, Stanislaw Gruszka <[email protected]> wrote:
>
> > On Tue, Aug 21, 2012 at 10:07:03PM +0200, Gertjan van Wingerde wrote:
> >>>>>> + if (rx_pkt_len > entry->skb->len) {
> >>>>>> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
> >>>>>> + goto procrxwi;
> >>>>>
> >>>>> I would rather prefer something like
> >>>>>
> >>>>> if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
> >>>>> /* Process error in rt2x00lib_rxdone() */
> >>>>> rxdesc->size = rx_pkt_len;
> >>>>> return;
> >>>>> }
> >>>>
> >>>> But how do you know the packet is correct then?
> >>> Non zero rx_pkt_len smaller than data_size indicate correct package.
> >>
> >> To be honest, I think the original approach of Sergei is better. Not touching rxdesc beyond setting the flag will ensure that rt2x00lib_rxdone will simply bounce the skb without handing an invalid packet over to mac80211. That said, it isn't necessary to set the flag. Just returning from the function is good enough.
> >>
> >> However, the check that Sergei does is not correct either. The real check that should be done is checking whether the skb has enough data to hold both rx_pkt_len bytes + the size of the rxd, which is 1 word (4 bytes). If only rx_pkt_len are left we don't have an rxd, and is the usb packet invalid as well.
> >
> > Yes, but there is also usb alignment on skb->len, so is better to use
> > queue->data_size to validate rx_pkt (data) length IMHO.
>
> Oh, well it's an (almost) equivalent test anyway, so I guess I don't care.
>
> >
> >>>> Obviously something is wrong,
> >>>> so just resetting the rxdesc->size wouldn't be a solution right?
> >>>
> >>> rt2x00lib_rxdone has rxdesc->size check too, if ->size is bad it
> >>> prints warning, and requeue skb.
> >>>
> >>> Perhaps this could be coded in some cleaner way (avoid double check),
> >>> but basically this should do the job.
> >>
> >> As I mentioned above, simply bailing out if rt2800usb_fill_rxdone without doing anything (not even setting a flag) should do the trick and IMHO is the cleanest approach.
> >
> > IIRC this is basically what I proposed, except without setting
> > rxdesc->size, unlikely() and rx_pkt_len == 0 check. It will work as
> > rxdesc->size will be 0. But I think it would be better, if WARNING on
> > rt2x00lib_rxdone() will print actual corrupted size instead of 0.
> > Having unlikely is good too - this must be unlikely situation.
>
> OK, I agree with the use of unlikely(). An rx_pkt_len of 0 doesn't seem to happen in practice, so testing for it seems superfluous, but may be providing some extra safety. Don't really care about that. I really don't think we should set rxdesc->size, as we cannot determine it. If we want to print the value, then do it in this function. Adding a hack to having it printed somewhere else doesn't seem right to me.

OK, I modified the check and changed WARNING() to ERROR() in
rt2x00lib_rxdone() as Stanislaw suggested.

Now the error messages looks like follows:
...
phy0 -> rt2800usb_fill_rxdone: Error - Bad frame length 12354, forcing to 0
phy0 -> rt2x00lib_rxdone: Error - Wrong frame size 0 max 3840.
...

OK to submit the final patch?

Regards,
Sergei

> Also, it should be an error log message, not a WARNING. There's no need to have a stack trace as the buffer is filled by HW, not by some other function. So, the use of WARNING, with its stack dumping functionality is overkill.
>
>
> >
> > BTW: would be good to fix reason of that corruption if possible
> > (as long this is not a H/W or F/W bug). But for now, let just
> > stop kernel crashing. Printing WARNING on this situation will
> > help to identify there is something wrong if someone will observe
> > performance problems or similar.
>
> I think this is a HW issue. As mentioned above, I believe a WARNING here is overkill, as we don't need the stack trace.
>
> Anyway, Sergei, would you be able to modify the patch along the lines of the discussion?
>
> ---
> Gertjan



2012-08-21 13:39:42

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On Tue, Aug 21, 2012 at 1:43 PM, Stanislaw Gruszka <[email protected]> wrote:
> On Mon, Aug 20, 2012 at 08:53:55PM +0400, Sergei Poselenov wrote:
>> On our system (ARM Cortex-M3 SOC running linux-2.6.33 with
>> compat-wireless-3.4-rc3-1 modules configured for rt2x00) frequent
> Please remove compat-wireless reference here and in the subject.
>
>> crashes were observed in rt2800usb module because of the invalid
>> length of the received packet (3392, 46920...). This patch adds
>> the sanity check on the packet legth. In case of the bad length,
>> mark the packet as with CRC error.
>>
>> The fix was also tested on the latest
>> compat-wireless-3.5.1-1-snpc.tar.bz2, applies cleanly.
>>
>> Cc: [email protected]
>> Signed-off-by: Sergei Poselenov <[email protected]>
>> ---
>> drivers/net/wireless/rt2x00/rt2800usb.c | 10 ++++++++--
>> 1 files changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>> index 001735f..6776ec8 100644
>> --- a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>> +++ b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
>> @@ -662,13 +662,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
>> rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
>>
>> /*
>> - * Remove the RXINFO structure from the sbk.
>> + * Remove the RXINFO structure from the skb.
>> */
>> skb_pull(entry->skb, RXINFO_DESC_SIZE);
> Would be great if you could post this as separate patch.
>
>> /*
>> - * FIXME: we need to check for rx_pkt_len validity
>> + * Check for rx_pkt_len validity, mark as failed.
>> */
>> + if (rx_pkt_len > entry->skb->len) {
>> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
>> + goto procrxwi;
>
> I would rather prefer something like
>
> if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
> /* Process error in rt2x00lib_rxdone() */
> rxdesc->size = rx_pkt_len;
> return;
> }

But how do you know the packet is correct then? Obviously something is wrong,
so just resetting the rxdesc->size wouldn't be a solution right?

Ivo

2012-08-27 08:23:38

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Fixed a typo

On Sun, Aug 26, 2012 at 3:56 PM, Sergei Poselenov
<[email protected]> wrote:
> Fixed a typo in the comment.
>
> Cc: [email protected]
> Signed-off-by: Sergei Poselenov <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

> ---
> drivers/net/wireless/rt2x00/rt2800usb.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
> index 6cf3365..f8085b2 100644
> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -662,7 +662,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
> rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
>
> /*
> - * Remove the RXINFO structure from the sbk.
> + * Remove the RXINFO structure from the skb.
> */
> skb_pull(entry->skb, RXINFO_DESC_SIZE);
>
> --
> 1.7.4.4
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2012-08-21 11:44:01

by Stanislaw Gruszka

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Added rx packet length validity check

On Mon, Aug 20, 2012 at 08:53:55PM +0400, Sergei Poselenov wrote:
> On our system (ARM Cortex-M3 SOC running linux-2.6.33 with
> compat-wireless-3.4-rc3-1 modules configured for rt2x00) frequent
Please remove compat-wireless reference here and in the subject.

> crashes were observed in rt2800usb module because of the invalid
> length of the received packet (3392, 46920...). This patch adds
> the sanity check on the packet legth. In case of the bad length,
> mark the packet as with CRC error.
>
> The fix was also tested on the latest
> compat-wireless-3.5.1-1-snpc.tar.bz2, applies cleanly.
>
> Cc: [email protected]
> Signed-off-by: Sergei Poselenov <[email protected]>
> ---
> drivers/net/wireless/rt2x00/rt2800usb.c | 10 ++++++++--
> 1 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> index 001735f..6776ec8 100644
> --- a/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/usbwifi/compat-wireless-3.4-rc3-1/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -662,13 +662,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
> rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);
>
> /*
> - * Remove the RXINFO structure from the sbk.
> + * Remove the RXINFO structure from the skb.
> */
> skb_pull(entry->skb, RXINFO_DESC_SIZE);
Would be great if you could post this as separate patch.

> /*
> - * FIXME: we need to check for rx_pkt_len validity
> + * Check for rx_pkt_len validity, mark as failed.
> */
> + if (rx_pkt_len > entry->skb->len) {
> + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
> + goto procrxwi;

I would rather prefer something like

if (unlikely(rx_pkt_len == 0 || rx_pkt_len > entry->queue->data_size)) {
/* Process error in rt2x00lib_rxdone() */
rxdesc->size = rx_pkt_len;
return;
}

Thanks
Stanislaw


2012-08-26 13:56:54

by Sergei Poselenov

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH] compat-wireless:rt2800usb: Fixed a typo

Fixed a typo in the comment.

Cc: [email protected]
Signed-off-by: Sergei Poselenov <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6cf3365..f8085b2 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -662,7 +662,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
rx_pkt_len = rt2x00_get_field32(word, RXINFO_W0_USB_DMA_RX_PKT_LEN);

/*
- * Remove the RXINFO structure from the sbk.
+ * Remove the RXINFO structure from the skb.
*/
skb_pull(entry->skb, RXINFO_DESC_SIZE);

--
1.7.4.4




2012-09-02 20:35:05

by Ivo Van Doorn

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH V2]: rt2800usb: Added rx packet length validity check

On Sun, Sep 2, 2012 at 11:14 AM, Sergei Poselenov
<[email protected]> wrote:
> On our system (ARM Cortex-M3 SOC running linux-2.6.33)
> frequent crashes were observed in the rt2800usb module
> because of the invalid length of the received packet (3392,
> 46920...). This patch adds the sanity check on the packet
> legth. Also, changed WARNING to ERROR in rt2x00lib_rxdone()
> so that the bad packet condition would be noticed.
>
> The fix was tested on the latest compat-wireless-3.5.1-1-snpc.
>
> Cc: [email protected]
> Signed-off-by: Sergei Poselenov <[email protected]>

Acked-by: Ivo van Doorn <[email protected]>

> ---
> drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++-
> drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +-
> 2 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
> index f8085b2..48df102 100644
> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
> skb_pull(entry->skb, RXINFO_DESC_SIZE);
>
> /*
> - * FIXME: we need to check for rx_pkt_len validity
> + * Check for rx_pkt_len validity. Return if invalid, leaving
> + * rxdesc->size zeroed out by the upper level.
> */
> + if (unlikely(rx_pkt_len == 0 ||
> + rx_pkt_len > entry->queue->data_size)) {
> + ERROR(entry->queue->rt2x00dev,
> + "Bad frame size %d, forcing to 0\n", rx_pkt_len);
> + return;
> + }
> +
> rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
>
> /*
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index a59048f..10cf672 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
> */
> if (unlikely(rxdesc.size == 0 ||
> rxdesc.size > entry->queue->data_size)) {
> - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
> + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
> rxdesc.size, entry->queue->data_size);
> dev_kfree_skb(entry->skb);
> goto renew_skb;
> --
> 1.7.4.4
>
>
>

2012-09-02 09:14:40

by Sergei Poselenov

[permalink] [raw]
Subject: Re: [rt2x00-users] [PATCH V2]: rt2800usb: Added rx packet length validity check

On our system (ARM Cortex-M3 SOC running linux-2.6.33)
frequent crashes were observed in the rt2800usb module
because of the invalid length of the received packet (3392,
46920...). This patch adds the sanity check on the packet
legth. Also, changed WARNING to ERROR in rt2x00lib_rxdone()
so that the bad packet condition would be noticed.

The fix was tested on the latest compat-wireless-3.5.1-1-snpc.

Cc: [email protected]
Signed-off-by: Sergei Poselenov <[email protected]>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 10 +++++++++-
drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +-
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f8085b2..48df102 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
skb_pull(entry->skb, RXINFO_DESC_SIZE);

/*
- * FIXME: we need to check for rx_pkt_len validity
+ * Check for rx_pkt_len validity. Return if invalid, leaving
+ * rxdesc->size zeroed out by the upper level.
*/
+ if (unlikely(rx_pkt_len == 0 ||
+ rx_pkt_len > entry->queue->data_size)) {
+ ERROR(entry->queue->rt2x00dev,
+ "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+ return;
+ }
+
rxd = (__le32 *)(entry->skb->data + rx_pkt_len);

/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index a59048f..10cf672 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
*/
if (unlikely(rxdesc.size == 0 ||
rxdesc.size > entry->queue->data_size)) {
- WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+ ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
rxdesc.size, entry->queue->data_size);
dev_kfree_skb(entry->skb);
goto renew_skb;
--
1.7.4.4