Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b59ba60 authored by Steve Wise's avatar Steve Wise Committed by Roland Dreier
Browse files

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: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 374b1057
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -181,9 +181,16 @@ static void add_ref(struct iw_cm_id *cm_id)
static void rem_ref(struct iw_cm_id *cm_id)
{
	struct iwcm_id_private *cm_id_priv;
	int cb_destroy;

	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));
		free_cm_id(cm_id_priv);
	}