From 8ecaa7bd0d402652a896c02e516e2db8d866ffdd Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Thu, 10 Dec 2015 12:52:38 +0530 Subject: qcacld-2.0: Avoid double free of vdev Due to a race condition, vdev is getting deleted in ol_txrx_vdev_detach and after that in ol_txrx_peer_unref_delete, as vdev->delete.pending is not equal to 0 as it is some garbage value, vdev is getting deleted again causing crash. This fix release the lock after checking vdev->delete.pending so that before vdev gets deleted in ol_txrx_vdev_detach, this check has been made and as vdev->delete.pending is 0, it will not delete the vdev in ol_txrx_peer_unref_delete and so vdev will be deleted only once. Change-Id: I4a7362b0e226c66ccb7c72243276d77e8df60b20 CRs-Fixed: 949397 --- CORE/CLD_TXRX/TXRX/ol_txrx.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/CORE/CLD_TXRX/TXRX/ol_txrx.c b/CORE/CLD_TXRX/TXRX/ol_txrx.c index 74369051e810..48c328ff111d 100644 --- a/CORE/CLD_TXRX/TXRX/ol_txrx.c +++ b/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -1692,19 +1692,20 @@ ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) /* check whether the parent vdev has no peers left */ if (TAILQ_EMPTY(&vdev->peer_list)) { - /* - * Now that there are no references to the peer, we can - * release the peer reference lock. - */ - adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); /* * Check if the parent vdev was waiting for its peers to be * deleted, in order for it to be deleted too. */ - if (vdev->delete.pending) { + if (vdev->delete.pending == 1) { ol_txrx_vdev_delete_cb vdev_delete_cb = vdev->delete.callback; void *vdev_delete_context = vdev->delete.context; + /* + * Now that there are no references to the peer, we can + * release the peer reference lock. + */ + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s: deleting vdev object %p " "(%02x:%02x:%02x:%02x:%02x:%02x)" @@ -1718,6 +1719,8 @@ ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) if (vdev_delete_cb) { vdev_delete_cb(vdev_delete_context); } + } else { + adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); } } else { adf_os_spin_unlock_bh(&pdev->peer_ref_mutex); -- cgit v1.2.3