mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
wifi: ath11k: fix invalid data access in ath11k_dp_rx_h_undecap_nwifi
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 <miaoqing.pan@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Link: https://patch.msgid.link/20260512022351.2033155-2-miaoqing.pan@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
parent
c7427f297d
commit
6b471e9aef
|
|
@ -2503,6 +2503,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,
|
||||
|
|
@ -2573,6 +2596,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);
|
||||
|
||||
|
|
@ -3262,6 +3290,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);
|
||||
|
|
@ -3954,6 +3988,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);
|
||||
|
|
@ -3998,7 +4036,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;
|
||||
|
|
@ -4006,6 +4044,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);
|
||||
|
|
@ -4015,6 +4054,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 |
|
||||
|
|
@ -4022,19 +4064,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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user