Przeglądaj źródła

qcacmn: Validate the rx descriptor before dereferencing

The rx descriptor obtained using the cookie
can be NULL if the cookie is invalid. Hence
dereferencing the rx descriptor without any
validation can cause invalid address access.

Fix this by validating the rx descriptor
which has been obtained using the cookie from
the hal ring descriptor.

Change-Id: Ib584f0d8175b581d15b0e1c67d2f6ed9119ecbfc
CRs-Fixed: 2629254
Rakesh Pillai 5 lat temu
rodzic
commit
7a26da4e7e
3 zmienionych plików z 46 dodań i 1 usunięć
  1. 41 1
      dp/wifi3.0/dp_rx.c
  2. 3 0
      dp/wifi3.0/dp_stats.c
  3. 2 0
      dp/wifi3.0/dp_types.h

+ 41 - 1
dp/wifi3.0/dp_rx.c

@@ -89,6 +89,40 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc,
 }
 #endif
 
+#ifdef RX_DESC_SANITY_WAR
+static inline
+QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc,
+			     hal_ring_handle_t hal_ring_hdl,
+			     hal_ring_desc_t ring_desc,
+			     struct dp_rx_desc *rx_desc)
+{
+	if (qdf_unlikely(!rx_desc)) {
+		/*
+		 * This is an unlikely case where the cookie obtained
+		 * from the ring_desc is invalid and hence we are not
+		 * able to find the corresponding rx_desc
+		 */
+		DP_STATS_INC(soc, rx.err.invalid_cookie, 1);
+		dp_err("Ring Desc:");
+		hal_srng_dump_ring_desc(hal_soc, hal_ring_hdl,
+					ring_desc);
+		qdf_assert(0);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline
+QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc,
+			     hal_ring_handle_t hal_ring_hdl,
+			     hal_ring_desc_t ring_desc,
+			     struct dp_rx_desc *rx_desc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /*
  * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
  *			       called during dp rx initialization
@@ -1831,6 +1865,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl,
 	uint32_t rx_ol_pkt_cnt = 0;
 	uint32_t num_entries = 0;
 	struct hal_rx_msdu_metadata msdu_metadata;
+	QDF_STATUS status;
 
 	DP_HIST_INIT();
 
@@ -1894,7 +1929,12 @@ more_data:
 		rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc);
 
 		rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie);
-		qdf_assert(rx_desc);
+		status = dp_rx_desc_sanity(soc, hal_soc, hal_ring_hdl,
+					   ring_desc, rx_desc);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			hal_srng_dst_get_next(hal_soc, hal_ring_hdl);
+			continue;
+		}
 
 		/*
 		 * this is a unlikely scenario where the host is reaping

+ 3 - 0
dp/wifi3.0/dp_stats.c

@@ -6033,6 +6033,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
 	DP_PRINT_STATS("RX scatter msdu: %d",
 		       soc->stats.rx.err.scatter_msdu);
 
+	DP_PRINT_STATS("RX invalid cookie: %d",
+		       soc->stats.rx.err.invalid_cookie);
+
 	DP_PRINT_STATS("RX wait completed msdu break: %d",
 		       soc->stats.rx.msdu_scatter_wait_break);
 

+ 2 - 0
dp/wifi3.0/dp_types.h

@@ -784,6 +784,8 @@ struct dp_soc_stats {
 			uint32_t reo_cmd_send_fail;
 			/* RX msdu drop count due to scatter */
 			uint32_t scatter_msdu;
+			/* RX msdu drop count due to invalid cookie */
+			uint32_t invalid_cookie;
 		} err;
 
 		/* packet count per core - per ring */