From: Felix Fietkau <nbd@openwrt.org>
Date: Sat, 12 May 2012 17:40:53 +0000 (+0000)
Subject: ath9k: fix a rare use-after-free bug
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=373d489a2c45e47ffa301c574d1d2021ed25ace2;p=openwrt%2Fstaging%2Fdangole.git

ath9k: fix a rare use-after-free bug

SVN-Revision: 31690
---

diff --git a/package/mac80211/patches/561-ath9k_fix_tid_buffer_free.patch b/package/mac80211/patches/561-ath9k_fix_tid_buffer_free.patch
new file mode 100644
index 0000000000..fd0bfa9f17
--- /dev/null
+++ b/package/mac80211/patches/561-ath9k_fix_tid_buffer_free.patch
@@ -0,0 +1,67 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -64,7 +64,8 @@ static void ath_tx_update_baw(struct ath
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ 					   struct ath_txq *txq,
+ 					   struct ath_atx_tid *tid,
+-					   struct sk_buff *skb);
++					   struct sk_buff *skb,
++					   bool dequeue);
+ 
+ enum {
+ 	MCS_HT20,
+@@ -821,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+ 		fi = get_frame_info(skb);
+ 		bf = fi->bf;
+ 		if (!fi->bf)
+-			bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++			bf = ath_tx_setup_buffer(sc, txq, tid, skb, true);
+ 
+ 		if (!bf)
+ 			continue;
+@@ -1737,7 +1738,7 @@ static void ath_tx_send_ampdu(struct ath
+ 		return;
+ 	}
+ 
+-	bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++	bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+ 	if (!bf)
+ 		return;
+ 
+@@ -1766,7 +1767,7 @@ static void ath_tx_send_normal(struct at
+ 
+ 	bf = fi->bf;
+ 	if (!bf)
+-		bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++		bf = ath_tx_setup_buffer(sc, txq, tid, skb, false);
+ 
+ 	if (!bf)
+ 		return;
+@@ -1827,7 +1828,8 @@ u8 ath_txchainmask_reduction(struct ath_
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ 					   struct ath_txq *txq,
+ 					   struct ath_atx_tid *tid,
+-					   struct sk_buff *skb)
++					   struct sk_buff *skb,
++					   bool dequeue)
+ {
+ 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ 	struct ath_frame_info *fi = get_frame_info(skb);
+@@ -1876,6 +1878,8 @@ static struct ath_buf *ath_tx_setup_buff
+ 	return bf;
+ 
+ error:
++	if (dequeue)
++		__skb_unlink(skb, &tid->buf_q);
+ 	dev_kfree_skb_any(skb);
+ 	return NULL;
+ }
+@@ -1895,7 +1899,7 @@ static void ath_tx_start_dma(struct ath_
+ 		 */
+ 		ath_tx_send_ampdu(sc, tid, skb, txctl);
+ 	} else {
+-		bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++		bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false);
+ 		if (!bf)
+ 			return;
+