From d762e0422fc0636f1eec53ebbec23a2258058734 Mon Sep 17 00:00:00 2001 From: P Praneesh 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 Signed-off-by: P Praneesh --- 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