]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
phonet: check register_netdevice_notifier() error in phonet_device_init()
authorMinhong He <heminhong@kylinos.cn>
Tue, 21 Jul 2026 09:39:56 +0000 (17:39 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 23 Jul 2026 17:28:50 +0000 (10:28 -0700)
phonet_device_init() registers a netdevice notifier before calling
phonet_netlink_register(), but does not check whether notifier
registration succeeded. On failure, netlink setup still proceeds and
init may return success without the notifier in place.

Also, the existing phonet_netlink_register() failure path called
phonet_device_exit(), which runs rtnl_unregister_all() even though
rtnl_register_many() already unwound any partial registration. Calling
the full exit helper on a partial init is not correct.

Check each registration error, including proc_create_net(), and unwind
only the steps that have succeeded so far, in reverse order.

Signed-off-by: Minhong He <heminhong@kylinos.cn>
Link: https://patch.msgid.link/20260721093956.162617-1-heminhong@kylinos.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/phonet/pn_dev.c

index ad44831d674527879319476469173ef69ffb8e7d..1272d49cd0385f879bf6b95d6680a43a5ffc5f30 100644 (file)
@@ -350,16 +350,34 @@ static struct pernet_operations phonet_net_ops = {
 /* Initialize Phonet devices list */
 int __init phonet_device_init(void)
 {
-       int err = register_pernet_subsys(&phonet_net_ops);
+       int err;
+
+       err = register_pernet_subsys(&phonet_net_ops);
        if (err)
                return err;
 
-       proc_create_net("pnresource", 0, init_net.proc_net, &pn_res_seq_ops,
-                       sizeof(struct seq_net_private));
-       register_netdevice_notifier(&phonet_device_notifier);
+       if (!proc_create_net("pnresource", 0, init_net.proc_net,
+                            &pn_res_seq_ops, sizeof(struct seq_net_private))) {
+               err = -ENOMEM;
+               goto err_pernet;
+       }
+
+       err = register_netdevice_notifier(&phonet_device_notifier);
+       if (err)
+               goto err_proc;
+
        err = phonet_netlink_register();
        if (err)
-               phonet_device_exit();
+               goto err_notifier;
+
+       return 0;
+
+err_notifier:
+       unregister_netdevice_notifier(&phonet_device_notifier);
+err_proc:
+       remove_proc_entry("pnresource", init_net.proc_net);
+err_pernet:
+       unregister_pernet_subsys(&phonet_net_ops);
        return err;
 }
 
@@ -367,8 +385,8 @@ void phonet_device_exit(void)
 {
        rtnl_unregister_all(PF_PHONET);
        unregister_netdevice_notifier(&phonet_device_notifier);
-       unregister_pernet_subsys(&phonet_net_ops);
        remove_proc_entry("pnresource", init_net.proc_net);
+       unregister_pernet_subsys(&phonet_net_ops);
 }
 
 int phonet_route_add(struct net_device *dev, u8 daddr)