From 97b144b82e2388efef1f78269626d61de0480feb Mon Sep 17 00:00:00 2001 From: Kang Yang Date: Wed, 16 Sep 2026 14:03:24 +0800 Subject: [PATCH] wifi: ath12k: fix skb leak on monitor PPDU ID wraparound ath12k_dp_mon_comp_ppduid() updates *ppdu_id and returns msdu_ppdu_id to indicate that a PPDU transition was detected. When PPDU IDs wrap around, msdu_ppdu_id can be 0. In that case the function updates *ppdu_id but returns 0, causing ath12k_wifi7_dp_rx_mon_mpdu_pop() to interpret the result as "no PPDU update" and continue processing the MPDU. The MSDUs are then linked into head_msdu while their RX descriptors have already been detached. Later, ath12k_wifi7_dp_rx_mon_dest_process() detects the PPDU mismatch and exits with the partially built MSDU chain, leaking the SKBs. kmemleak reports the leak through: kmemleak_alloc() __netdev_alloc_skb() ath12k_dp_rx_bufs_replenish() ath12k_wifi7_dp_rx_mon_dest_process() Fix this by returning a boolean value from ath12k_dp_mon_comp_ppduid() so the update notification is independent of the actual PPDU ID value. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3 Fixes: 72bfbf19b7da ("wifi: ath12k: add support to reap and process mon dest ring") Signed-off-by: Kang Yang Reviewed-by: Baochen Qiang Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20260916060325.854-6-kang.yang@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/dp_mon.c | 15 +++++++-------- drivers/net/wireless/ath/ath12k/dp_mon.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.c b/drivers/net/wireless/ath/ath12k/dp_mon.c index 1faf1896d0ab..709507d44d8e 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.c +++ b/drivers/net/wireless/ath/ath12k/dp_mon.c @@ -81,24 +81,23 @@ fail_alloc_skb: } EXPORT_SYMBOL(ath12k_dp_rx_alloc_mon_status_buf); -u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id) +bool ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id) { - u32 ret = 0; - if ((*ppdu_id < msdu_ppdu_id) && ((msdu_ppdu_id - *ppdu_id) < DP_NOT_PPDU_ID_WRAP_AROUND)) { /* Hold on mon dest ring, and reap mon status ring. */ *ppdu_id = msdu_ppdu_id; - ret = msdu_ppdu_id; - } else if ((*ppdu_id > msdu_ppdu_id) && - ((*ppdu_id - msdu_ppdu_id) > DP_NOT_PPDU_ID_WRAP_AROUND)) { + return true; + } + if ((*ppdu_id > msdu_ppdu_id) && + ((*ppdu_id - msdu_ppdu_id) > DP_NOT_PPDU_ID_WRAP_AROUND)) { /* PPDU ID has exceeded the maximum value and will * restart from 0. */ *ppdu_id = msdu_ppdu_id; - ret = msdu_ppdu_id; + return true; } - return ret; + return false; } EXPORT_SYMBOL(ath12k_dp_mon_comp_ppduid); diff --git a/drivers/net/wireless/ath/ath12k/dp_mon.h b/drivers/net/wireless/ath/ath12k/dp_mon.h index 162cdcaa57a7..f352655eae9d 100644 --- a/drivers/net/wireless/ath/ath12k/dp_mon.h +++ b/drivers/net/wireless/ath/ath12k/dp_mon.h @@ -100,7 +100,7 @@ struct sk_buff *ath12k_dp_rx_alloc_mon_status_buf(struct ath12k_base *ab, struct dp_rxdma_mon_ring *rx_ring, int *buf_id); -u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id); +bool ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id); int ath12k_dp_mon_parse_status_buf(struct ath12k_pdev_dp *dp_pdev, struct ath12k_mon_data *pmon,