Skip to content

Commit 9a394fd

Browse files
Rameshkumar Sundaramgregkh
authored andcommitted
wifi: ath11k: fix group data packet drops during rekey
[ Upstream commit 97acb02 ] During GTK rekey, mac80211 issues a clear key (if the old key exists) followed by an install key operation in the same context. This causes ath11k to send two WMI commands in quick succession: one to clear the old key and another to install the new key in the same slot. Under certain conditions—especially under high load or time sensitive scenarios, firmware may process these commands asynchronously in a way that firmware assumes the key is cleared whereas hardware has a valid key. This inconsistency between hardware and firmware leads to group addressed packet drops. Only setting the same key again can restore a valid key in firmware and allow packets to be transmitted. This issue remained latent because the host's clear key commands were not effective in firmware until commit 436a4e8 ("ath11k: clear the keys properly via DISABLE_KEY"). That commit enabled the host to explicitly clear group keys, which inadvertently exposed the race. To mitigate this, restrict group key clearing across all modes (AP, STA, MESH). During rekey, the new key can simply be set on top of the previous one, avoiding the need for a clear followed by a set. However, in AP mode specifically, permit group key clearing when no stations are associated. This exception supports transitions from secure modes (e.g., WPA2/WPA3) to open mode, during which all associated peers are removed and the group key is cleared as part of the transition. Add a per-BSS station counter to track the presence of stations during set key operations. Also add a reset_group_keys flag to track the key re-installation state and avoid repeated installation of the same key when the number of connected stations transitions to non-zero within a rekey period. Additionally, for AP and Mesh modes, when the first station associates, reinstall the same group key that was last set. This ensures that the firmware recovers from any race that may have occurred during a previous key clear when no stations were associated. This change ensures that key clearing is permitted only when no clients are connected, avoiding packet loss while enabling dynamic security mode transitions. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.41 Reported-by: Steffen Moser <lists@steffen-moser.de> Closes: https://lore.kernel.org/linux-wireless/c6366409-9928-4dd7-bf7b-ba7fcf20eabf@steffen-moser.de Fixes: 436a4e8 ("ath11k: clear the keys properly via DISABLE_KEY") Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Tested-by: Nicolas Escande <nico.escande@gmail.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Link: https://patch.msgid.link/20250810170018.1124014-1-rameshkumar.sundaram@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f1b8de7 commit 9a394fd

File tree

2 files changed

+104
-9
lines changed

2 files changed

+104
-9
lines changed

drivers/net/wireless/ath/ath11k/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ struct ath11k_vif {
410410
bool do_not_send_tmpl;
411411
struct ath11k_arp_ns_offload arp_ns_offload;
412412
struct ath11k_rekey_data rekey_data;
413+
u32 num_stations;
414+
bool reinstall_group_keys;
413415

414416
struct ath11k_reg_tpc_power_info reg_tpc_info;
415417

drivers/net/wireless/ath/ath11k/mac.c

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
43174317
return first_errno;
43184318
}
43194319

4320+
static int ath11k_set_group_keys(struct ath11k_vif *arvif)
4321+
{
4322+
struct ath11k *ar = arvif->ar;
4323+
struct ath11k_base *ab = ar->ab;
4324+
const u8 *addr = arvif->bssid;
4325+
int i, ret, first_errno = 0;
4326+
struct ath11k_peer *peer;
4327+
4328+
spin_lock_bh(&ab->base_lock);
4329+
peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
4330+
spin_unlock_bh(&ab->base_lock);
4331+
4332+
if (!peer)
4333+
return -ENOENT;
4334+
4335+
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
4336+
struct ieee80211_key_conf *key = peer->keys[i];
4337+
4338+
if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
4339+
continue;
4340+
4341+
ret = ath11k_install_key(arvif, key, SET_KEY, addr,
4342+
WMI_KEY_GROUP);
4343+
if (ret < 0 && first_errno == 0)
4344+
first_errno = ret;
4345+
4346+
if (ret < 0)
4347+
ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n",
4348+
i, arvif->vdev_id, ret);
4349+
}
4350+
4351+
return first_errno;
4352+
}
4353+
43204354
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
43214355
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
43224356
struct ieee80211_key_conf *key)
@@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
43264360
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
43274361
struct ath11k_peer *peer;
43284362
struct ath11k_sta *arsta;
4363+
bool is_ap_with_no_sta;
43294364
const u8 *peer_addr;
43304365
int ret = 0;
43314366
u32 flags = 0;
@@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
43864421
else
43874422
flags |= WMI_KEY_GROUP;
43884423

