[openib-general] [PATCH] cm refcount race fix

Michael S. Tsirkin mst at mellanox.co.il
Sun May 7 22:45:29 PDT 2006


Sean, please review.
Are there other places in code that have the same race?

--

Fix race condition in CM.
use after free if ib_destroy_cm_id tests the refcount after cm_deref_id has
decremented the reference count but before it has called wake_up.

Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: linux-2.6.16/drivers/infiniband/core/cm.c
===================================================================
--- linux-2.6.16.orig/drivers/infiniband/core/cm.c	2006-05-07 22:01:23.000000000 +0300
+++ linux-2.6.16/drivers/infiniband/core/cm.c	2006-05-07 22:01:40.000000000 +0300
@@ -159,8 +159,12 @@ static void cm_work_handler(void *data);
 
 static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cm_id_priv->lock, flags);
 	if (atomic_dec_and_test(&cm_id_priv->refcount))
 		wake_up(&cm_id_priv->wait);
+	spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 }
 
 static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
@@ -778,6 +782,10 @@ retest:
 	cm_free_id(cm_id->local_id);
 	atomic_dec(&cm_id_priv->refcount);
 	wait_event(cm_id_priv->wait, !atomic_read(&cm_id_priv->refcount));
+
+	/* Make sure cm_deref_id is not in progress */
+	spin_lock_irq(&cm_id_priv->lock);
+	spin_unlock_irq(&cm_id_priv->lock);
 	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
 		cm_free_work(work);
 	kfree(cm_id_priv->compare_data);

-- 
MST



More information about the general mailing list