diff options
author | Thomas Graf <tgraf@suug.ch> | 2012-06-18 08:08:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-16 11:47:37 -0400 |
commit | 5eceb057268c275e8193a03ed159bf540038feac (patch) | |
tree | b6ffd2d8578febb613c69ef38a6267ba9189a357 /net/ipv6 | |
parent | 76886430203577bfa3b437630058aa0346cb3168 (diff) |
ipv6: Move ipv6 proc file registration to end of init order
[ Upstream commit d189634ecab947c10f6f832258b103d0bbfe73cc ]
/proc/net/ipv6_route reflects the contents of fib_table_hash. The proc
handler is installed in ip6_route_net_init() whereas fib_table_hash is
allocated in fib6_net_init() _after_ the proc handler has been installed.
This opens up a short time frame to access fib_table_hash with its pants
down.
Move the registration of the proc files to a later point in the init
order to avoid the race.
Tested :-)
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/route.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8e600f827fe..7c5b4cb8838 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2846,10 +2846,6 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2846 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; | 2846 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; |
2847 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; | 2847 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; |
2848 | 2848 | ||
2849 | #ifdef CONFIG_PROC_FS | ||
2850 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2851 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2852 | #endif | ||
2853 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | 2849 | net->ipv6.ip6_rt_gc_expire = 30*HZ; |
2854 | 2850 | ||
2855 | ret = 0; | 2851 | ret = 0; |
@@ -2870,10 +2866,6 @@ out_ip6_dst_ops: | |||
2870 | 2866 | ||
2871 | static void __net_exit ip6_route_net_exit(struct net *net) | 2867 | static void __net_exit ip6_route_net_exit(struct net *net) |
2872 | { | 2868 | { |
2873 | #ifdef CONFIG_PROC_FS | ||
2874 | proc_net_remove(net, "ipv6_route"); | ||
2875 | proc_net_remove(net, "rt6_stats"); | ||
2876 | #endif | ||
2877 | kfree(net->ipv6.ip6_null_entry); | 2869 | kfree(net->ipv6.ip6_null_entry); |
2878 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2870 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2879 | kfree(net->ipv6.ip6_prohibit_entry); | 2871 | kfree(net->ipv6.ip6_prohibit_entry); |
@@ -2882,11 +2874,33 @@ static void __net_exit ip6_route_net_exit(struct net *net) | |||
2882 | dst_entries_destroy(&net->ipv6.ip6_dst_ops); | 2874 | dst_entries_destroy(&net->ipv6.ip6_dst_ops); |
2883 | } | 2875 | } |
2884 | 2876 | ||
2877 | static int __net_init ip6_route_net_init_late(struct net *net) | ||
2878 | { | ||
2879 | #ifdef CONFIG_PROC_FS | ||
2880 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2881 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2882 | #endif | ||
2883 | return 0; | ||
2884 | } | ||
2885 | |||
2886 | static void __net_exit ip6_route_net_exit_late(struct net *net) | ||
2887 | { | ||
2888 | #ifdef CONFIG_PROC_FS | ||
2889 | proc_net_remove(net, "ipv6_route"); | ||
2890 | proc_net_remove(net, "rt6_stats"); | ||
2891 | #endif | ||
2892 | } | ||
2893 | |||
2885 | static struct pernet_operations ip6_route_net_ops = { | 2894 | static struct pernet_operations ip6_route_net_ops = { |
2886 | .init = ip6_route_net_init, | 2895 | .init = ip6_route_net_init, |
2887 | .exit = ip6_route_net_exit, | 2896 | .exit = ip6_route_net_exit, |
2888 | }; | 2897 | }; |
2889 | 2898 | ||
2899 | static struct pernet_operations ip6_route_net_late_ops = { | ||
2900 | .init = ip6_route_net_init_late, | ||
2901 | .exit = ip6_route_net_exit_late, | ||
2902 | }; | ||
2903 | |||
2890 | static struct notifier_block ip6_route_dev_notifier = { | 2904 | static struct notifier_block ip6_route_dev_notifier = { |
2891 | .notifier_call = ip6_route_dev_notify, | 2905 | .notifier_call = ip6_route_dev_notify, |
2892 | .priority = 0, | 2906 | .priority = 0, |
@@ -2936,19 +2950,25 @@ int __init ip6_route_init(void) | |||
2936 | if (ret) | 2950 | if (ret) |
2937 | goto xfrm6_init; | 2951 | goto xfrm6_init; |
2938 | 2952 | ||
2953 | ret = register_pernet_subsys(&ip6_route_net_late_ops); | ||
2954 | if (ret) | ||
2955 | goto fib6_rules_init; | ||
2956 | |||
2939 | ret = -ENOBUFS; | 2957 | ret = -ENOBUFS; |
2940 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) || | 2958 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) || |
2941 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) || | 2959 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) || |
2942 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) | 2960 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2943 | goto fib6_rules_init; | 2961 | goto out_register_late_subsys; |
2944 | 2962 | ||
2945 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); | 2963 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
2946 | if (ret) | 2964 | if (ret) |
2947 | goto fib6_rules_init; | 2965 | goto out_register_late_subsys; |
2948 | 2966 | ||
2949 | out: | 2967 | out: |
2950 | return ret; | 2968 | return ret; |
2951 | 2969 | ||
2970 | out_register_late_subsys: | ||
2971 | unregister_pernet_subsys(&ip6_route_net_late_ops); | ||
2952 | fib6_rules_init: | 2972 | fib6_rules_init: |
2953 | fib6_rules_cleanup(); | 2973 | fib6_rules_cleanup(); |
2954 | xfrm6_init: | 2974 | xfrm6_init: |
@@ -2967,6 +2987,7 @@ out_kmem_cache: | |||
2967 | void ip6_route_cleanup(void) | 2987 | void ip6_route_cleanup(void) |
2968 | { | 2988 | { |
2969 | unregister_netdevice_notifier(&ip6_route_dev_notifier); | 2989 | unregister_netdevice_notifier(&ip6_route_dev_notifier); |
2990 | unregister_pernet_subsys(&ip6_route_net_late_ops); | ||
2970 | fib6_rules_cleanup(); | 2991 | fib6_rules_cleanup(); |
2971 | xfrm6_fini(); | 2992 | xfrm6_fini(); |
2972 | fib6_gc_cleanup(); | 2993 | fib6_gc_cleanup(); |