mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
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:
+35
-1
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user