[PATCH ath-next] wifi: ath12k: validate TLV length in process_tpc_stats()

From: Jeff Johnson

Date: Sun Jul 26 2026 - 19:02:16 EST


The outer skb->len guard only confirms the SKB is large enough
to hold the full fixed_param struct, but the TLV's own WMI_TLV_LEN
field is never checked. Firmware advertising a TLV length shorter
than sizeof(*fixed_param) causes reads of pdev_id and event_count
beyond the declared TLV payload.

Add a check that the TLV length is at least sizeof(*fixed_param)
before casting and dereferencing the pointer.

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jeff Johnson <jeff.johnson@xxxxxxxxxxxxxxxx>
---
drivers/net/wireless/ath/ath12k/wmi.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 672eae237ac6..8caafb4cb86c 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -9962,6 +9962,7 @@ static void ath12k_wmi_process_tpc_stats(struct ath12k_base *ab,
void *ptr = skb->data;
struct ath12k *ar;
u16 tlv_tag;
+ u16 tlv_len;
u32 event_count;
int ret;

@@ -9977,6 +9978,7 @@ static void ath12k_wmi_process_tpc_stats(struct ath12k_base *ab,

tlv = (struct wmi_tlv *)ptr;
tlv_tag = le32_get_bits(tlv->header, WMI_TLV_TAG);
+ tlv_len = le32_get_bits(tlv->header, WMI_TLV_LEN);
ptr += sizeof(*tlv);

if (tlv_tag != WMI_TAG_HALPHY_CTRL_PATH_EVENT_FIXED_PARAM) {
@@ -9984,6 +9986,12 @@ static void ath12k_wmi_process_tpc_stats(struct ath12k_base *ab,
return;
}

+ if (tlv_len < sizeof(*fixed_param)) {
+ ath12k_warn(ab, "TPC stats fixed param tlv len %u too short\n",
+ tlv_len);
+ return;
+ }
+
fixed_param = (struct ath12k_wmi_pdev_tpc_stats_event_fixed_params *)ptr;
rcu_read_lock();
ar = ath12k_mac_get_ar_by_pdev_id(ab, le32_to_cpu(fixed_param->pdev_id) + 1);

---
base-commit: 189721a4afa1804315e7dcfca9ca0539c7b1d7af
change-id: 20260720-ath12k_wmi_process_tpc_stats-len-check-e62cedb09818