* [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts
@ 2026-10-26 22:13 Naman Gulati
2026-10-26 22:28 ` Stanislav Fomichev
2026-10-29 16:10 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 6+ messages in thread
From: Naman Gulati @ 2026-10-26 22:13 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Kuniyuki Iwashima, netdev, linux-kernel,
syzbot+1269fe6cc2016008124e, Naman Gulati
netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while
it waits for the last references on a device to be dropped. By then
netdev_run_todo() has already marked the device NETREG_UNREGISTERED and
RTNL has been dropped at least once since the initial notification sent
by unregister_netdevice_many_notify().
netdev_genl_netdevice_event() does not tell these rebroadcasts apart
from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF
multicast for each of them. At best this spams NETDEV_NLGRP_MGMT
listeners with duplicate notifications; at worst the pernet state of
the netns the device belongs to is already gone and the handler
dereferences a NULL pointer.
default_device_exit_batch() only unregisters the devices still listed
in the exiting netns; it does not wait for in-flight unregistrations of
devices that were already unlisted (the barrier doing that was removed
by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")).
So when a device is unregistered by something other than the
cleanup_net() of its own netns while references on it are still held,
e.g. a veth whose peer in another netns gets deleted, and that netns
exits while the device is stuck in netdev_wait_allrefs_any(), the
remaining pernet exit handlers run and genl_pernet_exit() sets
net->genl_sock to NULL. The next rebroadcast then crashes in
genl_has_listeners():
BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388
Read of size 8 at addr 0000000000000578 by task syz.0.0/5325
Call Trace:
<TASK>
netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388
genl_has_listeners include/net/genetlink.h:644 [inline]
netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93
netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491
notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
netdev_wait_allrefs_any net/core/dev.c:11690 [inline]
netdev_run_todo+0x731/0x1060 net/core/dev.c:11808
rtnl_unlock net/core/rtnetlink.c:157 [inline]
rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707
syzbot hit this by moving one end of a veth pair into a short-lived
netns while netdevsim's deferred FIB event processing still held a
reference on it, and then deleting the other end (repro [1]). While the
source of this bug is netdevsim deferring FIB processing for and holding
onto the device reference for O(seconds) which is being fixed
separately [2], any driver may introduce such a delay and trigger the
null-ptr-deref.
Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events
delivered with reg_state == NETREG_UNREGISTERED. The notifications sent
by unregister_netdevice_many_notify() and, for a device leaving a netns,
by __dev_change_net_namespace() are issued under RTNL in the same
critical section that unlists the device, before its netns can be torn
down, and keep being handled. This mirrors what ip6_route_dev_notify()
already does to cope with the rebroadcasts.
This change should not break the UAPI spec as it defines dev-del-ntf as
a "Notification about device disappearing." which is a single event. The
rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel
subsystems holding references; netdev-genl happens to be on the notifier
chain and forwards it.
[1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae
[2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com
Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff")
Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Naman Gulati <namangulati@google.com>
---
Note that the reproducer attached to the syzbot bug targets a different
bug (via devlink_port_notify() on netns teardown) that happens to share
the same crash title, not the one in the original reported crash report.
---
net/core/netdev-genl.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 33b9f4eb9565a..2032ab9a864c2 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -1487,6 +1487,12 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb,
netdev_unlock_full_to_ops(netdev);
break;
case NETDEV_UNREGISTER:
+ /* netdev_wait_allrefs_any() rebroadcasts NETDEV_UNREGISTER
+ * while waiting for the last references to be dropped; the
+ * netns may already be torn down by then. Notify only once.
+ */
+ if (READ_ONCE(netdev->reg_state) == NETREG_UNREGISTERED)
+ break;
netdev_lock(netdev);
netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF);
netdev_unlock(netdev);
--
2.56.0.307.g5fe7bd680c-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts 2026-10-26 22:13 [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts Naman Gulati @ 2026-10-26 22:28 ` Stanislav Fomichev 2026-10-26 23:27 ` Naman Gulati 2026-10-27 1:47 ` Kuniyuki Iwashima 2026-10-29 16:10 ` patchwork-bot+netdevbpf 1 sibling, 2 replies; 6+ messages in thread From: Stanislav Fomichev @ 2026-10-26 22:28 UTC (permalink / raw) To: Naman Gulati Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Kuniyuki Iwashima, netdev, linux-kernel, syzbot+1269fe6cc2016008124e On 10/26, Naman Gulati wrote: > netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while > it waits for the last references on a device to be dropped. By then > netdev_run_todo() has already marked the device NETREG_UNREGISTERED and > RTNL has been dropped at least once since the initial notification sent > by unregister_netdevice_many_notify(). > > netdev_genl_netdevice_event() does not tell these rebroadcasts apart > from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF > multicast for each of them. At best this spams NETDEV_NLGRP_MGMT > listeners with duplicate notifications; at worst the pernet state of > the netns the device belongs to is already gone and the handler > dereferences a NULL pointer. > > default_device_exit_batch() only unregisters the devices still listed > in the exiting netns; it does not wait for in-flight unregistrations of > devices that were already unlisted (the barrier doing that was removed > by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")). > So when a device is unregistered by something other than the > cleanup_net() of its own netns while references on it are still held, > e.g. a veth whose peer in another netns gets deleted, and that netns > exits while the device is stuck in netdev_wait_allrefs_any(), the > remaining pernet exit handlers run and genl_pernet_exit() sets > net->genl_sock to NULL. The next rebroadcast then crashes in > genl_has_listeners(): > > BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > Read of size 8 at addr 0000000000000578 by task syz.0.0/5325 > Call Trace: > <TASK> > netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > genl_has_listeners include/net/genetlink.h:644 [inline] > netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93 > netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491 > notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 > netdev_wait_allrefs_any net/core/dev.c:11690 [inline] > netdev_run_todo+0x731/0x1060 net/core/dev.c:11808 > rtnl_unlock net/core/rtnetlink.c:157 [inline] > rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707 > > syzbot hit this by moving one end of a veth pair into a short-lived > netns while netdevsim's deferred FIB event processing still held a > reference on it, and then deleting the other end (repro [1]). While the > source of this bug is netdevsim deferring FIB processing for and holding > onto the device reference for O(seconds) which is being fixed > separately [2], any driver may introduce such a delay and trigger the > null-ptr-deref. > > Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events > delivered with reg_state == NETREG_UNREGISTERED. The notifications sent > by unregister_netdevice_many_notify() and, for a device leaving a netns, > by __dev_change_net_namespace() are issued under RTNL in the same > critical section that unlists the device, before its netns can be torn > down, and keep being handled. This mirrors what ip6_route_dev_notify() > already does to cope with the rebroadcasts. > > This change should not break the UAPI spec as it defines dev-del-ntf as > a "Notification about device disappearing." which is a single event. The > rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel > subsystems holding references; netdev-genl happens to be on the notifier > chain and forwards it. > > [1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae > [2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com > > Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") > Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com > Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/ > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> > Signed-off-by: Naman Gulati <namangulati@google.com> > --- > Note that the reproducer attached to the syzbot bug targets a different > bug (via devlink_port_notify() on netns teardown) that happens to share > the same crash title, not the one in the original reported crash report. > --- > net/core/netdev-genl.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c > index 33b9f4eb9565a..2032ab9a864c2 100644 > --- a/net/core/netdev-genl.c > +++ b/net/core/netdev-genl.c > @@ -1487,6 +1487,12 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb, > netdev_unlock_full_to_ops(netdev); > break; > case NETDEV_UNREGISTER: > + /* netdev_wait_allrefs_any() rebroadcasts NETDEV_UNREGISTER > + * while waiting for the last references to be dropped; the > + * netns may already be torn down by then. Notify only once. > + */ [..] > + if (READ_ONCE(netdev->reg_state) == NETREG_UNREGISTERED) > + break; Same as https://lore.kernel.org/netdev/20261026063743.1797-1-lege.wang@jaguarmicro.com/ ? reg_state is protected by netdev, why not do this under netdev_lock? Also seems like we are fixing a symptom, not the problem? > netdev_lock(netdev); > netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF); > netdev_unlock(netdev); ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts 2026-10-26 22:28 ` Stanislav Fomichev @ 2026-10-26 23:27 ` Naman Gulati 2026-10-27 1:47 ` Kuniyuki Iwashima 1 sibling, 0 replies; 6+ messages in thread From: Naman Gulati @ 2026-10-26 23:27 UTC (permalink / raw) To: Stanislav Fomichev Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Kuniyuki Iwashima, netdev, linux-kernel, syzbot+1269fe6cc2016008124e, lege.wang On Mon, Oct 26, 2026 at 3:28 PM Stanislav Fomichev <sdf.kernel@gmail.com> wrote: > > On 10/26, Naman Gulati wrote: > > netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while > > it waits for the last references on a device to be dropped. By then > > netdev_run_todo() has already marked the device NETREG_UNREGISTERED and > > RTNL has been dropped at least once since the initial notification sent > > by unregister_netdevice_many_notify(). > > > > netdev_genl_netdevice_event() does not tell these rebroadcasts apart > > from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF > > multicast for each of them. At best this spams NETDEV_NLGRP_MGMT > > listeners with duplicate notifications; at worst the pernet state of > > the netns the device belongs to is already gone and the handler > > dereferences a NULL pointer. > > > > default_device_exit_batch() only unregisters the devices still listed > > in the exiting netns; it does not wait for in-flight unregistrations of > > devices that were already unlisted (the barrier doing that was removed > > by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")). > > So when a device is unregistered by something other than the > > cleanup_net() of its own netns while references on it are still held, > > e.g. a veth whose peer in another netns gets deleted, and that netns > > exits while the device is stuck in netdev_wait_allrefs_any(), the > > remaining pernet exit handlers run and genl_pernet_exit() sets > > net->genl_sock to NULL. The next rebroadcast then crashes in > > genl_has_listeners(): > > > > BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > Read of size 8 at addr 0000000000000578 by task syz.0.0/5325 > > Call Trace: > > <TASK> > > netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > genl_has_listeners include/net/genetlink.h:644 [inline] > > netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93 > > netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491 > > notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 > > netdev_wait_allrefs_any net/core/dev.c:11690 [inline] > > netdev_run_todo+0x731/0x1060 net/core/dev.c:11808 > > rtnl_unlock net/core/rtnetlink.c:157 [inline] > > rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707 > > > > syzbot hit this by moving one end of a veth pair into a short-lived > > netns while netdevsim's deferred FIB event processing still held a > > reference on it, and then deleting the other end (repro [1]). While the > > source of this bug is netdevsim deferring FIB processing for and holding > > onto the device reference for O(seconds) which is being fixed > > separately [2], any driver may introduce such a delay and trigger the > > null-ptr-deref. > > > > Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events > > delivered with reg_state == NETREG_UNREGISTERED. The notifications sent > > by unregister_netdevice_many_notify() and, for a device leaving a netns, > > by __dev_change_net_namespace() are issued under RTNL in the same > > critical section that unlists the device, before its netns can be torn > > down, and keep being handled. This mirrors what ip6_route_dev_notify() > > already does to cope with the rebroadcasts. > > > > This change should not break the UAPI spec as it defines dev-del-ntf as > > a "Notification about device disappearing." which is a single event. The > > rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel > > subsystems holding references; netdev-genl happens to be on the notifier > > chain and forwards it. > > > > [1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae > > [2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com > > > > Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") > > Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com > > Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/ > > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> > > Signed-off-by: Naman Gulati <namangulati@google.com> > > --- > > Note that the reproducer attached to the syzbot bug targets a different > > bug (via devlink_port_notify() on netns teardown) that happens to share > > the same crash title, not the one in the original reported crash report. > > --- > > net/core/netdev-genl.c | 6 ++++++ > > 1 file changed, 6 insertions(+) > > > > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c > > index 33b9f4eb9565a..2032ab9a864c2 100644 > > --- a/net/core/netdev-genl.c > > +++ b/net/core/netdev-genl.c > > @@ -1487,6 +1487,12 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb, > > netdev_unlock_full_to_ops(netdev); > > break; > > case NETDEV_UNREGISTER: > > + /* netdev_wait_allrefs_any() rebroadcasts NETDEV_UNREGISTER > > + * while waiting for the last references to be dropped; the > > + * netns may already be torn down by then. Notify only once. > > + */ > > [..] > > > + if (READ_ONCE(netdev->reg_state) == NETREG_UNREGISTERED) > > + break; > > Same as > https://lore.kernel.org/netdev/20261026063743.1797-1-lege.wang@jaguarmicro.com/ > ? Yes, sorry, same as that patch - which I missed. The author sent that as an RFC and mentioned they're happy for someone else to take it over. I'm happy to iterate on this and credit them unless Xiaoguang prefers to keep working on it. > > reg_state is protected by netdev, why not do this under netdev_lock? No strong reason. I read it outside the lock because the rebroadcast runs on the same thread that set NETREG_UNREGISTERED in netdev_run_todo() so reading reg_state under the lock is not strictly required, but we take the lock right below so can move it there if prefered. > Also seems like we are fixing a symptom, not the problem? Since 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()"), cleanup_net() doesn't wait for devices stuck in netdev_wait_allrefs_any(), so the rebroadcast can reach notifiers after the device's netns has already exited. However the rebroadcast is only a retry to make ref holders let go, not a new event, yet netdev-genl sends userspace another DEL_NTF for each one. I don't think userspace should receive these redundant notifications, even if the device still exists and we avoid the null-ptr-deref. ip6_route_dev_notify() and mlxsw_sp_netdevice_unregister() already skip handling the rebroadcasts the same way, by checking for NETREG_UNREGISTERED. pw-bot: changes-requested > > > netdev_lock(netdev); > > netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF); > > netdev_unlock(netdev); ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts 2026-10-26 22:28 ` Stanislav Fomichev 2026-10-26 23:27 ` Naman Gulati @ 2026-10-27 1:47 ` Kuniyuki Iwashima 2026-10-28 16:37 ` Stanislav Fomichev 1 sibling, 1 reply; 6+ messages in thread From: Kuniyuki Iwashima @ 2026-10-27 1:47 UTC (permalink / raw) To: Stanislav Fomichev Cc: Naman Gulati, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-kernel, syzbot+1269fe6cc2016008124e On Mon, 26 Oct 2026 15:28:44 -0700, Stanislav Fomichev wrote: > On 10/26, Naman Gulati wrote: > > netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while > > it waits for the last references on a device to be dropped. By then > > netdev_run_todo() has already marked the device NETREG_UNREGISTERED and > > RTNL has been dropped at least once since the initial notification sent > > by unregister_netdevice_many_notify(). > > > > netdev_genl_netdevice_event() does not tell these rebroadcasts apart > > from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF > > multicast for each of them. At best this spams NETDEV_NLGRP_MGMT > > listeners with duplicate notifications; at worst the pernet state of > > the netns the device belongs to is already gone and the handler > > dereferences a NULL pointer. > > > > default_device_exit_batch() only unregisters the devices still listed > > in the exiting netns; it does not wait for in-flight unregistrations of > > devices that were already unlisted (the barrier doing that was removed > > by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")). > > So when a device is unregistered by something other than the > > cleanup_net() of its own netns while references on it are still held, > > e.g. a veth whose peer in another netns gets deleted, and that netns > > exits while the device is stuck in netdev_wait_allrefs_any(), the > > remaining pernet exit handlers run and genl_pernet_exit() sets > > net->genl_sock to NULL. The next rebroadcast then crashes in > > genl_has_listeners(): > > > > BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > Read of size 8 at addr 0000000000000578 by task syz.0.0/5325 > > Call Trace: > > <TASK> > > netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > genl_has_listeners include/net/genetlink.h:644 [inline] > > netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93 > > netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491 > > notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 > > netdev_wait_allrefs_any net/core/dev.c:11690 [inline] > > netdev_run_todo+0x731/0x1060 net/core/dev.c:11808 > > rtnl_unlock net/core/rtnetlink.c:157 [inline] > > rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707 > > > > syzbot hit this by moving one end of a veth pair into a short-lived > > netns while netdevsim's deferred FIB event processing still held a > > reference on it, and then deleting the other end (repro [1]). While the > > source of this bug is netdevsim deferring FIB processing for and holding > > onto the device reference for O(seconds) which is being fixed > > separately [2], any driver may introduce such a delay and trigger the > > null-ptr-deref. > > > > Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events > > delivered with reg_state == NETREG_UNREGISTERED. The notifications sent > > by unregister_netdevice_many_notify() and, for a device leaving a netns, > > by __dev_change_net_namespace() are issued under RTNL in the same > > critical section that unlists the device, before its netns can be torn > > down, and keep being handled. This mirrors what ip6_route_dev_notify() > > already does to cope with the rebroadcasts. > > > > This change should not break the UAPI spec as it defines dev-del-ntf as > > a "Notification about device disappearing." which is a single event. The > > rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel > > subsystems holding references; netdev-genl happens to be on the notifier > > chain and forwards it. > > > > [1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae > > [2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com > > > > Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") > > Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com > > Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/ > > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> > > Signed-off-by: Naman Gulati <namangulati@google.com> > > --- > > Note that the reproducer attached to the syzbot bug targets a different > > bug (via devlink_port_notify() on netns teardown) that happens to share > > the same crash title, not the one in the original reported crash report. > > --- > > net/core/netdev-genl.c | 6 ++++++ > > 1 file changed, 6 insertions(+) > > > > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c > > index 33b9f4eb9565a..2032ab9a864c2 100644 > > --- a/net/core/netdev-genl.c > > +++ b/net/core/netdev-genl.c > > @@ -1487,6 +1487,12 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb, > > netdev_unlock_full_to_ops(netdev); > > break; > > case NETDEV_UNREGISTER: > > + /* netdev_wait_allrefs_any() rebroadcasts NETDEV_UNREGISTER > > + * while waiting for the last references to be dropped; the > > + * netns may already be torn down by then. Notify only once. > > + */ > > [..] > > > + if (READ_ONCE(netdev->reg_state) == NETREG_UNREGISTERED) > > + break; > > Same as > https://lore.kernel.org/netdev/20261026063743.1797-1-lege.wang@jaguarmicro.com/ > ? > > reg_state is protected by netdev, why not do this under netdev_lock? > Also seems like we are fixing a symptom, not the problem? fwiw, I suggested not to take the lock since we are only interested in NETREG_UNREGISTERED here and there is a clear ordering in the case. The root cause is netdevsim this time, and I have a fix, https://syzkaller.appspot.com/text?tag=Patch&x=15923c21580000 but rebroadcast itself is not-ideal-but-valid behaviour, so each NETDEV_UNREGISTER must be idempotent unless we can completley remove the rebroadcast mechanism itself in the future. > > > netdev_lock(netdev); > > netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF); > > netdev_unlock(netdev); ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts 2026-10-27 1:47 ` Kuniyuki Iwashima @ 2026-10-28 16:37 ` Stanislav Fomichev 0 siblings, 0 replies; 6+ messages in thread From: Stanislav Fomichev @ 2026-10-28 16:37 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: Naman Gulati, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-kernel, syzbot+1269fe6cc2016008124e On 10/27, Kuniyuki Iwashima wrote: > On Mon, 26 Oct 2026 15:28:44 -0700, Stanislav Fomichev wrote: > > On 10/26, Naman Gulati wrote: > > > netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while > > > it waits for the last references on a device to be dropped. By then > > > netdev_run_todo() has already marked the device NETREG_UNREGISTERED and > > > RTNL has been dropped at least once since the initial notification sent > > > by unregister_netdevice_many_notify(). > > > > > > netdev_genl_netdevice_event() does not tell these rebroadcasts apart > > > from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF > > > multicast for each of them. At best this spams NETDEV_NLGRP_MGMT > > > listeners with duplicate notifications; at worst the pernet state of > > > the netns the device belongs to is already gone and the handler > > > dereferences a NULL pointer. > > > > > > default_device_exit_batch() only unregisters the devices still listed > > > in the exiting netns; it does not wait for in-flight unregistrations of > > > devices that were already unlisted (the barrier doing that was removed > > > by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")). > > > So when a device is unregistered by something other than the > > > cleanup_net() of its own netns while references on it are still held, > > > e.g. a veth whose peer in another netns gets deleted, and that netns > > > exits while the device is stuck in netdev_wait_allrefs_any(), the > > > remaining pernet exit handlers run and genl_pernet_exit() sets > > > net->genl_sock to NULL. The next rebroadcast then crashes in > > > genl_has_listeners(): > > > > > > BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > > Read of size 8 at addr 0000000000000578 by task syz.0.0/5325 > > > Call Trace: > > > <TASK> > > > netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388 > > > genl_has_listeners include/net/genetlink.h:644 [inline] > > > netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93 > > > netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491 > > > notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85 > > > netdev_wait_allrefs_any net/core/dev.c:11690 [inline] > > > netdev_run_todo+0x731/0x1060 net/core/dev.c:11808 > > > rtnl_unlock net/core/rtnetlink.c:157 [inline] > > > rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707 > > > > > > syzbot hit this by moving one end of a veth pair into a short-lived > > > netns while netdevsim's deferred FIB event processing still held a > > > reference on it, and then deleting the other end (repro [1]). While the > > > source of this bug is netdevsim deferring FIB processing for and holding > > > onto the device reference for O(seconds) which is being fixed > > > separately [2], any driver may introduce such a delay and trigger the > > > null-ptr-deref. > > > > > > Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events > > > delivered with reg_state == NETREG_UNREGISTERED. The notifications sent > > > by unregister_netdevice_many_notify() and, for a device leaving a netns, > > > by __dev_change_net_namespace() are issued under RTNL in the same > > > critical section that unlists the device, before its netns can be torn > > > down, and keep being handled. This mirrors what ip6_route_dev_notify() > > > already does to cope with the rebroadcasts. > > > > > > This change should not break the UAPI spec as it defines dev-del-ntf as > > > a "Notification about device disappearing." which is a single event. The > > > rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel > > > subsystems holding references; netdev-genl happens to be on the notifier > > > chain and forwards it. > > > > > > [1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae > > > [2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com > > > > > > Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff") > > > Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com > > > Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/ > > > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> > > > Signed-off-by: Naman Gulati <namangulati@google.com> > > > --- > > > Note that the reproducer attached to the syzbot bug targets a different > > > bug (via devlink_port_notify() on netns teardown) that happens to share > > > the same crash title, not the one in the original reported crash report. > > > --- > > > net/core/netdev-genl.c | 6 ++++++ > > > 1 file changed, 6 insertions(+) > > > > > > diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c > > > index 33b9f4eb9565a..2032ab9a864c2 100644 > > > --- a/net/core/netdev-genl.c > > > +++ b/net/core/netdev-genl.c > > > @@ -1487,6 +1487,12 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb, > > > netdev_unlock_full_to_ops(netdev); > > > break; > > > case NETDEV_UNREGISTER: > > > + /* netdev_wait_allrefs_any() rebroadcasts NETDEV_UNREGISTER > > > + * while waiting for the last references to be dropped; the > > > + * netns may already be torn down by then. Notify only once. > > > + */ > > > > [..] > > > > > + if (READ_ONCE(netdev->reg_state) == NETREG_UNREGISTERED) > > > + break; > > > > Same as > > https://lore.kernel.org/netdev/20261026063743.1797-1-lege.wang@jaguarmicro.com/ > > ? > > > > reg_state is protected by netdev, why not do this under netdev_lock? > > Also seems like we are fixing a symptom, not the problem? > > fwiw, I suggested not to take the lock since we are only interested > in NETREG_UNREGISTERED here and there is a clear ordering in the case. > > The root cause is netdevsim this time, and I have a fix, > > https://syzkaller.appspot.com/text?tag=Patch&x=15923c21580000 > > but rebroadcast itself is not-ideal-but-valid behaviour, so each > NETDEV_UNREGISTER must be idempotent unless we can completley remove > the rebroadcast mechanism itself in the future. (to both you and Naman) Idk, I haven't looked deep into that, it just reads a bit weird that we call the notifiers only then to filter (some of?) them out later. While this patch might fix a narrow race I wonder if we are missing a bigger picture (for example, why not get back to pre commit 8a4fc54b07d7 state?). ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts 2026-10-26 22:13 [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts Naman Gulati 2026-10-26 22:28 ` Stanislav Fomichev @ 2026-10-29 16:10 ` patchwork-bot+netdevbpf 1 sibling, 0 replies; 6+ messages in thread From: patchwork-bot+netdevbpf @ 2026-10-29 16:10 UTC (permalink / raw) To: Naman Gulati Cc: davem, edumazet, kuba, pabeni, horms, kuniyu, netdev, linux-kernel, syzbot+1269fe6cc2016008124e Hello: This patch was applied to netdev/net.git (main) by Jakub Kicinski <kuba@kernel.org>: On Mon, 26 Oct 2026 22:13:06 +0000 you wrote: > netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while > it waits for the last references on a device to be dropped. By then > netdev_run_todo() has already marked the device NETREG_UNREGISTERED and > RTNL has been dropped at least once since the initial notification sent > by unregister_netdevice_many_notify(). > > netdev_genl_netdevice_event() does not tell these rebroadcasts apart > from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF > multicast for each of them. At best this spams NETDEV_NLGRP_MGMT > listeners with duplicate notifications; at worst the pernet state of > the netns the device belongs to is already gone and the handler > dereferences a NULL pointer. > > [...] Here is the summary with links: - [net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts https://git.kernel.org/netdev/net/c/fd0909e963ed You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-29 16:10 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-26 22:13 [PATCH net] netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts Naman Gulati 2026-10-26 22:28 ` Stanislav Fomichev 2026-10-26 23:27 ` Naman Gulati 2026-10-27 1:47 ` Kuniyuki Iwashima 2026-10-28 16:37 ` Stanislav Fomichev 2026-10-29 16:10 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox