]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mt76: add wcid publish check in mt76_sta_add
authorJiajia Liu <liujiajia@kylinos.cn>
Thu, 28 May 2026 03:38:14 +0000 (11:38 +0800)
committerFelix Fietkau <nbd@nbd.name>
Tue, 9 Jun 2026 10:15:22 +0000 (10:15 +0000)
Since mt7925_mac_sta_add publishes wcid, add publish check in mt76_sta_add
to avoid reinitializing the wcid->poll_list.

Found dev->sta_poll_list corruption when using mt7925 and 7.1-rc4.
According to the corruption information, prev->next was changed to itself.

wlan0: disconnect from AP 90:fb:5d:94:8b:e3 for new auth to 90:fb:5d:94:8b:e2
wlan0: authenticate with 90:fb:5d:94:8b:e2 (local address=84:9e:56:9c:7e:6b)
wlan0: send auth to 90:fb:5d:94:8b:e2 (try 1/3)
 slab kmalloc-8k start ffff8c80958a6000 pointer offset 4160 size 8192
list_add corruption. prev->next should be next (ffff8c808a7488f8), but was ffff8c80958a7040. (prev=ffff8c80958a7040).

 mt76_wcid_add_poll+0x95/0xd0 [mt76]
 mt7925_mac_add_txs.part.0+0xa5/0xe0 [mt7925_common]
 mt7925_rx_check+0xa7/0xc0 [mt7925_common]
 mt76_dma_rx_poll+0x50d/0x790 [mt76]
 mt792x_poll_rx+0x52/0xe0 [mt792x_lib]

Signed-off-by: Jiajia Liu <liujiajia@kylinos.cn>
Link: https://patch.msgid.link/20260528033814.46418-1-liujiajia@kylinos.cn
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c

index dd68776ada287048305376151b8b8a971b1bb761..dd09ef1bd0c25afe280cf4042fb56e2cce335df8 100644 (file)
@@ -1578,6 +1578,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
 {
        struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;
        struct mt76_dev *dev = phy->dev;
+       struct mt76_wcid *published;
        int ret;
        int i;
 
@@ -1597,11 +1598,19 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
                mtxq->wcid = wcid->idx;
        }
 
-       ewma_signal_init(&wcid->rssi);
-       rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+       published = rcu_dereference_protected(dev->wcid[wcid->idx],
+                                             lockdep_is_held(&dev->mutex));
+       if (published != wcid) {
+               WARN_ON_ONCE(published);
+               ewma_signal_init(&wcid->rssi);
+               rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
+               mt76_wcid_init(wcid, phy->band_idx);
+       } else {
+               wcid->phy_idx = phy->band_idx;
+       }
+
        phy->num_sta++;
 
-       mt76_wcid_init(wcid, phy->band_idx);
 out:
        mutex_unlock(&dev->mutex);