4389-
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4390-
if (ret) {
4391-
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4392-
goto exit;
4393-
}
4424+
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4425+
"%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n",
4426+
cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id,
4427+
flags, arvif->vdev_type, arvif->num_stations);
4428+
4429+
/* Allow group key clearing only in AP mode when no stations are
4430+
* associated. There is a known race condition in firmware where
4431+
* group addressed packets may be dropped if the key is cleared
4432+
* and immediately set again during rekey.
4433+
*
4434+
* During GTK rekey, mac80211 issues a clear key (if the old key
4435+
* exists) followed by an install key operation for same key
4436+
* index. This causes ath11k to send two WMI commands in quick
4437+
* succession: one to clear the old key and another to install the
4438+
* new key in the same slot.
4439+
*
4440+
* Under certain conditions—especially under high load or time
4441+
* sensitive scenarios, firmware may process these commands
4442+
* asynchronously in a way that firmware assumes the key is
4443+
* cleared whereas hardware has a valid key. This inconsistency
4444+
* between hardware and firmware leads to group addressed packet
4445+
* drops after rekey.
4446+
* Only setting the same key again can restore a valid key in
4447+
* firmware and allow packets to be transmitted.
4448+
*
4449+
* There is a use case where an AP can transition from Secure mode
4450+
* to open mode without a vdev restart by just deleting all
4451+
* associated peers and clearing key, Hence allow clear key for
4452+
* that case alone. Mark arvif->reinstall_group_keys in such cases
4453+
* and reinstall the same key when the first peer is added,
4454+
* allowing firmware to recover from the race if it had occurred.
4455+
*/
43944456

4395-
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4396-
if (ret) {
4397-
ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
4398-
goto exit;
4457+
is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP &&
4458+
!arvif->num_stations);
4459+
if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) {
4460+
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4461+
if (ret) {
4462+
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4463+
goto exit;
4464+
}
4465+
4466+
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4467+
if (ret) {
4468+
ath11k_warn(ab, "failed to offload PN replay detection %d\n",
4469+
ret);
4470+
goto exit;
4471+
}
4472+
4473+
if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta)
4474+
arvif->reinstall_group_keys = true;
43994475
}
44004476

44014477
spin_lock_bh(&ab->base_lock);
@@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
49945070
return -ENOBUFS;
49955071

49965072
ar->num_stations++;
5073+
arvif->num_stations++;
49975074

49985075
return 0;
49995076
}
@@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
50095086
return;
50105087

50115088
ar->num_stations--;
5089+
arvif->num_stations--;
50125090
}
50135091

50145092
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
@@ -9536,6 +9614,21 @@ static int ath11k_mac_station_add(struct ath11k *ar,
95369614
goto exit;
95379615
}
95389616

9617+
/* Driver allows the DEL KEY followed by SET KEY sequence for
9618+
* group keys for only when there is no clients associated, if at
9619+
* all firmware has entered the race during that window,
9620+
* reinstalling the same key when the first sta connects will allow
9621+
* firmware to recover from the race.
9622+
*/
9623+
if (arvif->num_stations == 1 && arvif->reinstall_group_keys) {
9624+
ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n",
9625+
arvif->vdev_id);
9626+
ret = ath11k_set_group_keys(arvif);
9627+
if (ret)
9628+
goto dec_num_station;
9629+
arvif->reinstall_group_keys = false;
9630+
}
9631+
95399632
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
95409633
if (!arsta->rx_stats) {
95419634
ret = -ENOMEM;

0 commit comments

Comments
 (0)