[ofa-general] [PATCH] IB/sa_query: fix update_sm_ah() race condition.

Jack Morgenstein jackm at dev.mellanox.co.il
Mon Mar 2 23:20:46 PST 2009


Our testing uncovered a race condition in ib_sa_event():
    spin_lock_irqsave(&port->ah_lock, flags);
    if (port->sm_ah)
        kref_put(&port->sm_ah->ref, free_sm_ah);
        port->sm_ah = NULL;
    spin_unlock_irqrestore(&port->ah_lock, flags);

    schedule_work(&sa_dev->port[event->element.port_num -
                  sa_dev->start_port].update_task);

If two events occur back-to-back (e.g., client-reregister and lid change),
both may pass the spinlock-protected code above before the first
schedule_work updates the port->sm_ah handle.
The second schedule_work operation will then find a non-null port->ah_lock,
and will simply overwrite it in update_sm_ah -- resulting in an ah leak.

Signed-off-by: Jack Morgenstein <jackm at dev.mellanox.co.il>

diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 7863a50..1865049 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -395,6 +395,8 @@ static void update_sm_ah(struct work_struct *work)
 	}
 
 	spin_lock_irq(&port->ah_lock);
+	if (port->sm_ah)
+		kref_put(&port->sm_ah->ref, free_sm_ah);
 	port->sm_ah = new_ah;
 	spin_unlock_irq(&port->ah_lock);
 



More information about the general mailing list