Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

IPoIB: Fix crash when path record fails after path flush

Commit ee1e2c82 ("IPoIB: Refresh paths instead of flushing them on SM
change events") changed how paths are flushed on an SM event. This
change introduces a problem if the path record query triggered by
fails, causing path->ah to become NULL. A later successful path query
will then trigger WARN_ON() in path_rec_completion(), and crash
because path->ah has already been freed, so the ipoib_put_ah() inside
the lock in path_rec_completion() may actually drop the last reference
(contrary to the comment that claims this is safe).

Fix this by updating path->ah and freeing old_ah only when the path
record query is successful. This prevents the neighbour AH and that
path AH from getting out of sync.

This fixes <https://bugs.openfabrics.org/show_bug.cgi?id=1194>

Reported-by: Rabah Salem <ravah@mellanox.com>
Debugged-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Roland Dreier and committed by
Linus Torvalds
6ef190cc efba91bd

+4 -4
+4 -4
drivers/infiniband/ulp/ipoib/ipoib_main.c
··· 404 404 struct net_device *dev = path->dev; 405 405 struct ipoib_dev_priv *priv = netdev_priv(dev); 406 406 struct ipoib_ah *ah = NULL; 407 - struct ipoib_ah *old_ah; 407 + struct ipoib_ah *old_ah = NULL; 408 408 struct ipoib_neigh *neigh, *tn; 409 409 struct sk_buff_head skqueue; 410 410 struct sk_buff *skb; ··· 428 428 429 429 spin_lock_irqsave(&priv->lock, flags); 430 430 431 - old_ah = path->ah; 432 - path->ah = ah; 433 - 434 431 if (ah) { 435 432 path->pathrec = *pathrec; 433 + 434 + old_ah = path->ah; 435 + path->ah = ah; 436 436 437 437 ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n", 438 438 ah, be16_to_cpu(pathrec->dlid), pathrec->sl);