summaryrefslogtreecommitdiff
authorJunwei Hu <hujunwei4@huawei.com>2019-05-16 02:51:15 (GMT)
committer Greg Kroah-Hartman <gregkh@linuxfoundation.org>2019-05-25 16:26:44 (GMT)
commita336df52d00791b90970a419c5458068ff4e3c26 (patch)
treeb9ec1f1567e885ce02440e8f4b5c7a07d1637f97
parentdcdc0a49a5cbf2b8607a8a154d870242bf0c2f76 (diff)
downloadcommon-a336df52d00791b90970a419c5458068ff4e3c26.zip
common-a336df52d00791b90970a419c5458068ff4e3c26.tar.gz
common-a336df52d00791b90970a419c5458068ff4e3c26.tar.bz2
tipc: switch order of device registration to fix a crash
[ Upstream commit 7e27e8d6130c5e88fac9ddec4249f7f2337fe7f8 ] 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: a62fbccecd62 ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat
-rw-r--r--net/tipc/core.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 236b043..bf77321 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -125,10 +125,6 @@ static int __init tipc_init(void)
if (err)
goto out_netlink_compat;
- err = tipc_socket_init();
- if (err)
- goto out_socket;
-
err = tipc_register_sysctl();
if (err)
goto out_sysctl;
@@ -137,6 +133,10 @@ static int __init tipc_init(void)
if (err)
goto out_pernet;
+ err = tipc_socket_init();
+ if (err)
+ goto out_socket;
+
err = tipc_bearer_setup();
if (err)
goto out_bearer;
@@ -144,12 +144,12 @@ static int __init tipc_init(void)
pr_info("Started in single node mode\n");
return 0;
out_bearer:
+ tipc_socket_stop();
+out_socket:
unregister_pernet_subsys(&tipc_net_ops);
out_pernet:
tipc_unregister_sysctl();
out_sysctl:
- tipc_socket_stop();
-out_socket:
tipc_netlink_compat_stop();
out_netlink_compat:
tipc_netlink_stop();
@@ -161,10 +161,10 @@ out_netlink:
static void __exit tipc_exit(void)
{
tipc_bearer_cleanup();
+ tipc_socket_stop();
unregister_pernet_subsys(&tipc_net_ops);
tipc_netlink_stop();
tipc_netlink_compat_stop();
- tipc_socket_stop();
tipc_unregister_sysctl();
pr_info("Deactivated\n");