phonet: check register_netdevice_notifier() error in phonet_device_init()

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>
This commit is contained in:
Minhong He 2026-07-21 17:39:56 +08:00 committed by Jakub Kicinski
parent 0f71f852a9
commit d1ff66b661

View 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)