From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A2275964F6; Mon, 31 Aug 2026 13:51:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788184282; cv=none; b=UIlywbf08HGa6dTglLRENdRHVN6i8bpi1z6JQazOAA5cSUqrJZXdZ1dthXXFYzGMY1WfquPOeFEr6ma7Z6MefKuhth41k1yKNE0Islu+v7TgFbV0c/rp2GgfcXx/b0lSzLplbOgc2x9pBIJZbDsxu3JXYDLajCo71fg3i7MjtqY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788184282; c=relaxed/simple; bh=7DQPlXEzN7WI/ZJhNp1OCOCeojyf0YI5nPKpWjPOezw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fH0vK3lPWYSkgVI0Yu+A5fZnhbLN6iLlkXWuZ5RM/0Dz6enz0Y36YaWO2kweoU3jUl67maFl6rgMSk4GqyPEBXSLITb4WJquiZUBsF0sTRAgi++oLGYzbyAHOukf1aW+VRZqX8BBAbCGdb/q3jbfJUVDlp7+xFqq/gawnTfveas= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TKwFqX6j; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TKwFqX6j" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CAB631F00A3D; Mon, 31 Aug 2026 13:51:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788184280; bh=JcFqPQ4TWgXMnuZg61x6R9zAyZTT0bouo2OLeij6rhA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TKwFqX6j44cQfaj+wnVOw8es1MnZZ6IY3hlkJctVp0b998Iyb6q15MR6ZCQPWNbnh 6ubOeaKyFguozVIxwKHrStnYJ8YDMcE+ClyG2kQnm4mhKORzKgfCaHjHI+vXWxouhR BsTEaNDK59Jb7Xq126Nsap66zGYmrjBbQ6ISchQ+0cq0VHO3jobzO6yCXu+g69AtYd sgKSwR4djguYLWnHJ2i2enitKQ/DkeU5L0mXBO4eFc9bHjmxQzt6j5oFZNwjPV1p+/ wu4qXzwLqvwhgWPfSmVLbUVNRPhIj6M/PUucah9Xf+DnKaARm9eXJKlvacHlTxwZGU c5kHQI37ri8Wg== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Miaoqing Pan , Rameshkumar Sundaram , Baochen Qiang , Jeff Johnson , Sasha Levin , jjohnson@kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 6.18-6.1] wifi: ath11k: fix invalid data access in ath11k_dp_rx_h_undecap_nwifi Date: Mon, 31 Aug 2026 09:30:26 -0400 Message-ID: <20260831133314.4125787-598-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org> References: <20260831133314.4125787-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.18.48 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Miaoqing Pan [ Upstream commit 6b471e9aefee9ed73278eb1141e0d8530a56fae9 ] In certain cases, hardware might provide packets with a length greater than the maximum native Wi-Fi header length. This can lead to accessing and modifying fields in the header within the ath11k_dp_rx_h_undecap_nwifi() function for the DP_RX_DECAP_TYPE_NATIVE_WIFI decap type and potentially result in invalid data access and memory corruption. Kernel stack is corrupted in: ath11k_dp_rx_h_undecap+0x6b0/0x6b0 [ath11k] Call trace: ath11k_dp_rx_h_mpdu+0x0/0x2e8 [ath11k] ath11k_dp_rx_h_mpdu+0x1e0/0x2e8 [ath11k] ath11k_dp_rx_wbm_err+0x1e0/0x450 [ath11k] ath11k_dp_rx_process_wbm_err+0x2fc/0x460 [ath11k] ath11k_dp_service_srng+0x2e0/0x348 [ath11k] Add a sanity check before processing the SKB to prevent invalid data access in the undecap native Wi-Fi function for the DP_RX_DECAP_TYPE_NATIVE_WIFI decap type. This adapted from the discussion/patch of the ath12k driver [1]. Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 Link: https://lore.kernel.org/linux-wireless/20250211090302.4105141-1-tamizh.raja@oss.qualcomm.com/ # [1] Signed-off-by: Miaoqing Pan Reviewed-by: Rameshkumar Sundaram Reviewed-by: Baochen Qiang Link: https://patch.msgid.link/20260512022351.2033155-2-miaoqing.pan@oss.qualcomm.com Signed-off-by: Jeff Johnson Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: The background searches finished and match the earlier analysis: - **Ath11k fix not in tree** — `git log --grep` found no commit for `ath11k_dp_rx_check_nwifi_hdr_len_valid` or the ath11k undecap_nwifi fix. - **Ath12k analogue present** — `9a0dddfb30f12` (`wifi: ath12k: Fix invalid data access in ath12k_dp_rx_h_undecap_nwifi`) is already in v6.18.44. That supports the **YES** backport verdict: the bug is still present in ath11k here, and the fix is a proven port of code already merged for ath12k in this tree. drivers/net/wireless/ath/ath11k/dp_rx.c | 50 +++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 330446f279cd6..1514f8657d546 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2501,6 +2501,29 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap ieee80211_rx_napi(ar->hw, pubsta, msdu, napi); } +static bool ath11k_dp_rx_check_nwifi_hdr_len_valid(struct ath11k_base *ab, + struct hal_rx_desc *rx_desc, + struct sk_buff *msdu) +{ + struct ieee80211_hdr *hdr; + u8 decap_type; + u32 hdr_len; + + decap_type = ath11k_dp_rx_h_msdu_start_decap_type(ab, rx_desc); + if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI) + return true; + + hdr = (struct ieee80211_hdr *)msdu->data; + hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN)) + return true; + + ab->soc_stats.invalid_rbm++; + WARN_ON_ONCE(1); + return false; +} + static int ath11k_dp_rx_process_msdu(struct ath11k *ar, struct sk_buff *msdu, struct sk_buff_head *msdu_list, @@ -2571,6 +2594,11 @@ static int ath11k_dp_rx_process_msdu(struct ath11k *ar, } } + if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) { + ret = -EINVAL; + goto free_out; + } + ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status); ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status); @@ -3306,6 +3334,12 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED; skb_pull(msdu, hal_rx_desc_sz); + if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, rx_desc, + msdu))) { + dev_kfree_skb_any(msdu); + return -EINVAL; + } + ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs); ath11k_dp_rx_h_undecap(ar, msdu, rx_desc, HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true); @@ -3998,6 +4032,10 @@ static int ath11k_dp_rx_h_null_q_desc(struct ath11k *ar, struct sk_buff *msdu, skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); } + + if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, desc, msdu))) + return -EINVAL; + ath11k_dp_rx_h_ppdu(ar, desc, status); ath11k_dp_rx_h_mpdu(ar, msdu, desc, status); @@ -4042,7 +4080,7 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu, 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; @@ -4050,6 +4088,7 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, u8 l3pad_bytes; struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz; + struct ath11k_base *ab = ar->ab; rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(ar->ab, desc); rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(ar->ab, desc); @@ -4059,6 +4098,9 @@ static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu, skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len); skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes); + if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu))) + return true; + ath11k_dp_rx_h_ppdu(ar, desc, status); status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR | @@ -4066,19 +4108,21 @@ 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, struct ieee80211_rx_status *status) { struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu); - bool drop = false; + bool drop; ar->ab->soc_stats.rxdma_error[rxcb->err_code]++; 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.53.0