Search Linux Wireless

Re: [PATCH 1/3] rt2x00: fix crash in rt2800usb_write_tx_desc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 10, 2011 at 3:32 PM, Stanislaw Gruszka <sgruszka@xxxxxxxxxx> wrote:
> Patch should fix this oops:
>
> BUG: unable to handle kernel NULL pointer dereference at 000000a0
> IP: [<f8e06078>] rt2800usb_write_tx_desc+0x18/0xc0 [rt2800usb]
> *pdpt = 000000002408c001 *pde = 0000000024079067 *pte = 0000000000000000
> Oops: 0000 [#1] SMP
> EIP: 0060:[<f8e06078>] EFLAGS: 00010282 CPU: 0
> EIP is at rt2800usb_write_tx_desc+0x18/0xc0 [rt2800usb]
> EAX: 00000035 EBX: ef2bef10 ECX: 00000000 EDX: d40958a0
> ESI: ef1865f8 EDI: ef1865f8 EBP: d4095878 ESP: d409585c
>  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
> Call Trace:
>  [<f8da5e85>] rt2x00queue_write_tx_frame+0x155/0x300 [rt2x00lib]
>  [<f8da424c>] rt2x00mac_tx+0x7c/0x370 [rt2x00lib]
>  [<c04882b2>] ? mark_held_locks+0x62/0x90
>  [<c081f645>] ? _raw_spin_unlock_irqrestore+0x35/0x60
>  [<c04884ba>] ? trace_hardirqs_on_caller+0x5a/0x170
>  [<c04885db>] ? trace_hardirqs_on+0xb/0x10
>  [<f8d618ac>] __ieee80211_tx+0x5c/0x1e0 [mac80211]
>  [<f8d631fc>] ieee80211_tx+0xbc/0xe0 [mac80211]
>  [<f8d63163>] ? ieee80211_tx+0x23/0xe0 [mac80211]
>  [<f8d632e1>] ieee80211_xmit+0xc1/0x200 [mac80211]
>  [<f8d63220>] ? ieee80211_tx+0xe0/0xe0 [mac80211]
>  [<c0487d45>] ? lock_release_holdtime+0x35/0x1b0
>  [<f8d63986>] ? ieee80211_subif_start_xmit+0x446/0x5f0 [mac80211]
>  [<f8d637dd>] ieee80211_subif_start_xmit+0x29d/0x5f0 [mac80211]
>  [<f8d63924>] ? ieee80211_subif_start_xmit+0x3e4/0x5f0 [mac80211]
>  [<c0760188>] ? sock_setsockopt+0x6a8/0x6f0
>  [<c0760000>] ? sock_setsockopt+0x520/0x6f0
>  [<c076daef>] dev_hard_start_xmit+0x2ef/0x650
>
> Oops might happen because we perform parallel putting new entries in a
> queue (rt2x00queue_write_tx_frame()) and removing entries after
> finishing transmitting (rt2800usb_work_txdone()). There are cases when
> _txdone may process an entry that was not fully send and nullify
> entry->skb .
>
> To fix check in _txdone if entry has flags that indicate pending
> transmission and wait until flags get cleared.
>
> Reported-by: Justin Piszcz <jpiszcz@xxxxxxxxxxxxxxx>
> Cc: stable@xxxxxxxxxx
> Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx>

Acked-by: Ivo van Doorn <IvDoorn@xxxxxxxxx>

> ---
>  drivers/net/wireless/rt2x00/rt2800usb.c |   13 ++++++++++++-
>  1 files changed, 12 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
> index 5075593..d137812 100644
> --- a/drivers/net/wireless/rt2x00/rt2800usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2800usb.c
> @@ -464,6 +464,15 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
>        int wcid, ack, pid;
>        int tx_wcid, tx_ack, tx_pid;
>
> +       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
> +           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
> +               WARNING(entry->queue->rt2x00dev,
> +                       "Data pending for entry %u in queue %u\n",
> +                       entry->entry_idx, entry->queue->qid);
> +               cond_resched();
> +               return false;
> +       }
> +
>        wcid    = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
>        ack     = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
>        pid     = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
> @@ -558,8 +567,10 @@ static void rt2800usb_work_txdone(struct work_struct *work)
>                while (!rt2x00queue_empty(queue)) {
>                        entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
>
> -                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
> +                       if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
> +                           !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
>                                break;
> +
>                        if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
>                                rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
>                        else if (rt2x00queue_status_timeout(entry))
> --
> 1.7.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux