diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-05-24 08:32:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-29 13:45:22 -0400 |
commit | 81357a281dcc454841532c46b30e6f2ba12b73ea (patch) | |
tree | a5e0bcf8b7b79434e8242695c2d6f8b24e4dda7d /drivers/net/wireless/ath | |
parent | ceea2a51969f8b578777c99ec2718021427770c3 (diff) |
ath9k: fix a use-after-free-bug when ath_tx_setup_buffer() fails
ath_tx_setup_buffer() can fail if there is no ath_buf left, or if mapping DMA
failed. In this case it frees the skb passed to it.
If ath_tx_setup_buffer is called from ath_tx_form_aggr, the skb is still
linked into the tid buffer list and must be dequeued before being released.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@vger.kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 23eaa1b26ebe..d59dd01d6cde 100644 --- 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_softc *sc, struct ath_atx_tid *tid, | |||
64 | static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, | 64 | static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, |
65 | struct ath_txq *txq, | 65 | struct ath_txq *txq, |
66 | struct ath_atx_tid *tid, | 66 | struct ath_atx_tid *tid, |
67 | struct sk_buff *skb); | 67 | struct sk_buff *skb, |
68 | bool dequeue); | ||
68 | 69 | ||
69 | enum { | 70 | enum { |
70 | MCS_HT20, | 71 | MCS_HT20, |
@@ -811,7 +812,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
811 | fi = get_frame_info(skb); | 812 | fi = get_frame_info(skb); |
812 | bf = fi->bf; | 813 | bf = fi->bf; |
813 | if (!fi->bf) | 814 | if (!fi->bf) |
814 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 815 | bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); |
815 | 816 | ||
816 | if (!bf) | 817 | if (!bf) |
817 | continue; | 818 | continue; |
@@ -1726,7 +1727,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1726 | return; | 1727 | return; |
1727 | } | 1728 | } |
1728 | 1729 | ||
1729 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | 1730 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); |
1730 | if (!bf) | 1731 | if (!bf) |
1731 | return; | 1732 | return; |
1732 | 1733 | ||
@@ -1753,7 +1754,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
1753 | 1754 | ||
1754 | bf = fi->bf; | 1755 | bf = fi->bf; |
1755 | if (!bf) | 1756 | if (!bf) |
1756 | bf = ath_tx_setup_buffer(sc, txq, tid, skb); | 1757 | bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); |
1757 | 1758 | ||
1758 | if (!bf) | 1759 | if (!bf) |
1759 | return; | 1760 | return; |
@@ -1814,7 +1815,8 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) | |||
1814 | static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, | 1815 | static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, |
1815 | struct ath_txq *txq, | 1816 | struct ath_txq *txq, |
1816 | struct ath_atx_tid *tid, | 1817 | struct ath_atx_tid *tid, |
1817 | struct sk_buff *skb) | 1818 | struct sk_buff *skb, |
1819 | bool dequeue) | ||
1818 | { | 1820 | { |
1819 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1821 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1820 | struct ath_frame_info *fi = get_frame_info(skb); | 1822 | struct ath_frame_info *fi = get_frame_info(skb); |
@@ -1863,6 +1865,8 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, | |||
1863 | return bf; | 1865 | return bf; |
1864 | 1866 | ||
1865 | error: | 1867 | error: |
1868 | if (dequeue) | ||
1869 | __skb_unlink(skb, &tid->buf_q); | ||
1866 | dev_kfree_skb_any(skb); | 1870 | dev_kfree_skb_any(skb); |
1867 | return NULL; | 1871 | return NULL; |
1868 | } | 1872 | } |
@@ -1893,7 +1897,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, | |||
1893 | */ | 1897 | */ |
1894 | ath_tx_send_ampdu(sc, tid, skb, txctl); | 1898 | ath_tx_send_ampdu(sc, tid, skb, txctl); |
1895 | } else { | 1899 | } else { |
1896 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); | 1900 | bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); |
1897 | if (!bf) | 1901 | if (!bf) |
1898 | return; | 1902 | return; |
1899 | 1903 | ||