RDMA/iwcm: Don't touch cm_id after deref in rem_ref
rem_ref() calls iwcm_deref_id(), which will wake up any blockers on cm_id_priv->destroy_comp if the refcnt hits 0. That will unblock someone in iw_destroy_cm_id() which will free the cmid. If that happens before rem_ref() calls test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags), then the test_bit() will touch freed memory. The fix is to read the bit first, then deref. We should never be in iw_destroy_cm_id() with IWCM_F_CALLBACK_DESTROY set, and there is a BUG_ON() to make sure of that. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
374b105797
commit
6b59ba609b
@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
|
|||||||
static void rem_ref(struct iw_cm_id *cm_id)
|
static void rem_ref(struct iw_cm_id *cm_id)
|
||||||
{
|
{
|
||||||
struct iwcm_id_private *cm_id_priv;
|
struct iwcm_id_private *cm_id_priv;
|
||||||
|
int cb_destroy;
|
||||||
|
|
||||||
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
|
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
|
||||||
if (iwcm_deref_id(cm_id_priv) &&
|
|
||||||
test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) {
|
/*
|
||||||
|
* Test bit before deref in case the cm_id gets freed on another
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
|
cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
|
||||||
|
if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
|
||||||
BUG_ON(!list_empty(&cm_id_priv->work_list));
|
BUG_ON(!list_empty(&cm_id_priv->work_list));
|
||||||
free_cm_id(cm_id_priv);
|
free_cm_id(cm_id_priv);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user