wifi: mt76: mt792x: fix use-after-free in mt76_rx_poll_complete
Subsystems (2)
PATCH v6 1/1 wifi: mt76: mt792x: fix use-after-free in mt76_rx_poll_complete
From: Eason Lai <[email protected]>
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]>
---
v2: fix mt76x02 build errors
v3: fix mt76x02 build error due to variable set but not used
v4: fix use-after-free in MLO
v5: correct commit message
v6: correct commit message
--- .../net/wireless/mediatek/mt76/mt7925/main.c | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +35 -1
@@ -2410,6 +2410,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,
@@ -2422,7 +2456,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 )
Signature · 1 line
2.45.2