missing bits of net-namespace / sysctl

Piss-poor sysctl registration API strikes again, film at 11...

What we really need is _pathname_ required to be present in already
registered table, so that kernel could warn about bad order. That's the
next target for sysctl stuff (and generally saner and more explicit
order of initialization of ipv[46] internals wouldn't hurt either).

For the time being, here are full fixups required by ..._rotable()
stuff; we make per-net sysctl sets descendents of "ro" one and make sure
that sufficient skeleton is there before we start registering per-net
sysctls.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Al Viro and committed by
Linus Torvalds
eeb61f71 bfbcf034

+43 -18
+2
include/net/ipv6.h
··· 608 608 extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); 609 609 extern int ipv6_sysctl_register(void); 610 610 extern void ipv6_sysctl_unregister(void); 611 + extern int ipv6_static_sysctl_register(void); 612 + extern void ipv6_static_sysctl_unregister(void); 611 613 #endif 612 614 613 615 #endif /* __KERNEL__ */
-2
include/net/route.h
··· 204 204 return rt->peer; 205 205 } 206 206 207 - extern ctl_table ipv4_route_table[]; 208 - 209 207 #endif /* _ROUTE_H */
+10 -1
net/ipv4/route.c
··· 2914 2914 return 0; 2915 2915 } 2916 2916 2917 - ctl_table ipv4_route_table[] = { 2917 + static ctl_table ipv4_route_table[] = { 2918 2918 { 2919 2919 .ctl_name = NET_IPV4_ROUTE_GC_THRESH, 2920 2920 .procname = "gc_thresh", ··· 3214 3214 register_pernet_subsys(&sysctl_route_ops); 3215 3215 #endif 3216 3216 return rc; 3217 + } 3218 + 3219 + /* 3220 + * We really need to sanitize the damn ipv4 init order, then all 3221 + * this nonsense will go away. 3222 + */ 3223 + void __init ip_static_sysctl_init(void) 3224 + { 3225 + register_sysctl_paths(ipv4_route_path, ipv4_route_table); 3217 3226 } 3218 3227 3219 3228 EXPORT_SYMBOL(__ip_select_ident);
-14
net/ipv4/sysctl_net_ipv4.c
··· 401 401 .proc_handler = &ipv4_local_port_range, 402 402 .strategy = &ipv4_sysctl_local_port_range, 403 403 }, 404 - { 405 - .ctl_name = NET_IPV4_ROUTE, 406 - .procname = "route", 407 - .maxlen = 0, 408 - .mode = 0555, 409 - .child = ipv4_route_table 410 - }, 411 404 #ifdef CONFIG_IP_MULTICAST 412 405 { 413 406 .ctl_name = NET_IPV4_IGMP_MAX_MEMBERSHIPS, ··· 873 880 } 874 881 875 882 return 0; 876 - } 877 - 878 - /* set enough of tree skeleton to get rid of ordering problems */ 879 - void __init ip_static_sysctl_init(void) 880 - { 881 - static ctl_table table[1]; 882 - register_sysctl_paths(net_ipv4_ctl_path, table); 883 883 } 884 884 885 885 __initcall(sysctl_ipv4_init);
+12
net/ipv6/af_inet6.c
··· 934 934 if (err) 935 935 goto out_unregister_sock; 936 936 937 + #ifdef CONFIG_SYSCTL 938 + err = ipv6_static_sysctl_register(); 939 + if (err) 940 + goto static_sysctl_fail; 941 + #endif 937 942 /* 938 943 * ipngwg API draft makes clear that the correct semantics 939 944 * for TCP and UDP is to consider one TCP and UDP instance ··· 1063 1058 icmp_fail: 1064 1059 unregister_pernet_subsys(&inet6_net_ops); 1065 1060 register_pernet_fail: 1061 + #ifdef CONFIG_SYSCTL 1062 + ipv6_static_sysctl_unregister(); 1063 + static_sysctl_fail: 1064 + #endif 1066 1065 cleanup_ipv6_mibs(); 1067 1066 out_unregister_sock: 1068 1067 sock_unregister(PF_INET6); ··· 1122 1113 rawv6_exit(); 1123 1114 1124 1115 unregister_pernet_subsys(&inet6_net_ops); 1116 + #ifdef CONFIG_SYSCTL 1117 + ipv6_static_sysctl_unregister(); 1118 + #endif 1125 1119 cleanup_ipv6_mibs(); 1126 1120 proto_unregister(&rawv6_prot); 1127 1121 proto_unregister(&udplitev6_prot);
+16
net/ipv6/sysctl_net_ipv6.c
··· 150 150 unregister_net_sysctl_table(ip6_header); 151 151 unregister_pernet_subsys(&ipv6_sysctl_net_ops); 152 152 } 153 + 154 + static struct ctl_table_header *ip6_base; 155 + 156 + int ipv6_static_sysctl_register(void) 157 + { 158 + static struct ctl_table empty[1]; 159 + ip6_base = register_net_sysctl_rotable(net_ipv6_ctl_path, empty); 160 + if (ip6_base == NULL) 161 + return -ENOMEM; 162 + return 0; 163 + } 164 + 165 + void ipv6_static_sysctl_unregister(void) 166 + { 167 + unregister_net_sysctl_table(ip6_base); 168 + }
+3 -1
net/sysctl_net.c
··· 73 73 74 74 static int sysctl_net_init(struct net *net) 75 75 { 76 - setup_sysctl_set(&net->sysctls, NULL, is_seen); 76 + setup_sysctl_set(&net->sysctls, 77 + &net_sysctl_ro_root.default_set, 78 + is_seen); 77 79 return 0; 78 80 } 79 81