From 9f297069f8e1f89765cfe0d68d43eb4da022ee2a Mon Sep 17 00:00:00 2001 From: Jingxiang Ge Date: Wed, 24 Jan 2018 13:31:31 +0800 Subject: [PATCH] qcacld-3.0: Fix race condition for get peer There is a very rare race condition between ol_txrx_peer_find_by_local_id_inc_ref(running in OL RX thread context) and ol_txrx_peer_detach(running in MC thread context) where MC thread 1st got chance and cleared the peer->valid flag before OL RX thread can increment the ref count and this led to OL RX thread got a peer without any ref count which was freed later while OL RX thread was still using it. Change: 1 Set peer to NULL if peer valid check fails in ol_txrx_peer_find_by_local_id_inc_ref 2 release peer ref cnt for error case in ol_rx_data_cb Change-Id: Id21350933386464e5814babcb078d9719572af86 CRs-Fixed: 2176704 --- core/dp/txrx/ol_txrx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index 513c54862b58..9a997424109b 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -525,6 +525,8 @@ ol_txrx_peer_get_ref_by_local_id(struct cdp_pdev *ppdev, qdf_spin_unlock_bh(&pdev->local_peer_ids.lock); if (peer && peer->valid) ol_txrx_peer_get_ref(peer, dbg_id); + else + peer = NULL; qdf_spin_unlock_bh(&pdev->peer_ref_mutex); return peer; @@ -4984,6 +4986,7 @@ static void ol_rx_data_cb(struct ol_txrx_pdev_t *pdev, if (qdf_unlikely(!(peer->state >= OL_TXRX_PEER_STATE_CONN) || !peer->vdev->rx)) { qdf_spin_unlock_bh(&peer->peer_info_lock); + ol_txrx_peer_release_ref(peer, PEER_DEBUG_ID_OL_RX_THREAD); goto free_buf; }