]>
Commit | Line | Data |
---|---|---|
6c46aeae GKH |
1 | From 526f5b851a96566803ee4bee60d0a34df56c77f8 Mon Sep 17 00:00:00 2001 |
2 | From: Junwei Hu <hujunwei4@huawei.com> | |
3 | Date: Mon, 20 May 2019 14:43:59 +0800 | |
4 | Subject: tipc: fix modprobe tipc failed after switch order of device registration | |
5 | ||
6 | From: Junwei Hu <hujunwei4@huawei.com> | |
7 | ||
8 | commit 526f5b851a96566803ee4bee60d0a34df56c77f8 upstream. | |
9 | ||
10 | Error message printed: | |
11 | modprobe: ERROR: could not insert 'tipc': Address family not | |
12 | supported by protocol. | |
13 | when modprobe tipc after the following patch: switch order of | |
14 | device registration, commit 7e27e8d6130c | |
15 | ("tipc: switch order of device registration to fix a crash") | |
16 | ||
17 | Because sock_create_kern(net, AF_TIPC, ...) called by | |
18 | tipc_topsrv_create_listener() in the initialization process | |
19 | of tipc_init_net(), so tipc_socket_init() must be execute before that. | |
20 | Meanwhile, tipc_net_id need to be initialized when sock_create() | |
21 | called, and tipc_socket_init() is no need to be called for each namespace. | |
22 | ||
23 | I add a variable tipc_topsrv_net_ops, and split the | |
24 | register_pernet_subsys() of tipc into two parts, and split | |
25 | tipc_socket_init() with initialization of pernet params. | |
26 | ||
27 | By the way, I fixed resources rollback error when tipc_bcast_init() | |
28 | failed in tipc_init_net(). | |
29 | ||
30 | Fixes: 7e27e8d6130c ("tipc: switch order of device registration to fix a crash") | |
31 | Signed-off-by: Junwei Hu <hujunwei4@huawei.com> | |
32 | Reported-by: Wang Wang <wangwang2@huawei.com> | |
33 | Reported-by: syzbot+1e8114b61079bfe9cbc5@syzkaller.appspotmail.com | |
34 | Reviewed-by: Kang Zhou <zhoukang7@huawei.com> | |
35 | Reviewed-by: Suanming Mou <mousuanming@huawei.com> | |
36 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
37 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
38 | ||
39 | --- | |
40 | net/tipc/core.c | 18 ++++++++++++------ | |
41 | net/tipc/subscr.h | 5 +++-- | |
42 | net/tipc/topsrv.c | 14 ++++++++++++-- | |
43 | 3 files changed, 27 insertions(+), 10 deletions(-) | |
44 | ||
45 | --- a/net/tipc/core.c | |
46 | +++ b/net/tipc/core.c | |
47 | @@ -75,9 +75,6 @@ static int __net_init tipc_init_net(stru | |
48 | goto out_nametbl; | |
49 | ||
50 | INIT_LIST_HEAD(&tn->dist_queue); | |
51 | - err = tipc_topsrv_start(net); | |
52 | - if (err) | |
53 | - goto out_subscr; | |
54 | ||
55 | err = tipc_bcast_init(net); | |
56 | if (err) | |
57 | @@ -86,8 +83,6 @@ static int __net_init tipc_init_net(stru | |
58 | return 0; | |
59 | ||
60 | out_bclink: | |
61 | - tipc_bcast_stop(net); | |
62 | -out_subscr: | |
63 | tipc_nametbl_stop(net); | |
64 | out_nametbl: | |
65 | tipc_sk_rht_destroy(net); | |
66 | @@ -97,7 +92,6 @@ out_sk_rht: | |
67 | ||
68 | static void __net_exit tipc_exit_net(struct net *net) | |
69 | { | |
70 | - tipc_topsrv_stop(net); | |
71 | tipc_net_stop(net); | |
72 | tipc_bcast_stop(net); | |
73 | tipc_nametbl_stop(net); | |
74 | @@ -111,6 +105,11 @@ static struct pernet_operations tipc_net | |
75 | .size = sizeof(struct tipc_net), | |
76 | }; | |
77 | ||
78 | +static struct pernet_operations tipc_topsrv_net_ops = { | |
79 | + .init = tipc_topsrv_init_net, | |
80 | + .exit = tipc_topsrv_exit_net, | |
81 | +}; | |
82 | + | |
83 | static int __init tipc_init(void) | |
84 | { | |
85 | int err; | |
86 | @@ -141,6 +140,10 @@ static int __init tipc_init(void) | |
87 | if (err) | |
88 | goto out_socket; | |
89 | ||
90 | + err = register_pernet_subsys(&tipc_topsrv_net_ops); | |
91 | + if (err) | |
92 | + goto out_pernet_topsrv; | |
93 | + | |
94 | err = tipc_bearer_setup(); | |
95 | if (err) | |
96 | goto out_bearer; | |
97 | @@ -148,6 +151,8 @@ static int __init tipc_init(void) | |
98 | pr_info("Started in single node mode\n"); | |
99 | return 0; | |
100 | out_bearer: | |
101 | + unregister_pernet_subsys(&tipc_topsrv_net_ops); | |
102 | +out_pernet_topsrv: | |
103 | tipc_socket_stop(); | |
104 | out_socket: | |
105 | unregister_pernet_subsys(&tipc_net_ops); | |
106 | @@ -165,6 +170,7 @@ out_netlink: | |
107 | static void __exit tipc_exit(void) | |
108 | { | |
109 | tipc_bearer_cleanup(); | |
110 | + unregister_pernet_subsys(&tipc_topsrv_net_ops); | |
111 | tipc_socket_stop(); | |
112 | unregister_pernet_subsys(&tipc_net_ops); | |
113 | tipc_netlink_stop(); | |
114 | --- a/net/tipc/subscr.h | |
115 | +++ b/net/tipc/subscr.h | |
116 | @@ -77,8 +77,9 @@ void tipc_sub_report_overlap(struct tipc | |
117 | u32 found_lower, u32 found_upper, | |
118 | u32 event, u32 port, u32 node, | |
119 | u32 scope, int must); | |
120 | -int tipc_topsrv_start(struct net *net); | |
121 | -void tipc_topsrv_stop(struct net *net); | |
122 | + | |
123 | +int __net_init tipc_topsrv_init_net(struct net *net); | |
124 | +void __net_exit tipc_topsrv_exit_net(struct net *net); | |
125 | ||
126 | void tipc_sub_put(struct tipc_subscription *subscription); | |
127 | void tipc_sub_get(struct tipc_subscription *subscription); | |
128 | --- a/net/tipc/topsrv.c | |
129 | +++ b/net/tipc/topsrv.c | |
130 | @@ -635,7 +635,7 @@ static void tipc_topsrv_work_stop(struct | |
131 | destroy_workqueue(s->send_wq); | |
132 | } | |
133 | ||
134 | -int tipc_topsrv_start(struct net *net) | |
135 | +static int tipc_topsrv_start(struct net *net) | |
136 | { | |
137 | struct tipc_net *tn = tipc_net(net); | |
138 | const char name[] = "topology_server"; | |
139 | @@ -668,7 +668,7 @@ int tipc_topsrv_start(struct net *net) | |
140 | return ret; | |
141 | } | |
142 | ||
143 | -void tipc_topsrv_stop(struct net *net) | |
144 | +static void tipc_topsrv_stop(struct net *net) | |
145 | { | |
146 | struct tipc_topsrv *srv = tipc_topsrv(net); | |
147 | struct socket *lsock = srv->listener; | |
148 | @@ -693,3 +693,13 @@ void tipc_topsrv_stop(struct net *net) | |
149 | idr_destroy(&srv->conn_idr); | |
150 | kfree(srv); | |
151 | } | |
152 | + | |
153 | +int __net_init tipc_topsrv_init_net(struct net *net) | |
154 | +{ | |
155 | + return tipc_topsrv_start(net); | |
156 | +} | |
157 | + | |
158 | +void __net_exit tipc_topsrv_exit_net(struct net *net) | |
159 | +{ | |
160 | + tipc_topsrv_stop(net); | |
161 | +} |