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 extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); 609 extern int ipv6_sysctl_register(void); 610 extern void ipv6_sysctl_unregister(void); 611 #endif 612 613 #endif /* __KERNEL__ */
··· 608 extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); 609 extern int ipv6_sysctl_register(void); 610 extern void ipv6_sysctl_unregister(void); 611 + extern int ipv6_static_sysctl_register(void); 612 + extern void ipv6_static_sysctl_unregister(void); 613 #endif 614 615 #endif /* __KERNEL__ */
-2
include/net/route.h
··· 204 return rt->peer; 205 } 206 207 - extern ctl_table ipv4_route_table[]; 208 - 209 #endif /* _ROUTE_H */
··· 204 return rt->peer; 205 } 206 207 #endif /* _ROUTE_H */
+10 -1
net/ipv4/route.c
··· 2914 return 0; 2915 } 2916 2917 - ctl_table ipv4_route_table[] = { 2918 { 2919 .ctl_name = NET_IPV4_ROUTE_GC_THRESH, 2920 .procname = "gc_thresh", ··· 3214 register_pernet_subsys(&sysctl_route_ops); 3215 #endif 3216 return rc; 3217 } 3218 3219 EXPORT_SYMBOL(__ip_select_ident);
··· 2914 return 0; 2915 } 2916 2917 + static ctl_table ipv4_route_table[] = { 2918 { 2919 .ctl_name = NET_IPV4_ROUTE_GC_THRESH, 2920 .procname = "gc_thresh", ··· 3214 register_pernet_subsys(&sysctl_route_ops); 3215 #endif 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); 3226 } 3227 3228 EXPORT_SYMBOL(__ip_select_ident);
-14
net/ipv4/sysctl_net_ipv4.c
··· 401 .proc_handler = &ipv4_local_port_range, 402 .strategy = &ipv4_sysctl_local_port_range, 403 }, 404 - { 405 - .ctl_name = NET_IPV4_ROUTE, 406 - .procname = "route", 407 - .maxlen = 0, 408 - .mode = 0555, 409 - .child = ipv4_route_table 410 - }, 411 #ifdef CONFIG_IP_MULTICAST 412 { 413 .ctl_name = NET_IPV4_IGMP_MAX_MEMBERSHIPS, ··· 873 } 874 875 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 } 884 885 __initcall(sysctl_ipv4_init);
··· 401 .proc_handler = &ipv4_local_port_range, 402 .strategy = &ipv4_sysctl_local_port_range, 403 }, 404 #ifdef CONFIG_IP_MULTICAST 405 { 406 .ctl_name = NET_IPV4_IGMP_MAX_MEMBERSHIPS, ··· 880 } 881 882 return 0; 883 } 884 885 __initcall(sysctl_ipv4_init);
+12
net/ipv6/af_inet6.c
··· 934 if (err) 935 goto out_unregister_sock; 936 937 /* 938 * ipngwg API draft makes clear that the correct semantics 939 * for TCP and UDP is to consider one TCP and UDP instance ··· 1063 icmp_fail: 1064 unregister_pernet_subsys(&inet6_net_ops); 1065 register_pernet_fail: 1066 cleanup_ipv6_mibs(); 1067 out_unregister_sock: 1068 sock_unregister(PF_INET6); ··· 1122 rawv6_exit(); 1123 1124 unregister_pernet_subsys(&inet6_net_ops); 1125 cleanup_ipv6_mibs(); 1126 proto_unregister(&rawv6_prot); 1127 proto_unregister(&udplitev6_prot);
··· 934 if (err) 935 goto out_unregister_sock; 936 937 + #ifdef CONFIG_SYSCTL 938 + err = ipv6_static_sysctl_register(); 939 + if (err) 940 + goto static_sysctl_fail; 941 + #endif 942 /* 943 * ipngwg API draft makes clear that the correct semantics 944 * for TCP and UDP is to consider one TCP and UDP instance ··· 1058 icmp_fail: 1059 unregister_pernet_subsys(&inet6_net_ops); 1060 register_pernet_fail: 1061 + #ifdef CONFIG_SYSCTL 1062 + ipv6_static_sysctl_unregister(); 1063 + static_sysctl_fail: 1064 + #endif 1065 cleanup_ipv6_mibs(); 1066 out_unregister_sock: 1067 sock_unregister(PF_INET6); ··· 1113 rawv6_exit(); 1114 1115 unregister_pernet_subsys(&inet6_net_ops); 1116 + #ifdef CONFIG_SYSCTL 1117 + ipv6_static_sysctl_unregister(); 1118 + #endif 1119 cleanup_ipv6_mibs(); 1120 proto_unregister(&rawv6_prot); 1121 proto_unregister(&udplitev6_prot);
+16
net/ipv6/sysctl_net_ipv6.c
··· 150 unregister_net_sysctl_table(ip6_header); 151 unregister_pernet_subsys(&ipv6_sysctl_net_ops); 152 }
··· 150 unregister_net_sysctl_table(ip6_header); 151 unregister_pernet_subsys(&ipv6_sysctl_net_ops); 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 74 static int sysctl_net_init(struct net *net) 75 { 76 - setup_sysctl_set(&net->sysctls, NULL, is_seen); 77 return 0; 78 } 79
··· 73 74 static int sysctl_net_init(struct net *net) 75 { 76 + setup_sysctl_set(&net->sysctls, 77 + &net_sysctl_ro_root.default_set, 78 + is_seen); 79 return 0; 80 } 81