aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEli Cohen <eli@mellanox.co.il>2006-02-27 23:47:43 -0500
committerRoland Dreier <rolandd@cisco.com>2006-03-20 13:08:18 -0500
commit7343b231f22cec11f069bcdbb0c9a417df2750d3 (patch)
tree3b72ba5f585fcab8271dc4be046b3bd447852847 /drivers
parent1d89b1ae6c203bc68a3f424be144abcdf62773c9 (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')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c9
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 */