diff options
author | Eli Cohen <eli@mellanox.co.il> | 2006-02-27 23:47:43 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-03-20 13:08:18 -0500 |
commit | 7343b231f22cec11f069bcdbb0c9a417df2750d3 (patch) | |
tree | 3b72ba5f585fcab8271dc4be046b3bd447852847 /drivers/infiniband/ulp | |
parent | 1d89b1ae6c203bc68a3f424be144abcdf62773c9 (diff) |
IPoIB: Close race in setting mcast->ah
ipoib_mcast_send() tests mcast->ah twice. If this value is changed
between these two points, we leak an skb. However,
ipoib_mcast_join_finish() sets mcast->ah with no locking, so it could
race against ipoib_mcast_send().
As a solution, take priv->lock around assignment to mcast->ah thus
making sure ipoib_mcast_send() (which also takes priv->lock) is not in
flight.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index a2408d7ec598..e5dc2a034530 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -213,6 +213,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
213 | { | 213 | { |
214 | struct net_device *dev = mcast->dev; | 214 | struct net_device *dev = mcast->dev; |
215 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 215 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
216 | struct ipoib_ah *ah; | ||
216 | int ret; | 217 | int ret; |
217 | 218 | ||
218 | mcast->mcmember = *mcmember; | 219 | mcast->mcmember = *mcmember; |
@@ -269,8 +270,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
269 | av.static_rate, priv->local_rate, | 270 | av.static_rate, priv->local_rate, |
270 | ib_sa_rate_enum_to_int(mcast->mcmember.rate)); | 271 | ib_sa_rate_enum_to_int(mcast->mcmember.rate)); |
271 | 272 | ||
272 | mcast->ah = ipoib_create_ah(dev, priv->pd, &av); | 273 | ah = ipoib_create_ah(dev, priv->pd, &av); |
273 | if (!mcast->ah) { | 274 | if (!ah) { |
274 | ipoib_warn(priv, "ib_address_create failed\n"); | 275 | ipoib_warn(priv, "ib_address_create failed\n"); |
275 | } else { | 276 | } else { |
276 | ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT | 277 | ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT |
@@ -280,6 +281,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
280 | be16_to_cpu(mcast->mcmember.mlid), | 281 | be16_to_cpu(mcast->mcmember.mlid), |
281 | mcast->mcmember.sl); | 282 | mcast->mcmember.sl); |
282 | } | 283 | } |
284 | |||
285 | spin_lock_irq(&priv->lock); | ||
286 | mcast->ah = ah; | ||
287 | spin_unlock_irq(&priv->lock); | ||
283 | } | 288 | } |
284 | 289 | ||
285 | /* actually send any queued packets */ | 290 | /* actually send any queued packets */ |