Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 56 additions & 3 deletions drivers/net/wireless/ath/ath11k/dp_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -3308,6 +3336,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);
Expand Down Expand Up @@ -4000,6 +4034,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);
Expand Down Expand Up @@ -4044,43 +4082,58 @@ 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;
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
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);

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 (unlikely(hal_rx_desc_sz + l3pad_bytes + msdu_len > DP_RX_BUFFER_SIZE)) {
ath11k_dbg(ab, ATH11K_DBG_DATA,
"invalid msdu len in tkip mic err %u\n", msdu_len);
ath11k_dbg_dump(ab, ATH11K_DBG_DATA, NULL, "", desc,
sizeof(*desc));
return true;
}

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 |
RX_FLAG_DECRYPTED);

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
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,10 @@ static int ath12k_wifi7_dp_rx_h_verify_tkip_mic(struct ath12k_pdev_dp *dp_pdev,
skb_pull(msdu, hal_rx_desc_sz);

if (unlikely(!ath12k_dp_rx_check_nwifi_hdr_len_valid(dp, rx_desc, msdu,
rx_info)))
rx_info))) {
dev_kfree_skb_any(msdu);
return -EINVAL;
}

ath12k_dp_rx_h_ppdu(dp_pdev, rx_info);
ath12k_dp_rx_h_undecap(dp_pdev, msdu, rx_desc,
Expand Down