Skip to content

Commit

Permalink
IPoIB: Fix usage of uninitialized multicast objects
Browse files Browse the repository at this point in the history
The driver should avoid calling ib_sa_free_multicast on the mcast->mc
object until it finishes its initialization state.  Otherwise we can
crash when ipoib_mcast_dev_flush() attempts to use the uninitialized
multicast object.

Instead, only call wait_for_completion() for multicast entries that
started the join process, meaning that ib_sa_join_multicast() finished.

Signed-off-by: Erez Shitrit <erezsh@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Erez Shitrit authored and Roland Dreier committed Nov 8, 2013
1 parent aede250 commit a9c8ba5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
2 changes: 2 additions & 0 deletions drivers/infiniband/ulp/ipoib/ipoib.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ enum {
IPOIB_MCAST_FLAG_SENDONLY = 1,
IPOIB_MCAST_FLAG_BUSY = 2, /* joining or already joined */
IPOIB_MCAST_FLAG_ATTACHED = 3,
IPOIB_MCAST_JOIN_STARTED = 4,

MAX_SEND_CQE = 16,
IPOIB_CM_COPYBREAK = 256,
Expand Down Expand Up @@ -151,6 +152,7 @@ struct ipoib_mcast {
struct sk_buff_head pkt_queue;

struct net_device *dev;
struct completion done;
};

struct ipoib_rx_buf {
Expand Down
21 changes: 17 additions & 4 deletions drivers/infiniband/ulp/ipoib/ipoib_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,10 @@ static int ipoib_mcast_join_complete(int status,
mcast->mcmember.mgid.raw, status);

/* We trap for port events ourselves. */
if (status == -ENETRESET)
return 0;
if (status == -ENETRESET) {
status = 0;
goto out;
}

if (!status)
status = ipoib_mcast_join_finish(mcast, &multicast->rec);
Expand All @@ -407,7 +409,8 @@ static int ipoib_mcast_join_complete(int status,
if (mcast == priv->broadcast)
queue_work(ipoib_workqueue, &priv->carrier_on_task);

return 0;
status = 0;
goto out;
}

if (mcast->logcount++ < 20) {
Expand All @@ -434,7 +437,8 @@ static int ipoib_mcast_join_complete(int status,
mcast->backoff * HZ);
spin_unlock_irq(&priv->lock);
mutex_unlock(&mcast_mutex);

out:
complete(&mcast->done);
return status;
}

Expand Down Expand Up @@ -484,11 +488,15 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
}

set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
init_completion(&mcast->done);
set_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags);

mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
&rec, comp_mask, GFP_KERNEL,
ipoib_mcast_join_complete, mcast);
if (IS_ERR(mcast->mc)) {
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
complete(&mcast->done);
ret = PTR_ERR(mcast->mc);
ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);

Expand Down Expand Up @@ -751,6 +759,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev)

spin_unlock_irqrestore(&priv->lock, flags);

/* seperate between the wait to the leave*/
list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
if (test_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags))
wait_for_completion(&mcast->done);

list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
ipoib_mcast_leave(dev, mcast);
ipoib_mcast_free(mcast);
Expand Down

0 comments on commit a9c8ba5

Please sign in to comment.