diff options
author | Junwei Hu <hujunwei4@huawei.com> | 2019-05-15 22:51:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-05-16 15:25:02 -0400 |
commit | 7e27e8d6130c5e88fac9ddec4249f7f2337fe7f8 (patch) | |
tree | 79a25be33c426c2ee802da089de94365cd5fde60 /net/tipc | |
parent | 61fb0d01680771f72cc9d39783fb2c122aaad51e (diff) |
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: 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>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/core.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/net/tipc/core.c b/net/tipc/core.c index 27cccd101ef6..ddd2e0f67c07 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -131,10 +131,6 @@ static int __init tipc_init(void) | |||
131 | if (err) | 131 | if (err) |
132 | goto out_netlink_compat; | 132 | goto out_netlink_compat; |
133 | 133 | ||
134 | err = tipc_socket_init(); | ||
135 | if (err) | ||
136 | goto out_socket; | ||
137 | |||
138 | err = tipc_register_sysctl(); | 134 | err = tipc_register_sysctl(); |
139 | if (err) | 135 | if (err) |
140 | goto out_sysctl; | 136 | goto out_sysctl; |
@@ -143,6 +139,10 @@ static int __init tipc_init(void) | |||
143 | if (err) | 139 | if (err) |
144 | goto out_pernet; | 140 | goto out_pernet; |
145 | 141 | ||
142 | err = tipc_socket_init(); | ||
143 | if (err) | ||
144 | goto out_socket; | ||
145 | |||
146 | err = tipc_bearer_setup(); | 146 | err = tipc_bearer_setup(); |
147 | if (err) | 147 | if (err) |
148 | goto out_bearer; | 148 | goto out_bearer; |
@@ -150,12 +150,12 @@ static int __init tipc_init(void) | |||
150 | pr_info("Started in single node mode\n"); | 150 | pr_info("Started in single node mode\n"); |
151 | return 0; | 151 | return 0; |
152 | out_bearer: | 152 | out_bearer: |
153 | tipc_socket_stop(); | ||
154 | out_socket: | ||
153 | unregister_pernet_subsys(&tipc_net_ops); | 155 | unregister_pernet_subsys(&tipc_net_ops); |
154 | out_pernet: | 156 | out_pernet: |
155 | tipc_unregister_sysctl(); | 157 | tipc_unregister_sysctl(); |
156 | out_sysctl: | 158 | out_sysctl: |
157 | tipc_socket_stop(); | ||
158 | out_socket: | ||
159 | tipc_netlink_compat_stop(); | 159 | tipc_netlink_compat_stop(); |
160 | out_netlink_compat: | 160 | out_netlink_compat: |
161 | tipc_netlink_stop(); | 161 | tipc_netlink_stop(); |
@@ -167,10 +167,10 @@ out_netlink: | |||
167 | static void __exit tipc_exit(void) | 167 | static void __exit tipc_exit(void) |
168 | { | 168 | { |
169 | tipc_bearer_cleanup(); | 169 | tipc_bearer_cleanup(); |
170 | tipc_socket_stop(); | ||
170 | unregister_pernet_subsys(&tipc_net_ops); | 171 | unregister_pernet_subsys(&tipc_net_ops); |
171 | tipc_netlink_stop(); | 172 | tipc_netlink_stop(); |
172 | tipc_netlink_compat_stop(); | 173 | tipc_netlink_compat_stop(); |
173 | tipc_socket_stop(); | ||
174 | tipc_unregister_sysctl(); | 174 | tipc_unregister_sysctl(); |
175 | 175 | ||
176 | pr_info("Deactivated\n"); | 176 | pr_info("Deactivated\n"); |