[PATCH NET-PREV 51/51] net: Make all NETDEV_REGISTER events to be called under nd_lock

From: Kirill Tkhai
Date: Sat Mar 22 2025 - 10:56:00 EST


Signed-off-by: Kirill Tkhai <tkhai@xxxxx>
---
net/core/dev.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index c477b39d08b9..03c1bfa35309 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1737,13 +1737,19 @@ static void call_netdevice_unregister_notifiers(struct notifier_block *nb,
}

static int call_netdevice_register_net_notifiers(struct notifier_block *nb,
- struct net *net)
+ struct net *net,
+ bool locked)
{
+ struct nd_lock *nd_lock;
struct net_device *dev;
int err;

for_each_netdev(net, dev) {
+ if (!locked)
+ lock_netdev(dev, &nd_lock);
err = call_netdevice_register_notifiers(nb, dev);
+ if (!locked)
+ unlock_netdev(nd_lock);
if (err)
goto rollback;
}
@@ -1794,7 +1800,7 @@ int register_netdevice_notifier(struct notifier_block *nb)
if (dev_boot_phase)
goto unlock;
for_each_net(net) {
- err = call_netdevice_register_net_notifiers(nb, net);
+ err = call_netdevice_register_net_notifiers(nb, net, false);
if (err)
goto rollback;
}
@@ -1851,7 +1857,8 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);

static int __register_netdevice_notifier_net(struct net *net,
struct notifier_block *nb,
- bool ignore_call_fail)
+ bool ignore_call_fail,
+ bool locked)
{
int err;

@@ -1861,7 +1868,7 @@ static int __register_netdevice_notifier_net(struct net *net,
if (dev_boot_phase)
return 0;

- err = call_netdevice_register_net_notifiers(nb, net);
+ err = call_netdevice_register_net_notifiers(nb, net, locked);
if (err && !ignore_call_fail)
goto chain_unregister;

@@ -1905,7 +1912,7 @@ int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb)
int err;

rtnl_lock();
- err = __register_netdevice_notifier_net(net, nb, false);
+ err = __register_netdevice_notifier_net(net, nb, false, false);
rtnl_unlock();
return err;
}
@@ -1944,17 +1951,20 @@ static void __move_netdevice_notifier_net(struct net *src_net,
struct notifier_block *nb)
{
__unregister_netdevice_notifier_net(src_net, nb);
- __register_netdevice_notifier_net(dst_net, nb, true);
+ __register_netdevice_notifier_net(dst_net, nb, true, true);
}

int register_netdevice_notifier_dev_net(struct net_device *dev,
struct notifier_block *nb,
struct netdev_net_notifier *nn)
{
+ struct nd_lock *nd_lock;
int err;

rtnl_lock();
- err = __register_netdevice_notifier_net(dev_net(dev), nb, false);
+ lock_netdev(dev, &nd_lock);
+ err = __register_netdevice_notifier_net(dev_net(dev), nb, false, true);
+ unlock_netdev(nd_lock);
if (!err) {
nn->nb = nb;
list_add(&nn->list, &dev->net_notifier_list);