lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 086/917] mt76: mt7615: fix skb use-after-free on mac reset
    Date
    From: Felix Fietkau <nbd@nbd.name>

    commit b5cd1fd6043bbb7c5810067b5f93f3016bfd8a6f 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>
    ---
    drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 45 ++++++++++++------------
    1 file changed, 23 insertions(+), 22 deletions(-)

    --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
    +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
    @@ -1494,32 +1494,41 @@ out:
    }

    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;
    @@ -2026,16 +2035,8 @@ void mt7615_tx_token_put(struct mt7615_d
    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);
    }

    \
     
     \ /
      Last update: 2021-11-16 00:32    [W:4.038 / U:0.236 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site