tipc: switch order of device registration to fix a crash
When tipc is loaded while many processes try to create a TIPC socket,
a crash occurs:
PANIC: Unable to handle kernel paging request at virtual
address "dfff20000000021d"
pc : tipc_sk_create+0x374/0x1180 [tipc]
lr : tipc_sk_create+0x374/0x1180 [tipc]
Exception class = DABT (current EL), IL = 32 bits
Call trace:
tipc_sk_create+0x374/0x1180 [tipc]
__sock_create+0x1cc/0x408
__sys_socket+0xec/0x1f0
__arm64_sys_socket+0x74/0xa8
...
This is due to race between sock_create and unfinished
register_pernet_device. tipc_sk_insert tries to do
"net_generic(net, tipc_net_id)".
but tipc_net_id is not initialized yet.
So switch the order of the two to close the race.
This can be reproduced with multiple processes doing socket(AF_TIPC, ...)
and one process doing module removal.
Fixes: a62fbccecd
("tipc: make subscriber server support net namespace")
Signed-off-by: Junwei Hu <hujunwei4@huawei.com>
Reported-by: Wang Wang <wangwang2@huawei.com>
Reviewed-by: Xiaogang Wang <wangxiaogang3@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
61fb0d0168
commit
7e27e8d613
|
@ -131,10 +131,6 @@ static int __init tipc_init(void)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_netlink_compat;
|
goto out_netlink_compat;
|
||||||
|
|
||||||
err = tipc_socket_init();
|
|
||||||
if (err)
|
|
||||||
goto out_socket;
|
|
||||||
|
|
||||||
err = tipc_register_sysctl();
|
err = tipc_register_sysctl();
|
||||||
if (err)
|
if (err)
|
||||||
goto out_sysctl;
|
goto out_sysctl;
|
||||||
|
@ -143,6 +139,10 @@ static int __init tipc_init(void)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_pernet;
|
goto out_pernet;
|
||||||
|
|
||||||
|
err = tipc_socket_init();
|
||||||
|
if (err)
|
||||||
|
goto out_socket;
|
||||||
|
|
||||||
err = tipc_bearer_setup();
|
err = tipc_bearer_setup();
|
||||||
if (err)
|
if (err)
|
||||||
goto out_bearer;
|
goto out_bearer;
|
||||||
|
@ -150,12 +150,12 @@ static int __init tipc_init(void)
|
||||||
pr_info("Started in single node mode\n");
|
pr_info("Started in single node mode\n");
|
||||||
return 0;
|
return 0;
|
||||||
out_bearer:
|
out_bearer:
|
||||||
|
tipc_socket_stop();
|
||||||
|
out_socket:
|
||||||
unregister_pernet_subsys(&tipc_net_ops);
|
unregister_pernet_subsys(&tipc_net_ops);
|
||||||
out_pernet:
|
out_pernet:
|
||||||
tipc_unregister_sysctl();
|
tipc_unregister_sysctl();
|
||||||
out_sysctl:
|
out_sysctl:
|
||||||
tipc_socket_stop();
|
|
||||||
out_socket:
|
|
||||||
tipc_netlink_compat_stop();
|
tipc_netlink_compat_stop();
|
||||||
out_netlink_compat:
|
out_netlink_compat:
|
||||||
tipc_netlink_stop();
|
tipc_netlink_stop();
|
||||||
|
@ -167,10 +167,10 @@ out_netlink:
|
||||||
static void __exit tipc_exit(void)
|
static void __exit tipc_exit(void)
|
||||||
{
|
{
|
||||||
tipc_bearer_cleanup();
|
tipc_bearer_cleanup();
|
||||||
|
tipc_socket_stop();
|
||||||
unregister_pernet_subsys(&tipc_net_ops);
|
unregister_pernet_subsys(&tipc_net_ops);
|
||||||
tipc_netlink_stop();
|
tipc_netlink_stop();
|
||||||
tipc_netlink_compat_stop();
|
tipc_netlink_compat_stop();
|
||||||
tipc_socket_stop();
|
|
||||||
tipc_unregister_sysctl();
|
tipc_unregister_sysctl();
|
||||||
|
|
||||||
pr_info("Deactivated\n");
|
pr_info("Deactivated\n");
|
||||||
|
|
Loading…
Reference in New Issue