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 <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Eason Lai
2026-07-21 15:33:43 +02:00
committed by Felix Fietkau
parent 763e99aadb
commit 491d786c1b
+35 -1
View File
@@ -2484,6 +2484,40 @@ static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw *hw,
}
}
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,
@@ -2496,7 +2530,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)