From 2c9a4ff2b4b10c5c0c88c6c16af81ddb06ec8a11 Mon Sep 17 00:00:00 2001 From: Zac Bowling Date: Wed, 31 Dec 2025 17:16:35 -0800 Subject: [PATCH 1/2] wifi: mt76: mt7925: add NULL checks in MCU STA TLV functions Add NULL pointer checks for link_conf and mconf in: - mt7925_mcu_sta_phy_tlv(): builds PHY capability TLV for station record - mt7925_mcu_sta_rate_ctrl_tlv(): builds rate control TLV for station record Both functions call mt792x_vif_to_bss_conf() and mt792x_vif_to_link() which can return NULL during MLO link state transitions when the link configuration in mac80211 is not yet synchronized with the driver's link tracking. Without these checks, the driver will crash with a NULL pointer dereference when accessing link_conf->chanreq.oper or link_conf->basic_rates. Reported-by: Zac Bowling Signed-off-by: Zac Bowling --- mt7925/mcu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mt7925/mcu.c b/mt7925/mcu.c index bd38807e4..11acdf1bd 100644 --- a/mt7925/mcu.c +++ b/mt7925/mcu.c @@ -1773,6 +1773,10 @@ mt7925_mcu_sta_phy_tlv(struct sk_buff *skb, link_conf = mt792x_vif_to_bss_conf(vif, link_sta->link_id); mconf = mt792x_vif_to_link(mvif, link_sta->link_id); + + if (!link_conf || !mconf) + return; + chandef = mconf->mt76.ctx ? &mconf->mt76.ctx->def : &link_conf->chanreq.oper; @@ -1851,6 +1855,10 @@ mt7925_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, link_conf = mt792x_vif_to_bss_conf(vif, link_sta->link_id); mconf = mt792x_vif_to_link(mvif, link_sta->link_id); + + if (!link_conf || !mconf) + return; + chandef = mconf->mt76.ctx ? &mconf->mt76.ctx->def : &link_conf->chanreq.oper; band = chandef->chan->band; From ba0f55dda341c44939bd2c740352fb330c3b5a2e Mon Sep 17 00:00:00 2001 From: Zac Bowling Date: Wed, 31 Dec 2025 17:16:44 -0800 Subject: [PATCH 2/2] wifi: mt76: mt7925: add NULL checks for link_conf and mlink in main.c Add NULL pointer checks throughout main.c for functions that call mt792x_vif_to_bss_conf(), mt792x_vif_to_link(), and mt792x_sta_to_link() without verifying the return value before dereferencing. Functions fixed: - mt7925_set_key(): Check link_conf, mconf, and mlink before use - mt7925_mac_link_sta_add(): Check link_conf before BSS info update - mt7925_mac_link_sta_assoc(): Check mlink and link_conf before use - mt7925_mac_link_sta_remove(): Check mlink and link_conf, add goto label for proper cleanup path - mt7925_change_vif_links(): Check link_conf before adding BSS These functions can receive NULL when the link configuration in mac80211 is not yet synchronized with the driver's link tracking during MLO operations or state transitions. Without these checks, the driver will crash with NULL pointer dereferences during station add/remove/association operations. Reported-by: Zac Bowling Signed-off-by: Zac Bowling --- mt7925/main.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/mt7925/main.c b/mt7925/main.c index 307850a58..9900bd77b 100644 --- a/mt7925/main.c +++ b/mt7925/main.c @@ -604,6 +604,10 @@ static int mt7925_set_link_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, link_sta = sta ? mt792x_sta_to_link_sta(vif, sta, link_id) : NULL; mconf = mt792x_vif_to_link(mvif, link_id); mlink = mt792x_sta_to_link(msta, link_id); + + if (!link_conf || !mconf || !mlink) + return -EINVAL; + wcid = &mlink->wcid; wcid_keyidx = &wcid->hw_key_idx; @@ -887,6 +891,8 @@ static int mt7925_mac_link_sta_add(struct mt76_dev *mdev, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); link_conf = mt792x_vif_to_bss_conf(vif, link_id); + if (!link_conf) + return -EINVAL; /* should update bss info before STA add */ if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { @@ -1032,6 +1038,8 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, msta = (struct mt792x_sta *)link_sta->sta->drv_priv; mlink = mt792x_sta_to_link(msta, link_sta->link_id); + if (!mlink) + return; mt792x_mutex_acquire(dev); @@ -1041,12 +1049,13 @@ static void mt7925_mac_link_sta_assoc(struct mt76_dev *mdev, link_conf = mt792x_vif_to_bss_conf(vif, vif->bss_conf.link_id); } - if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + if (link_conf && vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { struct mt792x_bss_conf *mconf; mconf = mt792x_link_conf_to_mconf(link_conf); - mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, - link_conf, link_sta, true); + if (mconf) + mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, + link_conf, link_sta, true); } ewma_avg_signal_init(&mlink->avg_ack_signal); @@ -1093,6 +1102,8 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, msta = (struct mt792x_sta *)link_sta->sta->drv_priv; mlink = mt792x_sta_to_link(msta, link_id); + if (!mlink) + return; mt7925_roc_abort_sync(dev); @@ -1106,10 +1117,12 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, link_conf = mt792x_vif_to_bss_conf(vif, link_id); - if (vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { + if (link_conf && vif->type == NL80211_IFTYPE_STATION && !link_sta->sta->tdls) { struct mt792x_bss_conf *mconf; mconf = mt792x_link_conf_to_mconf(link_conf); + if (!mconf) + goto out; if (ieee80211_vif_is_mld(vif)) mt792x_mac_link_bss_remove(dev, mconf, mlink); @@ -1117,6 +1130,7 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev, mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, link_sta, false); } +out: spin_lock_bh(&mdev->sta_poll_lock); if (!list_empty(&mlink->wcid.poll_list)) @@ -2021,6 +2035,11 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mlink = mlinks[link_id]; link_conf = mt792x_vif_to_bss_conf(vif, link_id); + if (!link_conf) { + err = -EINVAL; + goto free; + } + rcu_assign_pointer(mvif->link_conf[link_id], mconf); rcu_assign_pointer(mvif->sta.link[link_id], mlink);