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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:30:11 +0000 (10:30 +0200)
[ Upstream commit fcfe1b5e162bf473c1d47760962cec8523c00466 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/tx.c

index 917ea20c026b4844185b280fd124a3028e1a72e4..ef11043d1a4a7f1406f1917cd5de22797bfa9b8e 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 6b8c9dc80542554f19a2232f4080bb5cd9b79da8..ccaf9a31fbc45e88489d19823909c628b779390a 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)