]> Pileus Git - ~andy/linux/commitdiff
macvlan: better mode validation
authorMichael S. Tsirkin <mst@redhat.com>
Thu, 1 Aug 2013 10:43:19 +0000 (13:43 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Aug 2013 23:32:05 +0000 (16:32 -0700)
macvlan passthrough mode is special: it's not possible to switch to or
from it through a netlink command.

But if you try, the command will succeed, which is
confusing.

Validate input and return error to user.

Cc: Sridhar Samudrala <sri@us.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/macvlan.c

index 18373b6ae37d78543cf925e2d86efab1578f3019..13937f9c04ad276e22ee973ba7584c201947d8de 100644 (file)
@@ -863,6 +863,18 @@ static int macvlan_changelink(struct net_device *dev,
                struct nlattr *tb[], struct nlattr *data[])
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
+       enum macvlan_mode mode;
+       bool set_mode = false;
+
+       /* Validate mode, but don't set yet: setting flags may fail. */
+       if (data && data[IFLA_MACVLAN_MODE]) {
+               set_mode = true;
+               mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+               /* Passthrough mode can't be set or cleared dynamically */
+               if ((mode == MACVLAN_MODE_PASSTHRU) !=
+                   (vlan->mode == MACVLAN_MODE_PASSTHRU))
+                       return -EINVAL;
+       }
 
        if (data && data[IFLA_MACVLAN_FLAGS]) {
                __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
@@ -879,8 +891,8 @@ static int macvlan_changelink(struct net_device *dev,
                }
                vlan->flags = flags;
        }
-       if (data && data[IFLA_MACVLAN_MODE])
-               vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+       if (set_mode)
+               vlan->mode = mode;
        return 0;
 }