From 5d42d095c5a898bf670f0271053fee4d9be0827d Mon Sep 17 00:00:00 2001 From: Manish Dharanenthiran Date: Mon, 19 Dec 2022 14:24:55 +0530 Subject: [PATCH] ath12k: 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 --- drivers/net/wireless/ath/ath12k/dp_rx.c | 51 +++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -2940,6 +2940,31 @@ static void ath12k_dp_rx_deliver_msdu(st } } +static bool ath12k_dp_rx_check_max_nwifi_hdr_len(struct ath12k_base *ab, + struct hal_rx_desc *rx_desc, + struct sk_buff *msdu) +{ + u8 decap_type; + struct ieee80211_hdr *hdr; + u32 hdr_len; + + 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 int ath12k_dp_rx_process_msdu(struct ath12k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list, @@ -2999,6 +3024,11 @@ static int ath12k_dp_rx_process_msdu(str } } + if (ath12k_dp_rx_check_max_nwifi_hdr_len(ab, 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; @@ -4066,6 +4096,9 @@ 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_max_nwifi_hdr_len(ab, 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); @@ -4194,6 +4227,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_max_nwifi_hdr_len(ab, 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);