summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgbian <gbian@qti.qualcomm.com>2016-07-11 13:49:27 +0800
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-07-12 16:41:22 +0530
commit9dffd0e1910b43eafe3e4b02c1f67880be3fe90f (patch)
treea5bf3b4aa07098070fb37d88dad78b52b0038de0
parente6596d488894e07acb66769d15dd8a975dfd9922 (diff)
qcacld-2.0: Fix skb corruption in fragment RX handling
Add packet length check for HTT_T2H_MSG_TYPE_RX_FRAG_IND message. Do not clone the RX frag buffer in the ol_rx_fraglist_insert, and all buffer will be freed by ol_rx_frag_indication_handler or upper layer to avoid double free issue. Change-Id: I977ed9109a476a092dfb298386625a707bc98191 CRs-Fixed: 1039135
-rw-r--r--CORE/CLD_TXRX/HTT/htt_t2h.c35
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_rx_defrag.c8
2 files changed, 35 insertions, 8 deletions
diff --git a/CORE/CLD_TXRX/HTT/htt_t2h.c b/CORE/CLD_TXRX/HTT/htt_t2h.c
index aa8c43cafa42..b736a970c575 100644
--- a/CORE/CLD_TXRX/HTT/htt_t2h.c
+++ b/CORE/CLD_TXRX/HTT/htt_t2h.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -214,11 +214,44 @@ htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg )
tid = HTT_RX_FRAG_IND_EXT_TID_GET(*msg_word);
HTT_RX_FRAG_SET_LAST_MSDU(pdev, htt_t2h_msg);
+ /* If packet len is invalid, will discard this frame. */
+ if (pdev->cfg.is_high_latency) {
+ u_int32_t rx_pkt_len = 0;
+
+ rx_pkt_len = adf_nbuf_len(htt_t2h_msg);
+
+ if (rx_pkt_len < (HTT_RX_FRAG_IND_BYTES +
+ sizeof(struct hl_htt_rx_ind_base)+
+ sizeof(struct ieee80211_frame))) {
+
+ adf_os_print("%s: invalid packet len, %u\n",
+ __FUNCTION__,
+ rx_pkt_len);
+ /*
+ * This buf will be freed before
+ * exiting this function.
+ */
+ break;
+ }
+ }
+
ol_rx_frag_indication_handler(
pdev->txrx_pdev,
htt_t2h_msg,
peer_id,
tid);
+
+ if (pdev->cfg.is_high_latency) {
+ /*
+ * For high latency solution, HTT_T2H_MSG_TYPE_RX_FRAG_IND
+ * message and RX packet share the same buffer. All buffer will
+ * be freed by ol_rx_frag_indication_handler or upper layer to
+ * avoid double free issue.
+ *
+ */
+ return;
+ }
+
break;
}
case HTT_T2H_MSG_TYPE_RX_ADDBA:
diff --git a/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c b/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c
index cdbcc7667d07..b084889eb040 100644
--- a/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c
+++ b/CORE/CLD_TXRX/TXRX/ol_rx_defrag.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -128,14 +128,11 @@ static inline void OL_RX_FRAG_PULL_HDR(htt_pdev_handle htt_pdev,
rx_desc_len = htt_rx_msdu_rx_desc_size_hl(htt_pdev, rx_desc);
adf_nbuf_pull_head(frag, rx_desc_len + hdrsize);
}
-#define OL_RX_FRAG_CLONE(frag) \
- adf_nbuf_clone(frag)
#else
#define OL_RX_FRAG_GET_MAC_HDR(pdev, frag) \
(struct ieee80211_frame *) adf_nbuf_data(frag)
#define OL_RX_FRAG_PULL_HDR(pdev, frag, hdrsize) \
adf_nbuf_pull_head(frag, hdrsize);
-#define OL_RX_FRAG_CLONE(frag) NULL/* no-op */
#endif /* CONFIG_HL_SUPPORT */
static inline void
@@ -353,11 +350,8 @@ ol_rx_fraglist_insert(
struct ieee80211_frame *mac_hdr, *cmac_hdr, *next_hdr, *lmac_hdr;
u_int8_t fragno, cur_fragno, lfragno, next_fragno;
u_int8_t last_morefrag = 1, count = 0;
- adf_nbuf_t frag_clone;
adf_os_assert(frag);
- frag_clone = OL_RX_FRAG_CLONE(frag);
- frag = frag_clone ? frag_clone : frag;
mac_hdr = (struct ieee80211_frame *) OL_RX_FRAG_GET_MAC_HDR(htt_pdev, frag);
fragno = adf_os_le16_to_cpu(*(u_int16_t *) mac_hdr->i_seq) &