From d3b243c548006cd289fff659798e33fc0b27ecc1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 4 Aug 2026 08:51:11 +0200 Subject: [PATCH] wifi: mt76: check a remain-on-channel still belongs to the interface roc_phy on the shared per-interface data names the phy of the one started last, which may have ended or moved on to another interface since. Both users take it at face value: an interface going away aborts whatever it names, and cancelling one for an interface acts on it without asking whose it is. Aborting a stranger's leaves the interface's own outstanding one behind, and its work then runs once the interface is gone, tearing the link down through the freed bss_conf: Unable to handle kernel paging request at virtual address 000043c218ce0afd Workqueue: phy0 mt76_roc_complete_work [mt76] pc : mt76_connac_mcu_sta_basic_tlv+0xdc/0x260 [mt76_connac_lib] Call trace: mt76_connac_mcu_sta_basic_tlv mt7996_mcu_add_sta mt7996_vif_link_destroy mt7996_vif_link_remove mt76_put_vif_phy_link mt76_roc_complete mt76_roc_complete_work Check the interface before acting on it in both places. Signed-off-by: Felix Fietkau --- channel.c | 2 +- mac80211.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/channel.c b/channel.c index 28ad7bca..1d263567 100644 --- a/channel.c +++ b/channel.c @@ -423,7 +423,7 @@ int mt76_cancel_remain_on_channel(struct ieee80211_hw *hw, struct mt76_vif_data *mvif = mlink->mvif; struct mt76_phy *phy = mvif->roc_phy; - if (!phy) + if (!phy || phy->roc_vif != vif) return 0; mt76_abort_roc(phy); diff --git a/mac80211.c b/mac80211.c index e32e65b8..438787e6 100644 --- a/mac80211.c +++ b/mac80211.c @@ -2100,7 +2100,7 @@ void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif) rcu_assign_pointer(mvif->link[0], NULL); mt76_abort_scan(dev); - if (mvif->roc_phy) + if (mvif->roc_phy && mvif->roc_phy->roc_vif == vif) mt76_abort_roc(mvif->roc_phy); } EXPORT_SYMBOL_GPL(mt76_vif_cleanup);