diff options
| author | Bernard Pidoux <bernard.f6bvp@gmail.com> | 2026-05-26 15:57:47 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-06-27 11:07:39 +0100 |
| commit | 4e5848f3e04be9f427fa912a15cc54f032f059cd (patch) | |
| tree | bf80b0447959d774b99d04c6868a6ae941999b1c | |
| parent | fd6ae188077362567b06b189c87bbde4cadde717 (diff) | |
| download | linux-stable-4e5848f3e04be9f427fa912a15cc54f032f059cd.tar.gz linux-stable-4e5848f3e04be9f427fa912a15cc54f032f059cd.zip | |
rose: fix notifier unregistered too early in rose_exit()
commit f71a8a1edc14dba746edde38adddd654ba202b4d upstream.
rose_exit() called unregister_netdevice_notifier() before the loop that
calls unregister_netdev() on each ROSE virtual device. As a result,
the NETDEV_DOWN event fired by unregister_netdev() was never delivered
to rose_device_event(), so rose_kill_by_device() never ran.
Every socket whose rose->device pointed at a ROSE device therefore kept
its netdev_tracker entry live until free_netdev() destroyed the
ref_tracker_dir, at which point the kernel reported all of them as
leaked references (165 entries in a typical FPAC setup). Worse, those
sockets retained stale device pointers and live timers that could fire
into freed module text after module unload, causing a silent system
freeze with no kernel panic logged.
Fix by moving unregister_netdevice_notifier() to after the device-
unregistration loop. unregister_netdev() then delivers NETDEV_DOWN
while the notifier is still registered, rose_kill_by_device() runs for
each device, releases all netdev references held by open sockets, and
calls rose_disconnect() which stops the per-socket timers.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | net/rose/af_rose.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 7667278ad99c..64dfdf398ee0 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1669,19 +1669,28 @@ static void __exit rose_exit(void) #ifdef CONFIG_SYSCTL rose_unregister_sysctl(); #endif - unregister_netdevice_notifier(&rose_dev_notifier); - sock_unregister(PF_ROSE); for (i = 0; i < rose_ndevs; i++) { struct net_device *dev = dev_rose[i]; if (dev) { + /* unregister_netdev() fires NETDEV_DOWN, which -- while the + * notifier is still registered below -- invokes + * rose_kill_by_device(dev). That releases every socket's + * netdev reference and disconnects all active circuits. + * Unregistering the notifier before this loop was the + * original bug: NETDEV_DOWN was never delivered, leaving + * 165 netdev_tracker entries leaked and stale timers live. + */ unregister_netdev(dev); free_netdev(dev); } } + /* Now safe to remove the notifier -- all ROSE devices are gone. */ + unregister_netdevice_notifier(&rose_dev_notifier); + kfree(dev_rose); proto_unregister(&rose_proto); } |
