Эх сурвалжийг харах

qcacld-3.0: Use local variable to avoid race condition in packetdump

Race condiiton is observed as deregistration of 32 tx/rx packetdump
feature and packetdump callback call is happening at the same time
causing NULL pointer dereference.

Use local variable to store packetdump callback to avoid this race
condition.

Change-Id: Id4246d85e3816c0a3b8d0d0c1ef21e5ff053b608
CRs-Fixed: 1112126
Himanshu Agarwal 8 жил өмнө
parent
commit
bb226bc822

+ 12 - 11
core/dp/txrx/ol_rx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1443,6 +1443,7 @@ void ol_rx_pkt_dump_call(
 	v_CONTEXT_t vos_context;
 	ol_txrx_pdev_handle pdev;
 	struct ol_txrx_peer_t *peer = NULL;
+	tp_ol_packetdump_cb packetdump_cb;
 
 	vos_context = cds_get_global_context();
 	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
@@ -1453,17 +1454,17 @@ void ol_rx_pkt_dump_call(
 		return;
 	}
 
-	if (pdev->ol_rx_packetdump_cb) {
-		peer = ol_txrx_peer_find_by_id(pdev, peer_id);
-		if (!peer) {
-			TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
-				"%s: peer with peer id %d is NULL", __func__,
-				peer_id);
-			return;
-		}
-		pdev->ol_rx_packetdump_cb(msdu, status, peer->vdev->vdev_id,
-						RX_DATA_PKT);
+	peer = ol_txrx_peer_find_by_id(pdev, peer_id);
+	if (!peer) {
+		TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
+			"%s: peer with peer id %d is NULL", __func__,
+			peer_id);
+		return;
 	}
+
+	packetdump_cb = pdev->ol_rx_packetdump_cb;
+	if (packetdump_cb)
+		packetdump_cb(msdu, status, peer->vdev->vdev_id, RX_DATA_PKT);
 }
 
 /* the msdu_list passed here must be NULL terminated */

+ 8 - 4
core/dp/txrx/ol_tx_send.c

@@ -549,6 +549,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
 	struct ol_tx_desc_t *tx_desc;
 	uint32_t byte_cnt = 0;
 	qdf_nbuf_t netbuf;
+	tp_ol_packetdump_cb packetdump_cb;
 
 	union ol_tx_desc_list_elem_t *lcl_freelist = NULL;
 	union ol_tx_desc_list_elem_t *tx_desc_last = NULL;
@@ -565,8 +566,9 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
 		QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_FREE);
 
 		if (tx_desc->pkt_type != OL_TX_FRM_TSO) {
-			if (pdev->ol_tx_packetdump_cb)
-				pdev->ol_tx_packetdump_cb(netbuf, status,
+			packetdump_cb = pdev->ol_tx_packetdump_cb;
+			if (packetdump_cb)
+				packetdump_cb(netbuf, status,
 					tx_desc->vdev->vdev_id, TX_DATA_PKT);
 		}
 
@@ -775,6 +777,7 @@ ol_tx_single_completion_handler(ol_txrx_pdev_handle pdev,
 {
 	struct ol_tx_desc_t *tx_desc;
 	qdf_nbuf_t netbuf;
+	tp_ol_packetdump_cb packetdump_cb;
 
 	tx_desc = ol_tx_desc_find_check(pdev, tx_desc_id);
 	if (tx_desc == NULL) {
@@ -792,8 +795,9 @@ ol_tx_single_completion_handler(ol_txrx_pdev_handle pdev,
 	/* Do one shot statistics */
 	TXRX_STATS_UPDATE_TX_STATS(pdev, status, 1, qdf_nbuf_len(netbuf));
 
-	if (pdev->ol_tx_packetdump_cb)
-		pdev->ol_tx_packetdump_cb(netbuf, status,
+	packetdump_cb = pdev->ol_tx_packetdump_cb;
+	if (packetdump_cb)
+		packetdump_cb(netbuf, status,
 			tx_desc->vdev->vdev_id, TX_MGMT_PKT);
 
 	if (OL_TX_DESC_NO_REFS(tx_desc)) {

+ 10 - 7
core/wma/src/wma_mgmt.c

@@ -2502,6 +2502,7 @@ static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
 	uint8_t vdev_id = 0;
 	QDF_STATUS ret;
 	struct wlan_lmac_if_mgmt_txrx_rx_ops *mgmt_txrx_rx_ops;
+	tp_wma_packetdump_cb packetdump_cb;
 
 	if (wma_handle == NULL) {
 		WMA_LOGE("%s: wma handle is NULL", __func__);
@@ -2530,9 +2531,10 @@ static int wma_process_mgmt_tx_completion(tp_wma_handle wma_handle,
 		qdf_nbuf_unmap_single(wma_handle->qdf_dev, buf,
 					  QDF_DMA_TO_DEVICE);
 
-	if (wma_handle->wma_mgmt_tx_packetdump_cb)
-		wma_handle->wma_mgmt_tx_packetdump_cb(buf,
-			QDF_STATUS_SUCCESS, vdev_id, TX_MGMT_PKT);
+	packetdump_cb = wma_handle->wma_mgmt_tx_packetdump_cb;
+	if (packetdump_cb)
+		packetdump_cb(buf, QDF_STATUS_SUCCESS,
+			vdev_id, TX_MGMT_PKT);
 
 	if (!mgmt_txrx_rx_ops->mgmt_tx_completion_handler) {
 		WMA_LOGE("%s: tx completion callback to mgmt txrx layer is NULL",
@@ -3180,6 +3182,7 @@ int wma_form_rx_packet(qdf_nbuf_t buf,
 	int status;
 	tp_wma_handle wma_handle = (tp_wma_handle)
 				cds_get_context(QDF_MODULE_ID_WMA);
+	tp_wma_packetdump_cb packetdump_cb;
 
 	if (!wma_handle) {
 		WMA_LOGE(FL("wma handle is NULL"));
@@ -3294,12 +3297,12 @@ int wma_form_rx_packet(qdf_nbuf_t buf,
 		return -EINVAL;
 	}
 
+	packetdump_cb = wma_handle->wma_mgmt_rx_packetdump_cb;
 	if ((mgt_type == IEEE80211_FC0_TYPE_MGT &&
 			mgt_subtype != IEEE80211_FC0_SUBTYPE_BEACON) &&
-			wma_handle->wma_mgmt_rx_packetdump_cb)
-		wma_handle->wma_mgmt_rx_packetdump_cb(rx_pkt->pkt_buf,
-			QDF_STATUS_SUCCESS, rx_pkt->pkt_meta.sessionId,
-			RX_MGMT_PKT);
+			packetdump_cb)
+		packetdump_cb(rx_pkt->pkt_buf, QDF_STATUS_SUCCESS,
+			rx_pkt->pkt_meta.sessionId, RX_MGMT_PKT);
 
 	return 0;
 }