netns: foreach_netdev_safe is insufficient in default_device_exit
During network namespace teardown we either move or delete all of the network devices associated with a network namespace. In the case of veth devices deleting one will also delete it's pair device. If both devices are in the same network namespace then for_each_netdev_safe is insufficient as next may point to the second veth device we have deleted. To avoid problems I do what we do in __rtnl_kill_links and restart the scan of the device list, after we have deleted a device. Currently dev_change_netnamespace does not appear to suffer from this problem, but wireless devices are also paired and likely should be moved between network namespaces together. So I have errored on the side of caution and restart the scan of the network devices in that case as well. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>hifive-unleashed-5.1
parent
91b208c7c1
commit
8eb7986396
|
@ -5066,13 +5066,14 @@ static struct pernet_operations __net_initdata netdev_net_ops = {
|
||||||
|
|
||||||
static void __net_exit default_device_exit(struct net *net)
|
static void __net_exit default_device_exit(struct net *net)
|
||||||
{
|
{
|
||||||
struct net_device *dev, *next;
|
struct net_device *dev;
|
||||||
/*
|
/*
|
||||||
* Push all migratable of the network devices back to the
|
* Push all migratable of the network devices back to the
|
||||||
* initial network namespace
|
* initial network namespace
|
||||||
*/
|
*/
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
for_each_netdev_safe(net, dev, next) {
|
restart:
|
||||||
|
for_each_netdev(net, dev) {
|
||||||
int err;
|
int err;
|
||||||
char fb_name[IFNAMSIZ];
|
char fb_name[IFNAMSIZ];
|
||||||
|
|
||||||
|
@ -5083,7 +5084,7 @@ static void __net_exit default_device_exit(struct net *net)
|
||||||
/* Delete virtual devices */
|
/* Delete virtual devices */
|
||||||
if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) {
|
if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) {
|
||||||
dev->rtnl_link_ops->dellink(dev);
|
dev->rtnl_link_ops->dellink(dev);
|
||||||
continue;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push remaing network devices to init_net */
|
/* Push remaing network devices to init_net */
|
||||||
|
@ -5094,6 +5095,7 @@ static void __net_exit default_device_exit(struct net *net)
|
||||||
__func__, dev->name, err);
|
__func__, dev->name, err);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
goto restart;
|
||||||
}
|
}
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue