From 416fbdff2137e8d8cc8f23f517bee3a26b11526f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 11 Aug 2009 13:10:33 -0700 Subject: [PATCH 1/2] mac80211: fix panic when splicing unprepared TIDs We splice skbs from the pending queue for a TID onto the local pending queue when tearing down a block ack request. This is not necessary unless we actually have received a request to start a block ack request (rate control, for example). If we never received that request we should not be splicing the tid pending queue as it would be null, causing a panic. Not sure yet how exactly we allowed through a call when the tid state does not have at least HT_ADDBA_REQUESTED_MSK set, that will require some further review as it is not quite obvious. For more information see the bug report: http://bugzilla.kernel.org/show_bug.cgi?id=13922 This fixes this oops: BUG: unable to handle kernel NULL pointer dereference at 00000030 IP: [] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] *pdpt = 0000000002d1e001 *pde = 0000000000000000 Thread overran stack, or stack corrupted Oops: 0000 [#1] SMP last sysfs file: /sys/module/aes_generic/initstate Modules linked in: Pid: 0, comm: swapper Not tainted (2.6.31-rc5-wl #2) Dell DV051 EIP: 0060:[] EFLAGS: 00010292 CPU: 0 EIP is at ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] EAX: 00000030 EBX: 0000004c ECX: 00000003 EDX: 00000000 ESI: c1c98000 EDI: f745a1c0 EBP: c076be58 ESP: c076be38 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process swapper (pid: 0, ti=c076a000 task=c0709160 task.ti=c076a000) Stack: Call Trace: [] ? ieee80211_stop_tx_ba_cb+0xab/0x150 [mac80211] [] ? ieee80211_tasklet_handler+0xce/0x110 [mac80211] [] ? net_rx_action+0xef/0x1d0 [] ? tasklet_action+0x58/0xc0 [] ? __do_softirq+0xc2/0x190 [] ? handle_IRQ_event+0x58/0x140 [] ? ack_apic_level+0x7e/0x270 [] ? do_softirq+0x3d/0x40 [] ? irq_exit+0x65/0x90 [] ? do_IRQ+0x4f/0xc0 [] ? irq_exit+0x7d/0x90 [] ? smp_apic_timer_interrupt+0x57/0x90 [] ? common_interrupt+0x29/0x30 [] ? mwait_idle+0xbe/0x100 [] ? cpu_idle+0x52/0x90 [] ? rest_init+0x55/0x60 [] ? start_kernel+0x315/0x37d [] ? unknown_bootoption+0x0/0x1f9 [] ? i386_start_kernel+0x79/0x81 Code: EIP: [] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] SS:ESP 0068:c076be38 CR2: 0000000000000030 Cc: stable@kernel.org Testedy-by: Jack Lau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9e5762ad307d..a24e59816b93 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -381,6 +381,14 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local, &local->hw, queue, IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK)) + return; + + if (WARN(!sta->ampdu_mlme.tid_tx[tid], + "TID %d gone but expected when splicing aggregates from" + "the pending queue\n", tid)) + return; + if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { spin_lock_irqsave(&local->queue_stop_reason_lock, flags); /* mark queue as pending, it is stopped already */ From 6b26dead3ce97d016b57724b01974d5ca5c84bd5 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 4 Aug 2009 17:48:16 -0400 Subject: [PATCH 2/2] rt2x00: fix memory corruption in rf cache, add a sanity check Change rt2x00_rf_read() and rt2x00_rf_write() to subtract 1 from the rf register number. This is needed because the rf registers are enumerated starting with one. The size of the rf register cache is just enough to hold all registers, so writing to the highest register was corrupting memory. Add a check to make sure that the rf register number is valid. Signed-off-by: Pavel Roskin Cc: stable@kernel.org Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a498dde024e1..49c9e2c1433d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -849,13 +849,15 @@ struct rt2x00_dev { static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 *data) { - *data = rt2x00dev->rf[word]; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + *data = rt2x00dev->rf[word - 1]; } static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, u32 data) { - rt2x00dev->rf[word] = data; + BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); + rt2x00dev->rf[word - 1] = data; } /*