Skip to content

Commit 04bf617

Browse files
authored
wifi: ath11k/ath12k: dp rx sanity checks for invalid length in error paths (#564)
wifi: ath11k/ath12k: dp rx sanity checks for invalid length in error paths
2 parents 1dc6798 + 0e37411 commit 04bf617

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

drivers/net/wireless/ath/ath11k/dp_rx.c

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,6 +2502,29 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
25022502
ieee80211_rx_napi(ar->hw, pubsta, msdu, napi);
25032503
}
25042504

2505+
static bool ath11k_dp_rx_check_nwifi_hdr_len_valid(struct ath11k_base *ab,
2506+
struct hal_rx_desc *rx_desc,
2507+
struct sk_buff *msdu)
2508+
{
2509+
struct ieee80211_hdr *hdr;
2510+
u8 decap_type;
2511+
u32 hdr_len;
2512+
2513+
decap_type = ath11k_dp_rx_h_msdu_start_decap_type(ab, rx_desc);
2514+
if (decap_type != DP_RX_DECAP_TYPE_NATIVE_WIFI)
2515+
return true;
2516+
2517+
hdr = (struct ieee80211_hdr *)msdu->data;
2518+
hdr_len = ieee80211_hdrlen(hdr->frame_control);
2519+
2520+
if ((likely(hdr_len <= DP_MAX_NWIFI_HDR_LEN)))
2521+
return true;
2522+
2523+
ab->soc_stats.invalid_rbm++;
2524+
WARN_ON_ONCE(1);
2525+
return false;
2526+
}
2527+
25052528
static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
25062529
struct sk_buff *msdu,
25072530
struct sk_buff_head *msdu_list,
@@ -2572,6 +2595,11 @@ static int ath11k_dp_rx_process_msdu(struct ath11k *ar,
25722595
}
25732596
}
25742597

2598+
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, rx_desc, msdu))) {
2599+
ret = -EINVAL;
2600+
goto free_out;
2601+
}
2602+
25752603
ath11k_dp_rx_h_ppdu(ar, rx_desc, rx_status);
25762604
ath11k_dp_rx_h_mpdu(ar, msdu, rx_desc, rx_status);
25772605

@@ -3307,6 +3335,12 @@ static int ath11k_dp_rx_h_verify_tkip_mic(struct ath11k *ar, struct ath11k_peer
33073335
RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED;
33083336
skb_pull(msdu, hal_rx_desc_sz);
33093337

3338+
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, rx_desc,
3339+
msdu))) {
3340+
dev_kfree_skb_any(msdu);
3341+
return -EINVAL;
3342+
}
3343+
33103344
ath11k_dp_rx_h_ppdu(ar, rx_desc, rxs);
33113345
ath11k_dp_rx_h_undecap(ar, msdu, rx_desc,
33123346
HAL_ENCRYPT_TYPE_TKIP_MIC, rxs, true);
@@ -3999,6 +4033,10 @@ static int ath11k_dp_rx_h_null_q_desc(struct ath11k *ar, struct sk_buff *msdu,
39994033
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
40004034
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
40014035
}
4036+
4037+
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ar->ab, desc, msdu)))
4038+
return -EINVAL;
4039+
40024040
ath11k_dp_rx_h_ppdu(ar, desc, status);
40034041

40044042
ath11k_dp_rx_h_mpdu(ar, msdu, desc, status);
@@ -4043,43 +4081,58 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu,
40434081
return drop;
40444082
}
40454083

4046-
static void ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
4084+
static bool ath11k_dp_rx_h_tkip_mic_err(struct ath11k *ar, struct sk_buff *msdu,
40474085
struct ieee80211_rx_status *status)
40484086
{
40494087
u16 msdu_len;
40504088
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
40514089
u8 l3pad_bytes;
40524090
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
40534091
u32 hal_rx_desc_sz = ar->ab->hw_params.hal_desc_sz;
4092+
struct ath11k_base *ab = ar->ab;
40544093

40554094
rxcb->is_first_msdu = ath11k_dp_rx_h_msdu_end_first_msdu(ar->ab, desc);
40564095
rxcb->is_last_msdu = ath11k_dp_rx_h_msdu_end_last_msdu(ar->ab, desc);
40574096

40584097
l3pad_bytes = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, desc);
40594098
msdu_len = ath11k_dp_rx_h_msdu_start_msdu_len(ar->ab, desc);
4099+
4100+
if (unlikely(hal_rx_desc_sz + l3pad_bytes + msdu_len > DP_RX_BUFFER_SIZE)) {
4101+
ath11k_dbg(ab, ATH11K_DBG_DATA,
4102+
"invalid msdu len in tkip mic err %u\n", msdu_len);
4103+
ath11k_dbg_dump(ab, ATH11K_DBG_DATA, NULL, "", desc,
4104+
sizeof(*desc));
4105+
return true;
4106+
}
4107+
40604108
skb_put(msdu, hal_rx_desc_sz + l3pad_bytes + msdu_len);
40614109
skb_pull(msdu, hal_rx_desc_sz + l3pad_bytes);
40624110

4111+
if (unlikely(!ath11k_dp_rx_check_nwifi_hdr_len_valid(ab, desc, msdu)))
4112+
return true;
4113+
40634114
ath11k_dp_rx_h_ppdu(ar, desc, status);
40644115

40654116
status->flag |= (RX_FLAG_MMIC_STRIPPED | RX_FLAG_MMIC_ERROR |
40664117
RX_FLAG_DECRYPTED);
40674118

40684119
ath11k_dp_rx_h_undecap(ar, msdu, desc,
40694120
HAL_ENCRYPT_TYPE_TKIP_MIC, status, false);
4121+
4122+
return false;
40704123
}
40714124

40724125
static bool ath11k_dp_rx_h_rxdma_err(struct ath11k *ar, struct sk_buff *msdu,
40734126
struct ieee80211_rx_status *status)
40744127
{
40754128
struct ath11k_skb_rxcb *rxcb = ATH11K_SKB_RXCB(msdu);
4076-
bool drop = false;
4129+
bool drop;
40774130

40784131
ar->ab->soc_stats.rxdma_error[rxcb->err_code]++;
40794132

40804133
switch (rxcb->err_code) {
40814134
case HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR:
4082-
ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
4135+
drop = ath11k_dp_rx_h_tkip_mic_err(ar, msdu, status);
40834136
break;
40844137
default:
40854138
/* TODO: Review other rxdma error code to check if anything is

drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,8 +1031,10 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
10311031
skb_pull(msdu, hal_rx_desc_sz);
10321032

10331033
if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
1034-
rx_info)))
1034+
rx_info))) {
1035+
dev_kfree_skb_any(msdu);
10351036
return -EINVAL;
1037+
}
10361038

10371039
ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
10381040
ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,

0 commit comments

Comments
 (0)