diff options
author | Junwei Hu <hujunwei4@huawei.com> | 2019-05-20 02:43:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-05-20 13:45:43 -0400 |
commit | 526f5b851a96566803ee4bee60d0a34df56c77f8 (patch) | |
tree | 505f467992c5db001e508d31068e1377fcd8aa1b /net/tipc | |
parent | f49aa1de98363b6c5fba4637678d6b0ba3d18065 (diff) |
tipc: fix modprobe tipc failed after switch order of device registration
Error message printed:
modprobe: ERROR: could not insert 'tipc': Address family not
supported by protocol.
when modprobe tipc after the following patch: switch order of
device registration, commit 7e27e8d6130c
("tipc: switch order of device registration to fix a crash")
Because sock_create_kern(net, AF_TIPC, ...) called by
tipc_topsrv_create_listener() in the initialization process
of tipc_init_net(), so tipc_socket_init() must be execute before that.
Meanwhile, tipc_net_id need to be initialized when sock_create()
called, and tipc_socket_init() is no need to be called for each namespace.
I add a variable tipc_topsrv_net_ops, and split the
register_pernet_subsys() of tipc into two parts, and split
tipc_socket_init() with initialization of pernet params.
By the way, I fixed resources rollback error when tipc_bcast_init()
failed in tipc_init_net().
Fixes: 7e27e8d6130c ("tipc: switch order of device registration to fix a crash")
Signed-off-by: Junwei Hu <hujunwei4@huawei.com>
Reported-by: Wang Wang <wangwang2@huawei.com>
Reported-by: syzbot+1e8114b61079bfe9cbc5@syzkaller.appspotmail.com
Reviewed-by: Kang Zhou <zhoukang7@huawei.com>
Reviewed-by: Suanming Mou <mousuanming@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/core.c | 18 | ||||
-rw-r--r-- | net/tipc/subscr.h | 5 | ||||
-rw-r--r-- | net/tipc/topsrv.c | 14 |
3 files changed, 27 insertions, 10 deletions
diff --git a/net/tipc/core.c b/net/tipc/core.c index ddd2e0f67c07..ed536c05252a 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -77,9 +77,6 @@ static int __net_init tipc_init_net(struct net *net) | |||
77 | goto out_nametbl; | 77 | goto out_nametbl; |
78 | 78 | ||
79 | INIT_LIST_HEAD(&tn->dist_queue); | 79 | INIT_LIST_HEAD(&tn->dist_queue); |
80 | err = tipc_topsrv_start(net); | ||
81 | if (err) | ||
82 | goto out_subscr; | ||
83 | 80 | ||
84 | err = tipc_bcast_init(net); | 81 | err = tipc_bcast_init(net); |
85 | if (err) | 82 | if (err) |
@@ -88,8 +85,6 @@ static int __net_init tipc_init_net(struct net *net) | |||
88 | return 0; | 85 | return 0; |
89 | 86 | ||
90 | out_bclink: | 87 | out_bclink: |
91 | tipc_bcast_stop(net); | ||
92 | out_subscr: | ||
93 | tipc_nametbl_stop(net); | 88 | tipc_nametbl_stop(net); |
94 | out_nametbl: | 89 | out_nametbl: |
95 | tipc_sk_rht_destroy(net); | 90 | tipc_sk_rht_destroy(net); |
@@ -99,7 +94,6 @@ out_sk_rht: | |||
99 | 94 | ||
100 | static void __net_exit tipc_exit_net(struct net *net) | 95 | static void __net_exit tipc_exit_net(struct net *net) |
101 | { | 96 | { |
102 | tipc_topsrv_stop(net); | ||
103 | tipc_net_stop(net); | 97 | tipc_net_stop(net); |
104 | tipc_bcast_stop(net); | 98 | tipc_bcast_stop(net); |
105 | tipc_nametbl_stop(net); | 99 | tipc_nametbl_stop(net); |
@@ -113,6 +107,11 @@ static struct pernet_operations tipc_net_ops = { | |||
113 | .size = sizeof(struct tipc_net), | 107 | .size = sizeof(struct tipc_net), |
114 | }; | 108 | }; |
115 | 109 | ||
110 | static struct pernet_operations tipc_topsrv_net_ops = { | ||
111 | .init = tipc_topsrv_init_net, | ||
112 | .exit = tipc_topsrv_exit_net, | ||
113 | }; | ||
114 | |||
116 | static int __init tipc_init(void) | 115 | static int __init tipc_init(void) |
117 | { | 116 | { |
118 | int err; | 117 | int err; |
@@ -143,6 +142,10 @@ static int __init tipc_init(void) | |||
143 | if (err) | 142 | if (err) |
144 | goto out_socket; | 143 | goto out_socket; |
145 | 144 | ||
145 | err = register_pernet_subsys(&tipc_topsrv_net_ops); | ||
146 | if (err) | ||
147 | goto out_pernet_topsrv; | ||
148 | |||
146 | err = tipc_bearer_setup(); | 149 | err = tipc_bearer_setup(); |
147 | if (err) | 150 | if (err) |
148 | goto out_bearer; | 151 | goto out_bearer; |
@@ -150,6 +153,8 @@ static int __init tipc_init(void) | |||
150 | pr_info("Started in single node mode\n"); | 153 | pr_info("Started in single node mode\n"); |
151 | return 0; | 154 | return 0; |
152 | out_bearer: | 155 | out_bearer: |
156 | unregister_pernet_subsys(&tipc_topsrv_net_ops); | ||
157 | out_pernet_topsrv: | ||
153 | tipc_socket_stop(); | 158 | tipc_socket_stop(); |
154 | out_socket: | 159 | out_socket: |
155 | unregister_pernet_subsys(&tipc_net_ops); | 160 | unregister_pernet_subsys(&tipc_net_ops); |
@@ -167,6 +172,7 @@ out_netlink: | |||
167 | static void __exit tipc_exit(void) | 172 | static void __exit tipc_exit(void) |
168 | { | 173 | { |
169 | tipc_bearer_cleanup(); | 174 | tipc_bearer_cleanup(); |
175 | unregister_pernet_subsys(&tipc_topsrv_net_ops); | ||
170 | tipc_socket_stop(); | 176 | tipc_socket_stop(); |
171 | unregister_pernet_subsys(&tipc_net_ops); | 177 | unregister_pernet_subsys(&tipc_net_ops); |
172 | tipc_netlink_stop(); | 178 | tipc_netlink_stop(); |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index d793b4343885..aa015c233898 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -77,8 +77,9 @@ void tipc_sub_report_overlap(struct tipc_subscription *sub, | |||
77 | u32 found_lower, u32 found_upper, | 77 | u32 found_lower, u32 found_upper, |
78 | u32 event, u32 port, u32 node, | 78 | u32 event, u32 port, u32 node, |
79 | u32 scope, int must); | 79 | u32 scope, int must); |
80 | int tipc_topsrv_start(struct net *net); | 80 | |
81 | void tipc_topsrv_stop(struct net *net); | 81 | int __net_init tipc_topsrv_init_net(struct net *net); |
82 | void __net_exit tipc_topsrv_exit_net(struct net *net); | ||
82 | 83 | ||
83 | void tipc_sub_put(struct tipc_subscription *subscription); | 84 | void tipc_sub_put(struct tipc_subscription *subscription); |
84 | void tipc_sub_get(struct tipc_subscription *subscription); | 85 | void tipc_sub_get(struct tipc_subscription *subscription); |
diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index b45932d78004..f345662890a6 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c | |||
@@ -635,7 +635,7 @@ static void tipc_topsrv_work_stop(struct tipc_topsrv *s) | |||
635 | destroy_workqueue(s->send_wq); | 635 | destroy_workqueue(s->send_wq); |
636 | } | 636 | } |
637 | 637 | ||
638 | int tipc_topsrv_start(struct net *net) | 638 | static int tipc_topsrv_start(struct net *net) |
639 | { | 639 | { |
640 | struct tipc_net *tn = tipc_net(net); | 640 | struct tipc_net *tn = tipc_net(net); |
641 | const char name[] = "topology_server"; | 641 | const char name[] = "topology_server"; |
@@ -668,7 +668,7 @@ int tipc_topsrv_start(struct net *net) | |||
668 | return ret; | 668 | return ret; |
669 | } | 669 | } |
670 | 670 | ||
671 | void tipc_topsrv_stop(struct net *net) | 671 | static void tipc_topsrv_stop(struct net *net) |
672 | { | 672 | { |
673 | struct tipc_topsrv *srv = tipc_topsrv(net); | 673 | struct tipc_topsrv *srv = tipc_topsrv(net); |
674 | struct socket *lsock = srv->listener; | 674 | struct socket *lsock = srv->listener; |
@@ -693,3 +693,13 @@ void tipc_topsrv_stop(struct net *net) | |||
693 | idr_destroy(&srv->conn_idr); | 693 | idr_destroy(&srv->conn_idr); |
694 | kfree(srv); | 694 | kfree(srv); |
695 | } | 695 | } |
696 | |||
697 | int __net_init tipc_topsrv_init_net(struct net *net) | ||
698 | { | ||
699 | return tipc_topsrv_start(net); | ||
700 | } | ||
701 | |||
702 | void __net_exit tipc_topsrv_exit_net(struct net *net) | ||
703 | { | ||
704 | tipc_topsrv_stop(net); | ||
705 | } | ||