diff options
author | Thomas Graf <tgraf@suug.ch> | 2012-06-14 19:00:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-15 18:30:15 -0400 |
commit | 2a0c451ade8e1783c5d453948289e4a978d417c9 (patch) | |
tree | 136dbbaf024f45200848ec371368668872545a2e /net/ipv6/route.c | |
parent | 0f6efff92524c65fc3ef41c8b936c526580f1db0 (diff) |
ipv6: Prevent access to uninitialized fib_table_hash via /proc/net/ipv6_route
/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.
fib6_init() as a whole can't be moved to an earlier position as it also
registers the rtnetlink message handlers which should be registered at
the end. Therefore split it into fib6_init() which is run early and
fib6_init_late() to register the rtnetlink message handlers.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 999a982ad3fd..dc60bf585966 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -3018,10 +3018,14 @@ int __init ip6_route_init(void) | |||
3018 | if (ret) | 3018 | if (ret) |
3019 | goto out_kmem_cache; | 3019 | goto out_kmem_cache; |
3020 | 3020 | ||
3021 | ret = register_pernet_subsys(&ip6_route_net_ops); | 3021 | ret = fib6_init(); |
3022 | if (ret) | 3022 | if (ret) |
3023 | goto out_dst_entries; | 3023 | goto out_dst_entries; |
3024 | 3024 | ||
3025 | ret = register_pernet_subsys(&ip6_route_net_ops); | ||
3026 | if (ret) | ||
3027 | goto out_fib6_init; | ||
3028 | |||
3025 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | 3029 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; |
3026 | 3030 | ||
3027 | /* Registering of the loopback is done before this portion of code, | 3031 | /* Registering of the loopback is done before this portion of code, |
@@ -3035,13 +3039,13 @@ int __init ip6_route_init(void) | |||
3035 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; | 3039 | init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; |
3036 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | 3040 | init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); |
3037 | #endif | 3041 | #endif |
3038 | ret = fib6_init(); | 3042 | ret = fib6_init_late(); |
3039 | if (ret) | 3043 | if (ret) |
3040 | goto out_register_subsys; | 3044 | goto out_register_subsys; |
3041 | 3045 | ||
3042 | ret = xfrm6_init(); | 3046 | ret = xfrm6_init(); |
3043 | if (ret) | 3047 | if (ret) |
3044 | goto out_fib6_init; | 3048 | goto out_fib6_init_late; |
3045 | 3049 | ||
3046 | ret = fib6_rules_init(); | 3050 | ret = fib6_rules_init(); |
3047 | if (ret) | 3051 | if (ret) |
@@ -3064,10 +3068,12 @@ fib6_rules_init: | |||
3064 | fib6_rules_cleanup(); | 3068 | fib6_rules_cleanup(); |
3065 | xfrm6_init: | 3069 | xfrm6_init: |
3066 | xfrm6_fini(); | 3070 | xfrm6_fini(); |
3067 | out_fib6_init: | 3071 | out_fib6_init_late: |
3068 | fib6_gc_cleanup(); | 3072 | fib6_cleanup_late(); |
3069 | out_register_subsys: | 3073 | out_register_subsys: |
3070 | unregister_pernet_subsys(&ip6_route_net_ops); | 3074 | unregister_pernet_subsys(&ip6_route_net_ops); |
3075 | out_fib6_init: | ||
3076 | fib6_gc_cleanup(); | ||
3071 | out_dst_entries: | 3077 | out_dst_entries: |
3072 | dst_entries_destroy(&ip6_dst_blackhole_ops); | 3078 | dst_entries_destroy(&ip6_dst_blackhole_ops); |
3073 | out_kmem_cache: | 3079 | out_kmem_cache: |