Преглед на файлове

qcacmn: Validate nbuf while processing MPDU/MSDU level TLVs

nbuf could be freed when some error conditions are hit so
always validate nbuf while processing MPDU/MSDU level TLVs.

Change-Id: I5e0756bc8ba0a8c68c6ce8d2886b5b63068626a0
CRs-Fixed: 3318966
Jeevan Kukkalli преди 2 години
родител
ревизия
b0b3b2a793
променени са 2 файла, в които са добавени 25 реда и са изтрити 0 реда
  1. 16 0
      dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c
  2. 9 0
      qdf/linux/src/i_qdf_nbuf.h

+ 16 - 0
dp/wifi3.0/monitor/2.0/dp_rx_mon_2.0.c

@@ -1205,6 +1205,10 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 		}
 
 		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
+		if (qdf_unlikely(!nbuf)) {
+			dp_mon_debug("nbuf is NULL");
+			return num_buf_reaped;
+		}
 
 		if (mpdu_info->decap_type == DP_MON_DECAP_FORMAT_INVALID) {
 			/* decap type is invalid, drop the frame */
@@ -1305,6 +1309,10 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 			break;
 		}
 		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
+		if (qdf_unlikely(!nbuf)) {
+			dp_mon_debug("nbuf is NULL");
+			break;
+		}
 		num_frags = qdf_nbuf_get_nr_frags(nbuf);
 		if (ppdu_info->mpdu_info[user_id].decap_type ==
 				HAL_HW_RX_DECAP_FORMAT_RAW) {
@@ -1343,6 +1351,10 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 			break;
 		}
 		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
+		if (qdf_unlikely(!nbuf)) {
+			dp_mon_debug("nbuf is NULL");
+			break;
+		}
 		mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
 		mpdu_info = &ppdu_info->mpdu_info[user_id];
 		mpdu_meta->decap_type = mpdu_info->decap_type;
@@ -1361,6 +1373,10 @@ uint8_t dp_rx_mon_process_tlv_status(struct dp_pdev *pdev,
 			break;
 		}
 		nbuf = qdf_nbuf_queue_last(&ppdu_info->mpdu_q[user_id]);
+		if (qdf_unlikely(!nbuf)) {
+			dp_mon_debug("nbuf is NULL");
+			break;
+		}
 		mpdu_meta = (struct hal_rx_mon_mpdu_info *)qdf_nbuf_data(nbuf);
 		mpdu_meta->mpdu_length_err = mpdu_info->mpdu_length_err;
 		mpdu_meta->fcs_err = mpdu_info->fcs_err;

+ 9 - 0
qdf/linux/src/i_qdf_nbuf.h

@@ -1805,12 +1805,21 @@ __qdf_nbuf_queue_insert_head(__qdf_nbuf_queue_t *qhead, __qdf_nbuf_t skb)
 	qhead->qlen++;
 }
 
+/**
+ * __qdf_nbuf_queue_remove_last() - remove a skb from the tail of the queue
+ * @qhead: Queue head
+ *
+ * This is a lockless version. Driver should take care of the locks
+ *
+ * Return: skb or NULL
+ */
 static inline struct sk_buff *
 __qdf_nbuf_queue_remove_last(__qdf_nbuf_queue_t *qhead)
 {
 	__qdf_nbuf_t tmp_tail, node = NULL;
 
 	if (qhead->head) {
+		qhead->qlen--;
 		tmp_tail = qhead->tail;
 		node = qhead->head;
 		if (qhead->head == qhead->tail) {