Browse Source

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
gbian 8 years ago
parent
commit
2e02659bfe
2 changed files with 34 additions and 21 deletions
  1. 34 0
      core/dp/htt/htt_t2h.c
  2. 0 21
      core/dp/txrx/ol_rx_defrag.c

+ 34 - 0
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:

+ 0 - 21
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);