ath9k: fix a potential buffer leak in the STA teardown path

It looks like it might be possible for a TID to be paused, while still
holding some queued buffers, however ath_tx_node_cleanup currently only
iterates over active TIDs.
Fix this by always checking every allocated TID for the STA that is being
cleaned up.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Felix Fietkau 2010-07-07 19:42:08 +02:00 committed by John W. Linville
parent 60ea385ff2
commit 2b40994cab

View file

@ -2430,37 +2430,37 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
{
int i;
struct ath_atx_ac *ac, *ac_tmp;
struct ath_atx_tid *tid, *tid_tmp;
struct ath_atx_ac *ac;
struct ath_atx_tid *tid;
struct ath_txq *txq;
int i, tidno;
for (tidno = 0, tid = &an->tid[tidno];
tidno < WME_NUM_TID; tidno++, tid++) {
i = tid->ac->qnum;
if (!ATH_TXQ_SETUP(sc, i))
continue;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
txq = &sc->tx.txq[i];
ac = tid->ac;
spin_lock_bh(&txq->axq_lock);
list_for_each_entry_safe(ac,
ac_tmp, &txq->axq_acq, list) {
tid = list_first_entry(&ac->tid_q,
struct ath_atx_tid, list);
if (tid && tid->an != an)
continue;
list_del(&ac->list);
ac->sched = false;
list_for_each_entry_safe(tid,
tid_tmp, &ac->tid_q, list) {
if (tid->sched) {
list_del(&tid->list);
tid->sched = false;
}
if (ac->sched) {
list_del(&ac->list);
tid->ac->sched = false;
}
ath_tid_drain(sc, txq, tid);
tid->state &= ~AGGR_ADDBA_COMPLETE;
tid->state &= ~AGGR_CLEANUP;
}
}
spin_unlock_bh(&txq->axq_lock);
}
}
}