wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/683-ath12k-Debug-prints-to-prevent-buffer-overflow.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

142 lines
4.7 KiB
Diff

From ceb2fcfd062fc4ab8180019b00e62fc292ece4d2 Mon Sep 17 00:00:00 2001
From: Manish Dharanenthiran <quic_mdharane@quicinc.com>
Date: Fri, 4 Nov 2022 10:23:58 +0530
Subject: [PATCH] ath12k: [WAR] Add warning to detect buffer overflow
During Mesh 4 node testing, ath12k receives
SKB with header length greater than the MAX
native wifi header length. Because of which,
buffer overflow happens during undecap wifi.
To prevent overflow, added warning before
decap and stopped processing the SKB. Also,
dumped the msdu data for debugging purpose.
Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
---
drivers/net/wireless/ath/ath12k/dp_rx.c | 57 +++++++++++++++++++++++--
1 file changed, 54 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -2239,6 +2239,31 @@ static int ath12k_dp_rx_crypto_icv_len(s
return 0;
}
+static int ath12k_dp_rx_check_msdu_header_len(struct ath12k *ar,
+ struct hal_rx_desc *rx_desc,
+ struct sk_buff *msdu)
+{
+ struct ath12k_base *ab = ar->ab;
+ struct ieee80211_hdr *hdr;
+ u32 hdr_len;
+ u8 decap_type;
+
+ decap_type = ath12k_dp_rx_h_decap_type(ab, rx_desc);
+ if (decap_type == DP_RX_DECAP_TYPE_NATIVE_WIFI) {
+ hdr = (struct ieee80211_hdr *)msdu->data;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ if (unlikely(hdr_len > DP_MAX_NWIFI_HDR_LEN)) {
+ ab->soc_stats.invalid_rbm++;
+ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "msdu_data",
+ msdu->data, msdu->len);
+ ath12k_dbg_dump(ab, ATH12K_DBG_DATA, NULL, "rx_desc",
+ rx_desc, sizeof(*rx_desc));
+ return true;
+ }
+ }
+ return false;
+}
+
static void ath12k_dp_rx_h_undecap_nwifi(struct ath12k *ar,
struct sk_buff *msdu,
enum hal_encrypt_type enctype,
@@ -2246,7 +2271,7 @@ static void ath12k_dp_rx_h_undecap_nwifi
{
struct ath12k_base *ab = ar->ab;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
- u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN];
+ u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN] = {0};
struct ieee80211_hdr *hdr;
size_t hdr_len;
u8 *crypto_hdr;
@@ -2270,8 +2295,13 @@ static void ath12k_dp_rx_h_undecap_nwifi
/* TODO Add other QoS ctl fields when required */
- /* copy decap header before overwriting for reuse below */
- memcpy(decap_hdr, (uint8_t *)hdr, hdr_len);
+ if (hdr_len > DP_MAX_NWIFI_HDR_LEN) {
+ ath12k_err(ab, "hdr len received in %s is greater than MAX LEN [%u > %d]\n",
+ __func__, (unsigned int)hdr_len, DP_MAX_NWIFI_HDR_LEN);
+ } else {
+ /* copy decap header before overwriting for reuse below */
+ memcpy(decap_hdr, (uint8_t *)hdr, hdr_len);
+ }
/* Rebuild crypto header for mac80211 use */
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
@@ -2284,7 +2314,8 @@ static void ath12k_dp_rx_h_undecap_nwifi
memcpy(skb_push(msdu,
IEEE80211_QOS_CTL_LEN), &qos_ctl,
IEEE80211_QOS_CTL_LEN);
- memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len);
+ memcpy(skb_push(msdu, hdr_len), decap_hdr[0] ? decap_hdr : (uint8_t *)hdr,
+ hdr_len);
}
static void ath12k_dp_rx_h_undecap_raw(struct ath12k *ar, struct sk_buff *msdu,
@@ -2935,6 +2966,11 @@ static int ath12k_dp_rx_process_msdu(str
}
}
+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu)) {
+ ret = -EINVAL;
+ goto free_out;
+ }
+
ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status, fast_rx);
if (*fast_rx)
return 0;
@@ -3288,6 +3324,9 @@ mic_fail:
RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
skb_pull(msdu, hal_rx_desc_sz);
+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu))
+ return -EINVAL;
+
ath12k_dp_rx_h_ppdu(ar, rx_desc, rxs);
ath12k_dp_rx_h_undecap(ar, msdu, rx_desc,
HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
@@ -3999,6 +4038,10 @@ static int ath12k_dp_rx_h_null_q_desc(st
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
}
+
+ if (ath12k_dp_rx_check_msdu_header_len(ar, desc, msdu))
+ return -EINVAL;
+
ath12k_dp_rx_h_ppdu(ar, desc, status);
fast_rx = false;
ath12k_dp_rx_h_mpdu(ar, msdu, desc, status, &fast_rx);
@@ -4084,6 +4127,9 @@ static bool ath12k_dp_rx_h_tkip_mic_err(
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+ if (ath12k_dp_rx_check_msdu_header_len(ar, desc, msdu))
+ return true;
+
ath12k_dp_rx_h_ppdu(ar, desc, status);
status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
@@ -4125,6 +4171,9 @@ static bool ath12k_dp_rx_h_4addr_null_fr
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
+ if (ath12k_dp_rx_check_msdu_header_len(ar, rx_desc, msdu))
+ return true;
+
ath12k_dp_rx_h_ppdu(ar, rx_desc, status);
ath12k_dp_rx_h_mpdu(ar, msdu, rx_desc, status, &fast_rx);