git: 6ff264d47f99 - stable/15 - ath: fix ath_buf leak if ath_tx_tag_crypto() returns an error
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Oct 2026 17:38:58 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=6ff264d47f9970a1c6be03b48374110b56ef4ba5
commit 6ff264d47f9970a1c6be03b48374110b56ef4ba5
Author: Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-10-01 02:21:01 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-30 17:37:46 +0000
ath: fix ath_buf leak if ath_tx_tag_crypto() returns an error
If ath_tx_tag_crypto() returns an error, then ath_tx_normal_setup()
should consume the mbuf and return an error, so the caller knows to
free the ath_buf. But it wasn't.
This fixes issues I've seen locally where a an AP VAP constantly hits
error conditions (due to other RF/PHY/MAC chipset issues which I haven't
yet figured out) and encryption fails because the station goes away
whilst something's being queued.
Locally tested:
* AR9380, AP mode (2G HT20, 5G HT20, 5G HT40)
(cherry picked from commit f7aad20db59210a4411559d07976a48809b3b0a7)
---
sys/dev/ath/if_ath_tx.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index 1559b66a7c7d..20a205ddebbf 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -971,6 +971,12 @@ ath_legacy_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_handoff_hw(sc, txq, bf);
}
+/*
+ * Setup a frame for encryption.
+ *
+ * If this fails, then an non-zero error is returned. The mbuf
+ * must be freed by the caller.
+ */
static int
ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen,
@@ -1547,6 +1553,10 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq,
*
* Note that this may cause the mbuf to be reallocated, so
* m0 may not be valid.
+ *
+ * If there's a problem then the mbuf is freed and an error
+ * is returned. The ath_buf then needs to be freed by the
+ * caller.
*/
static int
ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
@@ -2069,9 +2079,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
/* This also sets up the DMA map; crypto; frame parameters, etc */
r = ath_tx_normal_setup(sc, ni, bf, m0, txq);
-
if (r != 0)
- goto done;
+ return (r);
/* At this point m0 could have changed! */
m0 = bf->bf_m;
@@ -2128,7 +2137,6 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
ath_tx_leak_count_update(sc, tid, bf);
ath_tx_xmit_normal(sc, txq, bf);
#endif
-done:
return 0;
}