wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/360-ath11k-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

131 lines
5.3 KiB
Diff

From d762e0422fc0636f1eec53ebbec23a2258058734 Mon Sep 17 00:00:00 2001
From: P Praneesh <quic_ppranees@quicinc.com>
Date: Tue, 30 Aug 2022 22:04:01 +0530
Subject: [PATCH 2/4] ath11k: 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.
Change-Id: I83e3440492c23a98fc3b667a78a9cc0449101231
Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
---
drivers/net/wireless/ath/ath11k/core.h | 2 ++
drivers/net/wireless/ath/ath11k/debugfs.c | 10 ++++++----
drivers/net/wireless/ath/ath11k/dp_rx.c | 21 +++++++++++++++++----
3 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 0fb2e80..4b17c42 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1007,7 +1007,9 @@ struct ath11k_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 ath11k_soc_dp_tx_err_stats tx_err;
struct ath11k_dp_ring_bp_stats bp_stats;
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index d62fca7..0ae0ef5 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -1576,13 +1576,15 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
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,
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 5946c5d..aefea73 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -5054,8 +5054,6 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu,
struct ath11k_skb_rxcb *rxcb = ATH11K_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 (ath11k_dp_rx_h_null_q_desc(ar, msdu, status, msdu_list))
@@ -5075,10 +5073,15 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu,
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 ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
+static bool ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
struct ieee80211_rx_status *status)
{
u16 msdu_len;
@@ -5092,6 +5095,14 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, desc);
msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc);
+
+ if ((hal_rx_desc_sz + l3pad_bytes + msdu_len) > DP_RX_BUFFER_SIZE) {
+ ath11k_warn(ar->ab, "invalid msdu len in tkip mirc err %u\n", msdu_len);
+ ath11k_dbg_dump(ar->ab, ATH11K_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);
@@ -5102,6 +5113,8 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
ath11k_dp_rx_h_undecap(ar, msdu, desc,
HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
+
+ return false;
}
static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu,
@@ -5114,7 +5127,7 @@ static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu,
switch (rxcb->err_code) {
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
- ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
+ drop = ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
break;
default:
/* TODO: Review other rxdma error code to check if anything is
--
2.17.1