]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Handle error cases during extended skb allocation
authorP Praneesh <praneesh.p@oss.qualcomm.com>
Fri, 11 Apr 2025 06:01:51 +0000 (11:31 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 17 Apr 2025 22:49:32 +0000 (15:49 -0700)
Currently, in the case of extended skb allocation, the buffer is freed
before the DMA unmap operation. This premature deletion can result in
skb->data corruption, as the memory region could be re-allocated for other
purposes. Fix this issue by reordering the failure cases by calling
dma_unmap_single() first, then followed by the corresponding kfree_skb().
This helps avoid data corruption in case of failures in dp_tx().

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: P Praneesh <praneesh.p@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250411060154.1388159-2-praneesh.p@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_tx.c

index 91da0805706ffcba36dc5abec87175ae073e2c99..9d58a9a9cbff690c60930ec140a33ebbb23d6b9c 100644 (file)
@@ -231,7 +231,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_link_vif *arvif,
        struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
        struct hal_tcl_data_cmd *hal_tcl_desc;
        struct hal_tx_msdu_ext_desc *msg;
-       struct sk_buff *skb_ext_desc;
+       struct sk_buff *skb_ext_desc = NULL;
        struct hal_srng *tcl_ring;
        struct ieee80211_hdr *hdr = (void *)skb->data;
        struct ath12k_vif *ahvif = arvif->ahvif;
@@ -417,18 +417,15 @@ map:
                        if (ret < 0) {
                                ath12k_dbg(ab, ATH12K_DBG_DP_TX,
                                           "Failed to add HTT meta data, dropping packet\n");
-                               kfree_skb(skb_ext_desc);
-                               goto fail_unmap_dma;
+                               goto fail_free_ext_skb;
                        }
                }
 
                ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,
                                          skb_ext_desc->len, DMA_TO_DEVICE);
                ret = dma_mapping_error(ab->dev, ti.paddr);
-               if (ret) {
-                       kfree_skb(skb_ext_desc);
-                       goto fail_unmap_dma;
-               }
+               if (ret)
+                       goto fail_free_ext_skb;
 
                ti.data_len = skb_ext_desc->len;
                ti.type = HAL_TCL_DESC_TYPE_EXT_DESC;
@@ -464,7 +461,7 @@ map:
                        ring_selector++;
                }
 
-               goto fail_unmap_dma;
+               goto fail_unmap_dma_ext;
        }
 
        spin_lock_bh(&arvif->link_stats_lock);
@@ -491,13 +488,16 @@ map:
 
        return 0;
 
-fail_unmap_dma:
-       dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
-
+fail_unmap_dma_ext:
        if (skb_cb->paddr_ext_desc)
                dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,
                                 sizeof(struct hal_tx_msdu_ext_desc),
                                 DMA_TO_DEVICE);
+fail_free_ext_skb:
+       kfree_skb(skb_ext_desc);
+
+fail_unmap_dma:
+       dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE);
 
 fail_remove_tx_buf:
        ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id);