diff options
author | Francesco Ruggeri <fruggeri@arista.com> | 2016-04-23 18:03:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-26 15:17:18 -0400 |
commit | 308379607548524b8d86dbf20134681024935e0b (patch) | |
tree | e755097f21c7b18c56e6a30542793e2b0cd9298b /drivers/net/macvlan.c | |
parent | 713d4ddc99677499281fbacdfc8519b9d22513fa (diff) |
macvlan: fix failure during registration v3
If macvlan_common_newlink fails in register_netdevice after macvlan_init
then it decrements port->count twice, first in macvlan_uninit (from
register_netdevice or rollback_registered) and then again in
macvlan_common_newlink.
A similar problem may exist in the ipvlan driver.
This patch consolidates modifications to port->count into macvlan_init
and macvlan_uninit (thanks to Eric Biederman for suggesting this approach).
v3: remove macvtap specific bits.
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 2bcf1f321bea..cb01023eab41 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -795,6 +795,7 @@ static int macvlan_init(struct net_device *dev) | |||
795 | { | 795 | { |
796 | struct macvlan_dev *vlan = netdev_priv(dev); | 796 | struct macvlan_dev *vlan = netdev_priv(dev); |
797 | const struct net_device *lowerdev = vlan->lowerdev; | 797 | const struct net_device *lowerdev = vlan->lowerdev; |
798 | struct macvlan_port *port = vlan->port; | ||
798 | 799 | ||
799 | dev->state = (dev->state & ~MACVLAN_STATE_MASK) | | 800 | dev->state = (dev->state & ~MACVLAN_STATE_MASK) | |
800 | (lowerdev->state & MACVLAN_STATE_MASK); | 801 | (lowerdev->state & MACVLAN_STATE_MASK); |
@@ -812,6 +813,8 @@ static int macvlan_init(struct net_device *dev) | |||
812 | if (!vlan->pcpu_stats) | 813 | if (!vlan->pcpu_stats) |
813 | return -ENOMEM; | 814 | return -ENOMEM; |
814 | 815 | ||
816 | port->count += 1; | ||
817 | |||
815 | return 0; | 818 | return 0; |
816 | } | 819 | } |
817 | 820 | ||
@@ -1312,10 +1315,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
1312 | return err; | 1315 | return err; |
1313 | } | 1316 | } |
1314 | 1317 | ||
1315 | port->count += 1; | ||
1316 | err = register_netdevice(dev); | 1318 | err = register_netdevice(dev); |
1317 | if (err < 0) | 1319 | if (err < 0) |
1318 | goto destroy_port; | 1320 | return err; |
1319 | 1321 | ||
1320 | dev->priv_flags |= IFF_MACVLAN; | 1322 | dev->priv_flags |= IFF_MACVLAN; |
1321 | err = netdev_upper_dev_link(lowerdev, dev); | 1323 | err = netdev_upper_dev_link(lowerdev, dev); |
@@ -1330,10 +1332,6 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
1330 | 1332 | ||
1331 | unregister_netdev: | 1333 | unregister_netdev: |
1332 | unregister_netdevice(dev); | 1334 | unregister_netdevice(dev); |
1333 | destroy_port: | ||
1334 | port->count -= 1; | ||
1335 | if (!port->count) | ||
1336 | macvlan_port_destroy(lowerdev); | ||
1337 | 1335 | ||
1338 | return err; | 1336 | return err; |
1339 | } | 1337 | } |