summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEason Lai <Eason.Lai@mediatek.com>2026-07-01 09:06:54 +0800
committerFelix Fietkau <nbd@nbd.name>2026-07-31 12:25:38 +0000
commit217f9e7bb02558759be9d9ecfe532e9708741c50 (patch)
tree6397d5b9039333fb6d28db0ea66b4cbeb09fe680
parent3c004f73d68b415d231189b75a3cff1582a17e90 (diff)
wifi: mt76: mt792x: fix use-after-free in mt76_rx_poll_complete
A use-after-free issue occurs in mt76_rx_poll_complete due to a race condition. The STA has already been removed, but the rx_status still had a pointer to the wcid in the STA. Set the links' wcid pointers to be NULL for a MLD in mt7925_sta_pre_rcu_remove() BUG: KASAN: invalid-access in mt76_rx_poll_complete+0x280/0x470 Call trace: dump_backtrace+0xec/0x128 show_stack+0x18/0x28 dump_stack_lvl+0x40/0xc8 print_report+0x1b8/0x710 kasan_report+0xe0/0x144 do_bad_area+0x120/0x260 do_tag_check_fault+0x20/0x34 do_mem_abort+0x54/0xa8 el1_abort+0x3c/0x5c el1h_64_sync_handler+0x40/0xcc el1h_64_sync+0x7c/0x80 mt76_rx_poll_complete+0x280/0x470 mt76_dma_rx_poll+0x114/0x51c mt792x_poll_rx+0x60/0xf8 napi_threaded_poll_loop+0xe0/0x450 napi_threaded_poll+0x80/0x9c kthread+0x11c/0x158 ret_from_fork+0x10/0x20 Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") Signed-off-by: Eason Lai <Eason.Lai@mediatek.com> Link: https://patch.msgid.link/20260701010654.956863-1-eason.lai@mediatek.com Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7925/main.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 6be5b60b9bac..abb56f6fea77 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -2661,6 +2661,40 @@ static int mt7925_nan_peer_sched_changed(struct ieee80211_hw *hw,
return err;
}
+static void mt7925_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct mt76_phy *phy = hw->priv;
+ struct mt76_dev *dev = phy->dev;
+ struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
+
+ mutex_lock(&dev->mutex);
+ spin_lock_bh(&dev->status_lock);
+
+ if (ieee80211_vif_is_mld(vif)) {
+ struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
+ struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+ unsigned long valid = mvif->valid_links;
+ struct mt792x_link_sta *mlink;
+ unsigned int link_id;
+
+ for_each_set_bit(link_id, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
+ mlink = mt792x_sta_to_link(msta, link_id);
+ if (!mlink || !mlink->wcid.sta)
+ continue;
+ if (mlink->wcid.idx < ARRAY_SIZE(dev->wcid))
+ rcu_assign_pointer(dev->wcid[mlink->wcid.idx],
+ NULL);
+ }
+ } else {
+ rcu_assign_pointer(dev->wcid[wcid->idx], NULL);
+ }
+
+ spin_unlock_bh(&dev->status_lock);
+ mutex_unlock(&dev->mutex);
+}
+
const struct ieee80211_ops mt7925_ops = {
.tx = mt792x_tx,
.start = mt7925_start,
@@ -2673,7 +2707,7 @@ const struct ieee80211_ops mt7925_ops = {
.start_ap = mt7925_start_ap,
.stop_ap = mt7925_stop_ap,
.sta_state = mt76_sta_state,
- .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
+ .sta_pre_rcu_remove = mt7925_sta_pre_rcu_remove,
.set_key = mt7925_set_key,
.sta_set_decap_offload = mt7925_sta_set_decap_offload,
#if IS_ENABLED(CONFIG_IPV6)