summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-05-12 17:40:53 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-05-12 17:40:53 +0000
commitb08f604d4a997447ba7911f6bb067298b42ef47d (patch)
treef21e761c94f2af26b49846a11eeb0c36ef04478a
parent69bd63a3db67acbc7bce63884fd2a7d5c082e4c0 (diff)
ath9k: fix a rare use-after-free bug
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31690 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--package/mac80211/patches/561-ath9k_fix_tid_buffer_free.patch67
1 files changed, 67 insertions, 0 deletions
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 000000000..fd0bfa9f1
--- /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;
+