IPoIB: Check multicast address format
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Sun, 6 Sep 2009 03:23:40 +0000 (20:23 -0700)
committerRoland Dreier <rolandd@cisco.com>
Sun, 6 Sep 2009 03:23:40 +0000 (20:23 -0700)
Check that the format of multicast link addresses is correct before
taking them from dev->mc_list to priv->multicast_list.  This way we
never try to send a bogus address to the SA, which prevents badness
from erronous 'ip maddr addr add', broken bonding drivers, etc.

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/ipoib/ipoib_multicast.c

index a0825fe451e051c320b9bc78a509b893364cdc52..25874fc680c99d74a0402b29000d6569e0a7a9b7 100644 (file)
@@ -760,6 +760,20 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
        }
 }
 
+static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen,
+                                    const u8 *broadcast)
+{
+       if (addrlen != INFINIBAND_ALEN)
+               return 0;
+       /* reserved QPN, prefix, scope */
+       if (memcmp(addr, broadcast, 6))
+               return 0;
+       /* signature lower, pkey */
+       if (memcmp(addr + 7, broadcast + 7, 3))
+               return 0;
+       return 1;
+}
+
 void ipoib_mcast_restart_task(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv =
@@ -793,6 +807,11 @@ void ipoib_mcast_restart_task(struct work_struct *work)
        for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
                union ib_gid mgid;
 
+               if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr,
+                                              mclist->dmi_addrlen,
+                                              dev->broadcast))
+                       continue;
+
                memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid);
 
                mcast = __ipoib_mcast_find(dev, &mgid);