From 15df0cf75edd970bd0b399a1354a69fc8aaa0f0f Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Fri, 11 Dec 2015 10:35:10 +0530 Subject: [PATCH] qcacld-3.0: Avoid double free of vdev Propagation from qcacld 2.0 to qcacld 3.0 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/dp/txrx/ol_txrx.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index fa9f7d8fd369..df24d693c900 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1642,11 +1642,6 @@ void 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. - */ - cdf_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. @@ -1657,6 +1652,12 @@ void ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) void *vdev_delete_context = vdev->delete.context; + /* + * Now that there are no references to the peer, + * we can release the peer reference lock. + */ + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + TXRX_PRINT(TXRX_PRINT_LEVEL_INFO1, "%s: deleting vdev object %p " "(%02x:%02x:%02x:%02x:%02x:%02x)" @@ -1672,9 +1673,12 @@ void ol_txrx_peer_unref_delete(ol_txrx_peer_handle peer) cdf_mem_free(vdev); if (vdev_delete_cb) vdev_delete_cb(vdev_delete_context); + } else { + cdf_spin_unlock_bh(&pdev->peer_ref_mutex); } - } else + } else { cdf_spin_unlock_bh(&pdev->peer_ref_mutex); + } /* * 'array' is allocated in addba handler and is supposed to be