[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <6674f2cd-53bc-bb9a-931e-d4dde6ef01e8@huawei.com>
Date: Thu, 16 May 2019 10:51:15 +0800
From: hujunwei <hujunwei4@...wei.com>
To: <jon.maloy@...csson.com>, <ying.xue@...driver.com>,
<davem@...emloft.net>
CC: "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
<tipc-discussion@...ts.sourceforge.net>, <mingfangsen@...wei.com>,
<wangxiaogang3@...wei.com>, <wangwang2@...wei.com>
Subject: [PATCH] tipc: switch order of device registration to fix a crash
From: Junwei Hu <hujunwei4@...wei.com>
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@...wei.com>
Reported-by: Wang Wang <wangwang2@...wei.com>
Reviewed-by: Xiaogang Wang <wangxiaogang3@...wei.com>
---
net/tipc/core.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 5b38f5164281..dbfc1e8b2866 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -129,10 +129,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;
@@ -141,6 +137,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;
@@ -148,12 +148,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();
@@ -165,10 +165,10 @@ static int __init tipc_init(void)
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");
--
2.21.GIT
Powered by blists - more mailing lists