Skip to content

Commit b20b8ae

Browse files
idoschPaolo Abeni
authored andcommitted
devlink: Fix netdev notifier chain corruption
Cited commit changed devlink to register its netdev notifier block on the global netdev notifier chain instead of on the per network namespace one. However, when changing the network namespace of the devlink instance, devlink still tries to unregister its notifier block from the chain of the old namespace and register it on the chain of the new namespace. This results in corruption of the notifier chains, as the same notifier block is registered on two different chains: The global one and the per network namespace one. In turn, this causes other problems such as the inability to dismantle namespaces due to netdev reference count issues. Fix by preventing devlink from moving its notifier block between namespaces. Reproducer: # echo "10 1" > /sys/bus/netdevsim/new_device # ip netns add test123 # devlink dev reload netdevsim/netdevsim10 netns test123 # ip netns del test123 [ 71.935619] unregister_netdevice: waiting for lo to become free. Usage count = 2 [ 71.938348] leaked reference. Fixes: 565b482 ("devlink: change port event netdev notifier from per-net to global") Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 5d54cb1 commit b20b8ae

File tree

3 files changed

+1
-14
lines changed

3 files changed

+1
-14
lines changed

include/linux/netdevice.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,8 +2839,6 @@ int unregister_netdevice_notifier(struct notifier_block *nb);
28392839
int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb);
28402840
int unregister_netdevice_notifier_net(struct net *net,
28412841
struct notifier_block *nb);
2842-
void move_netdevice_notifier_net(struct net *src_net, struct net *dst_net,
2843-
struct notifier_block *nb);
28442842
int register_netdevice_notifier_dev_net(struct net_device *dev,
28452843
struct notifier_block *nb,
28462844
struct netdev_net_notifier *nn);

net/core/dev.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,14 +1869,6 @@ static void __move_netdevice_notifier_net(struct net *src_net,
18691869
__register_netdevice_notifier_net(dst_net, nb, true);
18701870
}
18711871

1872-
void move_netdevice_notifier_net(struct net *src_net, struct net *dst_net,
1873-
struct notifier_block *nb)
1874-
{
1875-
rtnl_lock();
1876-
__move_netdevice_notifier_net(src_net, dst_net, nb);
1877-
rtnl_unlock();
1878-
}
1879-
18801872
int register_netdevice_notifier_dev_net(struct net_device *dev,
18811873
struct notifier_block *nb,
18821874
struct netdev_net_notifier *nn)

net/core/devlink.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4742,11 +4742,8 @@ static int devlink_reload(struct devlink *devlink, struct net *dest_net,
47424742
if (err)
47434743
return err;
47444744

4745-
if (dest_net && !net_eq(dest_net, curr_net)) {
4746-
move_netdevice_notifier_net(curr_net, dest_net,
4747-
&devlink->netdevice_nb);
4745+
if (dest_net && !net_eq(dest_net, curr_net))
47484746
write_pnet(&devlink->_net, dest_net);
4749-
}
47504747

47514748
err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
47524749
devlink_reload_failed_set(devlink, !!err);

0 commit comments

Comments
 (0)