wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/661-ath12k-add-length-validation-before-skb_put-call.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

190 lines
7.9 KiB
Diff

From 319e5d13d42583ec89fae2dbcf483656f2d1e5dd Mon Sep 17 00:00:00 2001
From: P Praneesh <quic_ppranees@quicinc.com>
Date: Thu, 25 Aug 2022 19:40:04 +0530
Subject: [PATCH] ath12k: add length validation before skb_put call
In the wbm_err path, while processing tkip mic error msdu_len is fetched
from the hal_rx_desc's msdu_end. This msdu_len is directly passing to the
skb_put without the validation.
In the stretch test scenario, some of the descriptors received under wbm_err
is invalid and carries junk values which leads to higher msdu_len compare to
actual msdu data size.
Add a check to drop the skb when the calculation msdu length is greater than
the skb size and add provision to capture the dropped packet count in
soc_dp_stats.
433.528769: <2> skbuff: skb_over_panic: text:00000000ae22af6c len:16634 put:16634 head:000000000f476cc4 data:00000000bd8a38f5 tail:0x413a end:0x940 dev:<NULL>
433.536000: <2> ------------[ cut here ]------------
433.549601: <2> kernel BUG at net/core/skbuff.c:137!
433.554375: <2> Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
433.826006: <2> CPU: 0 PID: 9 Comm: ksoftirqd/0 Tainted: G W 5.4.164 #0
433.844482: <2> Hardware name: Qualcomm Technologies, Inc. IPQ9574/AP-AL02-C4 (DT)
433.851947: <2> pstate: 40400005 (nZcv daif +PAN -UAO)
433.859153: <2> pc : skb_panic+0x48/0x4c
433.863921: <2> lr : skb_panic+0x48/0x4c
433.867654: <2> sp : ffffff801c5af9f0
433.871213: <2> x29: ffffff801c5afa00 x28: 0000000000000018
433.874427: <2> x27: 0000000000000420 x26: ffffff8023602938
433.879809: <2> x25: 00000000000000f8 x24: ffffff8034128000
433.885104: <2> x23: ffffff8034120000 x22: 00000000000000fb
433.890398: <2> x21: ffffff8023602938 x20: ffffff8026d59540
433.895694: <2> x19: ffffff802a237000 x18: 0000000000000000
433.900989: <2> x17: 0000000000000000 x16: 0000000000002cd8
433.906284: <2> x15: 0000000000002c88 x14: 4c554e3c3a766564
433.911579: <2> x13: 2030343978303a64 x12: 6e65206133313478
433.916874: <2> x11: 303a6c6961742035 x10: 6638336138646230
433.922170: <2> x9 : 303030303030303a x8 : 6174616420346363
433.927464: <2> x7 : 3637346630303030 x6 : 0000000000000001
433.932760: <2> x5 : 0000000000000000 x4 : 0000000000000000
433.938055: <2> x3 : 0000000000000000 x2 : 7634c30f3f78ed00
433.943350: <2> x1 : 0000000000000000 x0 : 000000000000008e
433.948645: <2> Call trace:
433.953938: <2> skb_panic+0x48/0x4c
433.956109: <2> skb_put+0x54/0x60
433.959591: <2> ath12k_dp_rx_h_ppdu+0x7d4/0x87c [ath12k]
433.962450: <2> ath12k_dp_rx_process_wbm_err+0x37c/0x3d0 [ath12k]
433.967573: <2> ath12k_dp_service_srng+0xb0/0x260 [ath12k]
433.973302: <2> ath12k_pci_write32+0x99c/0xb18 [ath12k]
433.978421: <2> __napi_poll+0x30/0xa4
433.983626: <2> net_rx_action+0x118/0x270
433.986840: <2> __do_softirq+0x10c/0x244
433.990571: <2> run_ksoftirqd+0x30/0x44
433.994305: <2> smpboot_thread_fn+0x234/0x254
433.997951: <2> kthread+0x140/0x150
434.001856: <2> ret_from_fork+0x10/0x18
434.005245: <2> Code: f0001d40 aa0803e1 912b2400 9406144f (d4210000)
434.008803: <2> ---[ end trace 6a0a441d397527ec ]---
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
---
drivers/net/wireless/ath/ath12k/core.h | 2 ++
drivers/net/wireless/ath/ath12k/debugfs.c | 10 ++++++----
drivers/net/wireless/ath/ath12k/dp_rx.c | 28 +++++++++++++++++++++-------
3 files changed, 29 insertions(+), 11 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -890,7 +890,9 @@ struct ath12k_soc_dp_stats {
u32 err_ring_pkts;
u32 invalid_rbm;
u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
+ u32 rxdma_error_drop[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
+ u32 reo_error_drop[HAL_REO_DEST_RING_ERROR_CODE_MAX];
u32 hal_reo_error[DP_REO_DST_RING_MAX];
struct ath12k_soc_dp_tx_err_stats tx_err;
struct ath12k_dp_ring_bp_stats bp_stats;
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -838,13 +838,15 @@ static ssize_t ath12k_debugfs_dump_soc_d
soc_stats->invalid_rbm);
len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
- len += scnprintf(buf + len, size - len, "%s: %u\n",
- rxdma_err[i], soc_stats->rxdma_error[i]);
+ len += scnprintf(buf + len, size - len, "%s: handled %u dropped %u\n",
+ rxdma_err[i], soc_stats->rxdma_error[i],
+ soc_stats->rxdma_error_drop[i]);
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
- len += scnprintf(buf + len, size - len, "%s: %u\n",
- reo_err[i], soc_stats->reo_error[i]);
+ len += scnprintf(buf + len, size - len, "%s: handled %u dropped %u\n",
+ reo_err[i], soc_stats->reo_error[i],
+ soc_stats->reo_error_drop[i]);
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
len += scnprintf(buf + len, size - len,
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -3990,8 +3990,6 @@ static bool ath12k_dp_rx_h_reo_err(struc
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
bool drop = false;
- ar->ab->soc_stats.reo_error[rxcb->err_code]++;
-
switch (rxcb->err_code) {
case HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO:
if (ath12k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list))
@@ -4011,10 +4009,15 @@ static bool ath12k_dp_rx_h_reo_err(struc
break;
}
+ if (drop)
+ ar->ab->soc_stats.reo_error_drop[rxcb->err_code]++;
+ else
+ ar->ab->soc_stats.reo_error[rxcb->err_code]++;
+
return drop;
}
-static void ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
+static bool ath12k_dp_rx_h_tkip_mic_err(struct ath12k *ar, struct sk_buff *msdu,
struct ieee80211_rx_status *status)
{
struct ath12k_base *ab = ar->ab;
@@ -4029,6 +4032,14 @@ static void ath12k_dp_rx_h_tkip_mic_err(
l3pad_bytes = ath12k_dp_rx_h_l3pad(ab, desc);
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
+
+ if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
+ ath12k_warn(ab, "invalid msdu len in tkip mirc err %u\n", msdu_len);
+ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "", desc,
+ sizeof(struct hal_rx_desc));
+ return true;
+ }
+
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
@@ -4039,6 +4050,7 @@ static void ath12k_dp_rx_h_tkip_mic_err(
ath12k_dp_rx_h_undecap(ar, msdu, desc,
HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
+ return false;
}
static bool ath12k_dp_rx_h_4addr_null_frame_handler(struct ath12k *ar, struct sk_buff *msdu,
@@ -4058,7 +4070,6 @@ static bool ath12k_dp_rx_h_4addr_null_fr
msdu_len = ath12k_dp_rx_h_msdu_len(ab, rx_desc);
peer_id = ath12k_dp_rx_h_peer_id(ab, rx_desc);
- ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
if(!ath12k_peer_find_by_id(ab, peer_id)) {
ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
@@ -4098,8 +4109,6 @@ static bool ath12k_dp_rx_h_rxdma_err(str
bool drop = false;
u32 err_bitmap;
- ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
-
switch (rxcb->err_code) {
case HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR:
drop = ath12k_dp_rx_h_4addr_null_frame_handler(ar, msdu, status);
@@ -4108,7 +4117,7 @@ static bool ath12k_dp_rx_h_rxdma_err(str
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
err_bitmap = ath12k_dp_rx_h_mpdu_err(ab, rx_desc);
if (err_bitmap & HAL_RX_MPDU_ERR_TKIP_MIC) {
- ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status);
+ drop = ath12k_dp_rx_h_tkip_mic_err(ar, msdu, status);
break;
}
fallthrough;
@@ -4120,6 +4129,11 @@ static bool ath12k_dp_rx_h_rxdma_err(str
break;
}
+ if (drop)
+ ar->ab->soc_stats.rxdma_error_drop[rxcb->err_code]++;
+ else
+ ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
+
return drop;
}