From 6fc9af3df6ca7f3c94774d20f62dc7b49616026d Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Tue, 15 Oct 2024 12:11:03 +0530 Subject: [PATCH] wifi: ath10k: Fix memory leak in management tx commit e15d84b3bba187aa372dff7c58ce1fd5cb48a076 upstream. In the current logic, memory is allocated for storing the MSDU context during management packet TX but this memory is not being freed during management TX completion. Similar leaks are seen in the management TX cleanup logic. Kmemleak reports this problem as below, unreferenced object 0xffffff80b64ed250 (size 16): comm "kworker/u16:7", pid 148, jiffies 4294687130 (age 714.199s) hex dump (first 16 bytes): 00 2b d8 d8 80 ff ff ff c4 74 e9 fd 07 00 00 00 .+.......t...... backtrace: [] __kmem_cache_alloc_node+0x1e4/0x2d8 [] kmalloc_trace+0x48/0x110 [] ath10k_wmi_tlv_op_gen_mgmt_tx_send+0xd4/0x1d8 [ath10k_core] [] ath10k_mgmt_over_wmi_tx_work+0x134/0x298 [ath10k_core] [] process_scheduled_works+0x1ac/0x400 [] worker_thread+0x208/0x328 [] kthread+0x100/0x1c0 [] ret_from_fork+0x10/0x20 Free the memory during completion and cleanup to fix the leak. Protect the mgmt_pending_tx idr_remove() operation in ath10k_wmi_tlv_op_cleanup_mgmt_tx_send() using ar->data_lock similar to other instances. Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1 Fixes: dc405152bb64 ("ath10k: handle mgmt tx completion event") Fixes: c730c477176a ("ath10k: Remove msdu from idr when management pkt send fails") Cc: stable@vger.kernel.org Signed-off-by: Manikanta Pubbisetty Link: https://patch.msgid.link/20241015064103.6060-1-quic_mpubbise@quicinc.com Signed-off-by: Jeff Johnson Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 7 ++++++- drivers/net/wireless/ath/ath10k/wmi.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index ee1c86bb5078..9101e0a14a57 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2854,9 +2854,14 @@ ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu) { struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu); + struct ath10k_mgmt_tx_pkt_addr *pkt_addr; struct ath10k_wmi *wmi = &ar->wmi; - idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id); + spin_lock_bh(&ar->data_lock); + pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id); + spin_unlock_bh(&ar->data_lock); + + kfree(pkt_addr); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 81689dbab7f4..ed6316c41cb7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2385,6 +2385,7 @@ wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param) dma_unmap_single(ar->dev, pkt_addr->paddr, msdu->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(msdu); + kfree(pkt_addr); if (param->status) { info->flags &= ~IEEE80211_TX_STAT_ACK; @@ -9466,6 +9467,7 @@ static int ath10k_wmi_mgmt_tx_clean_up_pending(int msdu_id, void *ptr, dma_unmap_single(ar->dev, pkt_addr->paddr, msdu->len, DMA_TO_DEVICE); ieee80211_free_txskb(ar->hw, msdu); + kfree(pkt_addr); return 0; }