[PATCH] wifi: mt76: mt76x02: sync the group key PN before a restart

Cristian Papa pcristian292 at gmail.com
Sun Oct 11 00:27:02 PDT 2026


mt76x02_key_sync() skips keys without a station, including the GTK of
an AP. The hardware advances its TX packet number without updating
key->tx_pn. When mac80211 reinstalls the key after a watchdog restart,
mt76x02_mac_wcid_set_key() writes that stale software value back to the
hardware IV table. Peers retaining the GTK can then reject group frames
as replays.

On an MT7612E AP, saved snapshots show the hardware PN of the same active
CCMP GTK falling from 6412 to 0 across two watchdog restarts, while its
software PN remained zero. The PMF pairwise keys continued to advance
their software counters.

Use the interface's group WCID for keys without a station. Keep the
key-index check so that, when two GTKs are installed, only the key
programmed into that WCID is synchronized. Also retain the sw_iv check
to avoid overwriting software-generated packet numbers, including those
used by PMF pairwise keys.

Fixes: 004960423fe1 ("mt76: mt76x2: implement full device restart on watchdog reset")
Assisted-by: LLM
Signed-off-by: Cristian Papa <pcristian292 at gmail.com>

---
Reproduction: MT7612E in AP mode on an XR500v, using a locally patched
OpenWrt kernel 6.18.44 and mac80211 backports 7.2. The key-sync callback
has the same omission in the upstream base used here.

Validation:
- MIPS build against that kernel/backports: W=1 and the mt76 Makefile's
  -Werror, 11 modules built, no warnings or errors.
- Host tests compile the actual key-sync, key-install and PN helpers
  with emulated registers under ASan/UBSan. The baseline fails the
  captured 6412-PN regression; the candidate passes it and 12 test
  groups with 363 assertions, including two GTKs, PMF, two interfaces,
  repeated resets and rekey.
- On the router, with this change on top of the board's local patches,
  three watchdog restarts kept the hardware PN of the active GTK
  increasing (404 before, then 418, 421, 443 and 544 afterwards), and
  after the first restart the client still answered a ping to ff02::1
  without reconnecting. Without the change, the same PN went from 6412
  to 0, and no associated client answered ff02::1 until it reconnected,
  while unicast pings went through.
- After the third restart the client did stop receiving, for another
  reason: mac80211 kept it marked as asleep (WLAN_STA_PS_STA) and
  buffered its frames while it kept transmitting. That is a separate
  problem in the restart path and is not addressed here.

This change only includes the group key in the existing PN snapshot.
It does not change the watchdog's snapshot-before-MAC-stop ordering;
whether hardware can still advance PN in that interval is a separate
follow-up. It also does not change group-key selection or power save.

AI assistance was used to review the captures and source, draft the
change and message, and develop the host regression tests. No key
material or raw packet payload is included.

 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index dc7c03d2..ce4e0086 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -377,12 +377,13 @@ static void mt76x02_key_sync(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			     struct ieee80211_key_conf *key, void *data)
 {
 	struct mt76x02_dev *dev = hw->priv;
+	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
 	struct mt76_wcid *wcid;
 
-	if (!sta)
-		return;
-
-	wcid = (struct mt76_wcid *)sta->drv_priv;
+	if (sta)
+		wcid = (struct mt76_wcid *)sta->drv_priv;
+	else
+		wcid = &mvif->group_wcid;
 
 	if (wcid->hw_key_idx != key->keyidx || wcid->sw_iv)
 		return;

base-commit: 2e6968e9286f3573016b9f804d4945373a21c489
-- 
2.47.3




More information about the Linux-mediatek mailing list