mt76: fix tx status related use-after-free race on station removal
authorFelix Fietkau <nbd@nbd.name>
Sat, 23 Apr 2022 05:01:18 +0000 (07:01 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 13 May 2022 07:39:35 +0000 (09:39 +0200)
There is a small race window where ongoing tx activity can lead to a skb
getting added to the status tracking idr after that idr has already been
cleaned up, which will keep the wcid linked in the status poll list.
Fix this by only adding status skbs if the wcid pointer is still assigned
in dev->wcid, which gets cleared early by mt76_sta_pre_rcu_remove

Fixes: bd1e3e7b693c ("mt76: introduce packet_id idr")
Tested-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/tx.c

index 2dd3ebd1863f37d0f8666a631e239ec75e269350..8a2fedbb1451cc91cb362a2afe6e024eccc760da 100644 (file)
@@ -1381,7 +1381,9 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
 
        mutex_lock(&dev->mutex);
+       spin_lock_bh(&dev->status_lock);
        rcu_assign_pointer(dev->wcid[wcid->idx], NULL);
+       spin_unlock_bh(&dev->status_lock);
        mutex_unlock(&dev->mutex);
 }
 EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
index c3be62f58b62b775a3b5d92afb10e7683fe1dd65..d5a8456c108be533e880762fea7fe4e6716e73dd 100644 (file)
@@ -120,7 +120,7 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid,
 
        memset(cb, 0, sizeof(*cb));
 
-       if (!wcid)
+       if (!wcid || !rcu_access_pointer(dev->wcid[wcid->idx]))
                return MT_PACKET_ID_NO_ACK;
 
        if (info->flags & IEEE80211_TX_CTL_NO_ACK)