net/mlx4_en: Protect MAC address modification with the state_lock mutex
authorShani Michaelli <shanim@mellanox.com>
Wed, 14 May 2014 09:15:15 +0000 (12:15 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 14 May 2014 19:40:33 +0000 (15:40 -0400)
This Patches solves an issue that could raise when modifying the
device's MAC. It occurs due to a simultaneous access to priv->mac_hash
from two contexts. The buggy scenario described below:
Context 1: copy the new mac address to the dev->dev_addr field.
Context 2: mlx4_en_do_uc_filter removes prev_mac entry from the mac_hash
           db since it is not in dev->uc and not equal to dev->dev_addr.
Context 1: mlx4_en_do_set_mac() calls mlx4_en_replace_mac() to replace
           prev_mac with dev_addr but it fails to update the mac_hash db
           since it no longer contains prev_mac, therefore it returns
           with an error.

The fix is to prevent mlx4_en_do_uc_filter from being executed by both
of the context 1 calls described above, This is done by putting them
both under the mdev->state_lock lock, it will solve this issue since
mlx4_en_do_uc_filter is already protected by the mdev->state_lock.

Reviewed-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/en_netdev.c

index c0247945d83520da3cf1d7a321727c083c633993..8e8fb69fa871ccda2db2f1a07173e8ac542c0571 100644 (file)
@@ -789,9 +789,8 @@ static int mlx4_en_set_mac(struct net_device *dev, void *addr)
        if (!is_valid_ether_addr(saddr->sa_data))
                return -EADDRNOTAVAIL;
 
-       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
-
        mutex_lock(&mdev->state_lock);
+       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
        err = mlx4_en_do_set_mac(priv);
        mutex_unlock(&mdev->state_lock);