From 32e367fdd5be9fffb5c9a7ee218694d762254fca Mon Sep 17 00:00:00 2001 From: gbian Date: Mon, 31 Oct 2016 14:05:50 +0800 Subject: qcacld-3.0: Fix skb corruption in fragment RX handling qcacld-2.0 to qcacld-3.0 propagation 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 --- core/dp/htt/htt_t2h.c | 34 ++++++++++++++++++++++++++++++++++ core/dp/txrx/ol_rx_defrag.c | 21 --------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 9d044f3e8c0b..de70e0c03367 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -232,9 +232,43 @@ void htt_t2h_lp_msg_handler(void *context, qdf_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 = qdf_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))) { + + qdf_print("%s: invalid packet len, %u\n", + __func__, + 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/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index 76cec6117f72..e158bc1a6bcb 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -143,18 +143,6 @@ static void ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev, qdf_nbuf_pull_head(frag, rx_desc_len + hdrsize); } -/** - * ol_rx_frag_clone() - clone the rx frag - * @frag: rx fragment to clone from - * - * Return: cloned buffer - */ -static inline qdf_nbuf_t -ol_rx_frag_clone(qdf_nbuf_t frag) -{ - return qdf_nbuf_clone(frag); -} - /** * ol_rx_frag_desc_adjust() - adjust rx frag descriptor position * @pdev: pointer to txrx handle @@ -271,12 +259,6 @@ static inline void ol_rx_frag_pull_hdr(htt_pdev_handle htt_pdev, qdf_nbuf_pull_head(frag, hdrsize); } -static inline qdf_nbuf_t -ol_rx_frag_clone(qdf_nbuf_t frag) -{ - return NULL; -} - static inline void ol_rx_frag_desc_adjust(ol_txrx_pdev_handle pdev, qdf_nbuf_t msdu, @@ -493,11 +475,8 @@ ol_rx_fraglist_insert(htt_pdev_handle htt_pdev, struct ieee80211_frame *mac_hdr, *cmac_hdr, *next_hdr, *lmac_hdr; uint8_t fragno, cur_fragno, lfragno, next_fragno; uint8_t last_morefrag = 1, count = 0; - qdf_nbuf_t frag_clone; qdf_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); -- cgit v1.2.3