diff options
author | Thomas Graf <tgraf@suug.ch> | 2012-06-18 08:08:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-18 21:38:50 -0400 |
commit | d189634ecab947c10f6f832258b103d0bbfe73cc (patch) | |
tree | 22d89d2747004ecdfaa7093734fb3bd96366f59a /net | |
parent | 8cfe523a1294da65ef95b6ed7b0f7db5629f8d88 (diff) |
ipv6: Move ipv6 proc file registration to end of init order
/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>
Diffstat (limited to 'net')
-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 999a982ad3fd..becb048d18d4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2957,10 +2957,6 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2957 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; | 2957 | net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; |
2958 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; | 2958 | net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; |
2959 | 2959 | ||
2960 | #ifdef CONFIG_PROC_FS | ||
2961 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2962 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2963 | #endif | ||
2964 | net->ipv6.ip6_rt_gc_expire = 30*HZ; | 2960 | net->ipv6.ip6_rt_gc_expire = 30*HZ; |
2965 | 2961 | ||
2966 | ret = 0; | 2962 | ret = 0; |
@@ -2981,10 +2977,6 @@ out_ip6_dst_ops: | |||
2981 | 2977 | ||
2982 | static void __net_exit ip6_route_net_exit(struct net *net) | 2978 | static void __net_exit ip6_route_net_exit(struct net *net) |
2983 | { | 2979 | { |
2984 | #ifdef CONFIG_PROC_FS | ||
2985 | proc_net_remove(net, "ipv6_route"); | ||
2986 | proc_net_remove(net, "rt6_stats"); | ||
2987 | #endif | ||
2988 | kfree(net->ipv6.ip6_null_entry); | 2980 | kfree(net->ipv6.ip6_null_entry); |
2989 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2981 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2990 | kfree(net->ipv6.ip6_prohibit_entry); | 2982 | kfree(net->ipv6.ip6_prohibit_entry); |
@@ -2993,11 +2985,33 @@ static void __net_exit ip6_route_net_exit(struct net *net) | |||
2993 | dst_entries_destroy(&net->ipv6.ip6_dst_ops); | 2985 | dst_entries_destroy(&net->ipv6.ip6_dst_ops); |
2994 | } | 2986 | } |
2995 | 2987 | ||
2988 | static int __net_init ip6_route_net_init_late(struct net *net) | ||
2989 | { | ||
2990 | #ifdef CONFIG_PROC_FS | ||
2991 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); | ||
2992 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); | ||
2993 | #endif | ||
2994 | return 0; | ||
2995 | } | ||
2996 | |||
2997 | static void __net_exit ip6_route_net_exit_late(struct net *net) | ||
2998 | { | ||
2999 | #ifdef CONFIG_PROC_FS | ||
3000 | proc_net_remove(net, "ipv6_route"); | ||
3001 | proc_net_remove(net, "rt6_stats"); | ||
3002 | #endif | ||
3003 | } | ||
3004 | |||
2996 | static struct pernet_operations ip6_route_net_ops = { | 3005 | static struct pernet_operations ip6_route_net_ops = { |
2997 | .init = ip6_route_net_init, | 3006 | .init = ip6_route_net_init, |
2998 | .exit = ip6_route_net_exit, | 3007 | .exit = ip6_route_net_exit, |
2999 | }; | 3008 | }; |
3000 | 3009 | ||
3010 | static struct pernet_operations ip6_route_net_late_ops = { | ||
3011 | .init = ip6_route_net_init_late, | ||
3012 | .exit = ip6_route_net_exit_late, | ||
3013 | }; | ||
3014 | |||
3001 | static struct notifier_block ip6_route_dev_notifier = { | 3015 | static struct notifier_block ip6_route_dev_notifier = { |
3002 | .notifier_call = ip6_route_dev_notify, | 3016 | .notifier_call = ip6_route_dev_notify, |
3003 | .priority = 0, | 3017 | .priority = 0, |
@@ -3047,19 +3061,25 @@ int __init ip6_route_init(void) | |||
3047 | if (ret) | 3061 | if (ret) |
3048 | goto xfrm6_init; | 3062 | goto xfrm6_init; |
3049 | 3063 | ||
3064 | ret = register_pernet_subsys(&ip6_route_net_late_ops); | ||
3065 | if (ret) | ||
3066 | goto fib6_rules_init; | ||
3067 | |||
3050 | ret = -ENOBUFS; | 3068 | ret = -ENOBUFS; |
3051 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || | 3069 | if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || |
3052 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || | 3070 | __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || |
3053 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) | 3071 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) |
3054 | goto fib6_rules_init; | 3072 | goto out_register_late_subsys; |
3055 | 3073 | ||
3056 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); | 3074 | ret = register_netdevice_notifier(&ip6_route_dev_notifier); |
3057 | if (ret) | 3075 | if (ret) |
3058 | goto fib6_rules_init; | 3076 | goto out_register_late_subsys; |
3059 | 3077 | ||
3060 | out: | 3078 | out: |
3061 | return ret; | 3079 | return ret; |
3062 | 3080 | ||
3081 | out_register_late_subsys: | ||
3082 | unregister_pernet_subsys(&ip6_route_net_late_ops); | ||
3063 | fib6_rules_init: | 3083 | fib6_rules_init: |
3064 | fib6_rules_cleanup(); | 3084 | fib6_rules_cleanup(); |
3065 | xfrm6_init: | 3085 | xfrm6_init: |
@@ -3078,6 +3098,7 @@ out_kmem_cache: | |||
3078 | void ip6_route_cleanup(void) | 3098 | void ip6_route_cleanup(void) |
3079 | { | 3099 | { |
3080 | unregister_netdevice_notifier(&ip6_route_dev_notifier); | 3100 | unregister_netdevice_notifier(&ip6_route_dev_notifier); |
3101 | unregister_pernet_subsys(&ip6_route_net_late_ops); | ||
3081 | fib6_rules_cleanup(); | 3102 | fib6_rules_cleanup(); |
3082 | xfrm6_fini(); | 3103 | xfrm6_fini(); |
3083 | fib6_gc_cleanup(); | 3104 | fib6_gc_cleanup(); |