mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-24 21:02:35 +00:00
137 lines
4.9 KiB
Diff
137 lines
4.9 KiB
Diff
From c8fa79e48e36b54641204812f6976c2d8375b315 Mon Sep 17 00:00:00 2001
|
|
From: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
|
|
Date: Fri, 4 Nov 2022 12:54:36 +0530
|
|
Subject: [PATCH] ath12k: Check skb_headroom before using skb_push
|
|
|
|
Kernel panic may occur if there is no
|
|
skb_headroom available for performing skb_push.
|
|
|
|
Added check to perform length calculation to
|
|
prevent skb_push if the length is overrides the
|
|
skb headroom.
|
|
|
|
Signed-off-by: Tamizh Chelvam Raja <quic_tamizhr@quicinc.com>
|
|
Signed-off-by: Manish Dharanenthiran <quic_mdharane@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/dp_rx.c | 41 +++++++++++++++++++++++++
|
|
1 file changed, 41 insertions(+)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
|
|
@@ -2305,6 +2305,7 @@ static void ath12k_dp_rx_h_undecap_nwifi
|
|
u8 decap_hdr[DP_MAX_NWIFI_HDR_LEN];
|
|
struct ieee80211_hdr *hdr;
|
|
size_t hdr_len;
|
|
+ int expand_by = 0;
|
|
u8 *crypto_hdr;
|
|
u16 qos_ctl = 0;
|
|
|
|
@@ -2331,15 +2332,31 @@ static void ath12k_dp_rx_h_undecap_nwifi
|
|
|
|
/* Rebuild crypto header for mac80211 use */
|
|
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
|
+ if (skb_headroom(msdu) < ath12k_dp_rx_crypto_param_len(ar, enctype)) {
|
|
+ expand_by = ath12k_dp_rx_crypto_param_len(ar, enctype) - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
crypto_hdr = skb_push(msdu, ath12k_dp_rx_crypto_param_len(ar, enctype));
|
|
ath12k_dp_rx_desc_get_crypto_header(ar->ab,
|
|
rxcb->rx_desc, crypto_hdr,
|
|
enctype);
|
|
}
|
|
|
|
+ if (skb_headroom(msdu) < IEEE80211_QOS_CTL_LEN) {
|
|
+ expand_by = IEEE80211_QOS_CTL_LEN - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
memcpy(skb_push(msdu,
|
|
IEEE80211_QOS_CTL_LEN), &qos_ctl,
|
|
IEEE80211_QOS_CTL_LEN);
|
|
+
|
|
+ if (skb_headroom(msdu) < hdr_len) {
|
|
+ expand_by = hdr_len - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
memcpy(skb_push(msdu, hdr_len), decap_hdr, hdr_len);
|
|
}
|
|
|
|
@@ -2414,16 +2431,27 @@ static void ath12k_get_dot11_hdr_from_rx
|
|
struct ieee80211_hdr *hdr;
|
|
u16 qos_ctl = 0;
|
|
__le16 fc;
|
|
+ int expand_by;
|
|
u8 *crypto_hdr;
|
|
|
|
if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
|
|
crypto_len = ath12k_dp_rx_crypto_param_len(ar, enctype);
|
|
+ if (skb_headroom(msdu) < crypto_len) {
|
|
+ expand_by = crypto_len - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
crypto_hdr = skb_push(msdu, crypto_len);
|
|
ath12k_dp_rx_desc_get_crypto_header(ab, rx_desc, crypto_hdr, enctype);
|
|
}
|
|
|
|
fc = cpu_to_le16(ath12k_dp_rxdesc_get_mpdu_frame_ctrl(ab, rx_desc));
|
|
hdr_len = ieee80211_hdrlen(fc);
|
|
+ if (skb_headroom(msdu) < hdr_len) {
|
|
+ expand_by = hdr_len - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
skb_push(msdu, hdr_len);
|
|
hdr = (struct ieee80211_hdr *)msdu->data;
|
|
hdr->frame_control = fc;
|
|
@@ -2455,6 +2483,7 @@ static void ath12k_dp_rx_h_undecap_eth(s
|
|
struct ethhdr *eth;
|
|
u8 da[ETH_ALEN];
|
|
u8 sa[ETH_ALEN];
|
|
+ int expand_by;
|
|
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
|
struct ath12k_dp_rx_rfc1042_hdr rfc = {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}};
|
|
|
|
@@ -2463,6 +2492,11 @@ static void ath12k_dp_rx_h_undecap_eth(s
|
|
ether_addr_copy(sa, eth->h_source);
|
|
rfc.snap_type = eth->h_proto;
|
|
skb_pull(msdu, sizeof(struct ethhdr));
|
|
+ if (skb_headroom(msdu) < sizeof(struct ath12k_dp_rx_rfc1042_hdr)) {
|
|
+ expand_by = sizeof(struct ath12k_dp_rx_rfc1042_hdr) - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ return;
|
|
+ }
|
|
memcpy(skb_push(msdu, sizeof(struct ath12k_dp_rx_rfc1042_hdr)), &rfc,
|
|
sizeof(struct ath12k_dp_rx_rfc1042_hdr));
|
|
ath12k_get_dot11_hdr_from_rx_desc(ar, msdu, rxcb, status, enctype);
|
|
@@ -2860,6 +2894,7 @@ static void ath12k_dp_rx_deliver_msdu(st
|
|
struct ath12k_peer *peer;
|
|
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
|
u8 decap = DP_RX_DECAP_TYPE_RAW;
|
|
+ int expand_by;
|
|
bool is_mcbc = rxcb->is_mcbc;
|
|
bool is_eapol = rxcb->is_eapol;
|
|
struct ath12k_link_sta *arsta = NULL;
|
|
@@ -2867,6 +2902,11 @@ static void ath12k_dp_rx_deliver_msdu(st
|
|
|
|
if (status->encoding == RX_ENC_HE && !(status->flag & RX_FLAG_RADIOTAP_HE) &&
|
|
!(status->flag & RX_FLAG_SKIP_MONITOR)) {
|
|
+ if (skb_headroom(msdu) < sizeof(known)) {
|
|
+ expand_by = sizeof(known) - skb_headroom(msdu);
|
|
+ if (WARN_ON_ONCE(pskb_expand_head(msdu, expand_by, 0, GFP_ATOMIC)))
|
|
+ goto exit;
|
|
+ }
|
|
he = skb_push(msdu, sizeof(known));
|
|
memcpy(he, &known, sizeof(known));
|
|
status->flag |= RX_FLAG_RADIOTAP_HE;
|
|
@@ -2924,6 +2964,7 @@ static void ath12k_dp_rx_deliver_msdu(st
|
|
!(is_mcbc && rx_status->flag & RX_FLAG_DECRYPTED))
|
|
rx_status->flag |= RX_FLAG_8023;
|
|
|
|
+exit:
|
|
ieee80211_rx_napi(ar->ah->hw, pubsta, msdu, napi);
|
|
|
|
if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
|