Skip to content

Commit 0076543

Browse files
Rameshkumar Sundaramopsiff
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> (cherry picked from commit 5d7b2d45770e0d5e3dfa85c735abbf48315b4119)
1 parent de69d79 commit 0076543

2 files changed

Lines changed: 104 additions & 9 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ struct ath11k_vif {
365365
struct ieee80211_chanctx_conf chanctx;
366366
struct ath11k_arp_ns_offload arp_ns_offload;
367367
struct ath11k_rekey_data rekey_data;
368+
u32 num_stations;
369+
bool reinstall_group_keys;
368370

369371
#ifdef CONFIG_ATH11K_DEBUGFS
370372
struct dentry *debugfs_twt;

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

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4205,6 +4205,40 @@ static int ath11k_clear_peer_keys(struct ath11k_vif *arvif,
42054205
return first_errno;
42064206
}
42074207

4208+
static int ath11k_set_group_keys(struct ath11k_vif *arvif)
4209+
{
4210+
struct ath11k *ar = arvif->ar;
4211+
struct ath11k_base *ab = ar->ab;
4212+
const u8 *addr = arvif->bssid;
4213+
int i, ret, first_errno = 0;
4214+
struct ath11k_peer *peer;
4215+
4216+
spin_lock_bh(&ab->base_lock);
4217+
peer = ath11k_peer_find(ab, arvif->vdev_id, addr);
4218+
spin_unlock_bh(&ab->base_lock);
4219+
4220+
if (!peer)
4221+
return -ENOENT;
4222+
4223+
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
4224+
struct ieee80211_key_conf *key = peer->keys[i];
4225+
4226+
if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
4227+
continue;
4228+
4229+
ret = ath11k_install_key(arvif, key, SET_KEY, addr,
4230+
WMI_KEY_GROUP);
4231+
if (ret < 0 && first_errno == 0)
4232+
first_errno = ret;
4233+
4234+
if (ret < 0)
4235+
ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n",
4236+
i, arvif->vdev_id, ret);
4237+
}
4238+
4239+
return first_errno;
4240+
}
4241+
42084242
static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
42094243
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
42104244
struct ieee80211_key_conf *key)
@@ -4214,6 +4248,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
42144248
struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
42154249
struct ath11k_peer *peer;
42164250
struct ath11k_sta *arsta;
4251+
bool is_ap_with_no_sta;
42174252
const u8 *peer_addr;
42184253
int ret = 0;
42194254
u32 flags = 0;
@@ -4274,16 +4309,57 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
42744309
else
42754310
flags |= WMI_KEY_GROUP;
42764311

4277-
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4278-
if (ret) {
4279-
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4280-
goto exit;
4281-
}
4312+
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
4313+
"%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n",
4314+
cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id,
4315+
flags, arvif->vdev_type, arvif->num_stations);
4316+
4317+
/* Allow group key clearing only in AP mode when no stations are
4318+
* associated. There is a known race condition in firmware where
4319+
* group addressed packets may be dropped if the key is cleared
4320+
* and immediately set again during rekey.
4321+
*
4322+
* During GTK rekey, mac80211 issues a clear key (if the old key
4323+
* exists) followed by an install key operation for same key
4324+
* index. This causes ath11k to send two WMI commands in quick
4325+
* succession: one to clear the old key and another to install the
4326+
* new key in the same slot.
4327+
*
4328+
* Under certain conditions—especially under high load or time
4329+
* sensitive scenarios, firmware may process these commands
4330+
* asynchronously in a way that firmware assumes the key is
4331+
* cleared whereas hardware has a valid key. This inconsistency
4332+
* between hardware and firmware leads to group addressed packet
4333+
* drops after rekey.
4334+
* Only setting the same key again can restore a valid key in
4335+
* firmware and allow packets to be transmitted.
4336+
*
4337+
* There is a use case where an AP can transition from Secure mode
4338+
* to open mode without a vdev restart by just deleting all
4339+
* associated peers and clearing key, Hence allow clear key for
4340+
* that case alone. Mark arvif->reinstall_group_keys in such cases
4341+
* and reinstall the same key when the first peer is added,
4342+
* allowing firmware to recover from the race if it had occurred.
4343+
*/
42824344

4283-
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4284-
if (ret) {
4285-
ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret);
4286-
goto exit;
4345+
is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP &&
4346+
!arvif->num_stations);
4347+
if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) {
4348+
ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags);
4349+
if (ret) {
4350+
ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret);
4351+
goto exit;
4352+
}
4353+
4354+
ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key);
4355+
if (ret) {
4356+
ath11k_warn(ab, "failed to offload PN replay detection %d\n",
4357+
ret);
4358+
goto exit;
4359+
}
4360+
4361+
if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta)
4362+
arvif->reinstall_group_keys = true;
42874363
}
42884364

42894365
spin_lock_bh(&ab->base_lock);
@@ -4876,6 +4952,7 @@ static int ath11k_mac_inc_num_stations(struct ath11k_vif *arvif,
48764952
return -ENOBUFS;
48774953

48784954
ar->num_stations++;
4955+
arvif->num_stations++;
48794956

48804957
return 0;
48814958
}
@@ -4891,6 +4968,7 @@ static void ath11k_mac_dec_num_stations(struct ath11k_vif *arvif,
48914968
return;
48924969

48934970
ar->num_stations--;
4971+
arvif->num_stations--;
48944972
}
48954973

48964974
static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar,
@@ -8890,6 +8968,21 @@ static int ath11k_mac_station_add(struct ath11k *ar,
88908968
goto exit;
88918969
}
88928970

8971+
/* Driver allows the DEL KEY followed by SET KEY sequence for
8972+
* group keys for only when there is no clients associated, if at
8973+
* all firmware has entered the race during that window,
8974+
* reinstalling the same key when the first sta connects will allow
8975+
* firmware to recover from the race.
8976+
*/
8977+
if (arvif->num_stations == 1 && arvif->reinstall_group_keys) {
8978+
ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n",
8979+
arvif->vdev_id);
8980+
ret = ath11k_set_group_keys(arvif);
8981+
if (ret)
8982+
goto dec_num_station;
8983+
arvif->reinstall_group_keys = false;
8984+
}
8985+
88938986
arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL);
88948987
if (!arsta->rx_stats) {
88958988
ret = -ENOMEM;

0 commit comments

Comments
 (0)