Prechádzať zdrojové kódy

qcacmn: Fix use after free of SKB in DP trace path

qdf_dp_trace could access nbuf already freed after sending to CE ring.
Move trace log before sending skb and add error log when fail to send.

Change-Id: I8ce36b9d196b7d44e0e9f7dcfe05db404a77e32f
CRs-Fixed: 2090277
Yun Park 7 rokov pred
rodič
commit
c60a22b88d
3 zmenil súbory, kde vykonal 24 pridanie a 1 odobranie
  1. 17 1
      hif/src/ce/ce_service.c
  2. 2 0
      qdf/inc/qdf_trace.h
  3. 5 0
      qdf/linux/src/qdf_trace.c

+ 17 - 1
hif/src/ce/ce_service.c

@@ -712,6 +712,17 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu,
 	enum hif_ce_event_type type = FAST_TX_SOFTWARE_INDEX_UPDATE;
 	bool ok_to_send = true;
 
+	/*
+	 * Create a log assuming the call will go through, and if not, we would
+	 * add an error trace as well.
+	 * Please add the same failure log for any additional error paths.
+	 */
+	DPTRACE(qdf_dp_trace(msdu,
+			QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD,
+			QDF_TRACE_DEFAULT_PDEV_ID,
+			qdf_nbuf_data_addr(msdu),
+			sizeof(qdf_nbuf_data(msdu)), QDF_TX));
+
 	qdf_spin_lock_bh(&ce_state->ce_index_lock);
 
 	/*
@@ -741,6 +752,12 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu,
 		if (ok_to_send)
 			Q_TARGET_ACCESS_END(scn);
 		qdf_spin_unlock_bh(&ce_state->ce_index_lock);
+
+		DPTRACE(qdf_dp_trace(NULL,
+				QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD,
+				QDF_TRACE_DEFAULT_PDEV_ID,
+				NULL, 0, QDF_TX));
+
 		return 0;
 	}
 
@@ -845,7 +862,6 @@ int ce_send_fast(struct CE_handle *copyeng, qdf_nbuf_t msdu,
 		hif_pm_runtime_put(hif_hdl);
 	}
 
-
 	qdf_spin_unlock_bh(&ce_state->ce_index_lock);
 
 	/* sent 1 packet */

+ 2 - 0
qdf/inc/qdf_trace.h

@@ -190,6 +190,7 @@ typedef struct s_qdf_trace_data {
  * @QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD - Lithium DP layer ptr record
  * @QDF_DP_TRACE_CE_PACKET_PTR_RECORD - CE layer ptr record
  * @QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD- CE fastpath ptr record
+ * @QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD- CE fastpath error record
  * @QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD - HTT RX record
  * @QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD- HTT RX offload record
  * @QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD - HDD RX record
@@ -230,6 +231,7 @@ enum  QDF_DP_TRACE_ID {
 	QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD,
 	QDF_DP_TRACE_CE_PACKET_PTR_RECORD,
 	QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD,
+	QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD,
 	QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD,
 	QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD,
 	QDF_DP_TRACE_RX_LI_DP_PACKET_PTR_RECORD,

+ 5 - 0
qdf/linux/src/qdf_trace.c

@@ -1024,6 +1024,8 @@ const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
 		return "CE: TX: PTR:";
 	case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
 		return "CE: TX: FAST: PTR:";
+	case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
+		return "CE: TX: FAST: ERR:";
 	case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
 		return "FREE: TX: PTR:";
 	case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
@@ -1842,6 +1844,9 @@ void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord,
 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
 		break;
+	case  QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
+		DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
+		break;
 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
 	case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD: