Skip to content

Commit

Permalink
mt76: mt7615: fix skb use-after-free on mac reset
Browse files Browse the repository at this point in the history
commit b5cd1fd upstream.

When clearing all existing pending tx slots, mt76_tx_complete_skb needs to
be used to free the skbs, to ensure that they are cleared from the status
list as well.

Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
nbd168 authored and gregkh committed Nov 17, 2021
1 parent 7761ffe commit 6979b6f
Showing 1 changed file with 23 additions and 22 deletions.
45 changes: 23 additions & 22 deletions drivers/net/wireless/mediatek/mt76/mt7615/mac.c
Expand Up @@ -1494,32 +1494,41 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
}

static void
mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
__le32 *txwi_data;
u32 val;
u8 wcid;

trace_mac_tx_free(dev, token);
txwi = mt76_token_put(mdev, token);
if (!txwi)
return;
mt7615_txp_skb_unmap(mdev, txwi);
if (!txwi->skb)
goto out;

txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi);
val = le32_to_cpu(txwi_data[1]);
wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val);
mt76_tx_complete_skb(mdev, wcid, txwi->skb);

mt7615_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
mt76_tx_complete_skb(mdev, wcid, txwi->skb);
txwi->skb = NULL;
}

out:
txwi->skb = NULL;
mt76_put_txwi(mdev, txwi);
}

static void
mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;

trace_mac_tx_free(dev, token);
txwi = mt76_token_put(mdev, token);
if (!txwi)
return;

mt7615_txwi_free(dev, txwi);
}

static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
{
struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data;
Expand Down Expand Up @@ -2026,16 +2035,8 @@ void mt7615_tx_token_put(struct mt7615_dev *dev)
int id;

spin_lock_bh(&dev->mt76.token_lock);
idr_for_each_entry(&dev->mt76.token, txwi, id) {
mt7615_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb) {
struct ieee80211_hw *hw;

hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
ieee80211_free_txskb(hw, txwi->skb);
}
mt76_put_txwi(&dev->mt76, txwi);
}
idr_for_each_entry(&dev->mt76.token, txwi, id)
mt7615_txwi_free(dev, txwi);
spin_unlock_bh(&dev->mt76.token_lock);
idr_destroy(&dev->mt76.token);
}
Expand Down

0 comments on commit 6979b6f

Please sign in to comment.