Commit 4aaeda7f authored by WANG Cong's avatar WANG Cong Committed by Sasha Levin

ipv6: initialize route null entry in addrconf_init()

[ Upstream commit 2f460933 ]

Andrey reported a crash on init_net.ipv6.ip6_null_entry->rt6i_idev
since it is always NULL.

This is clearly wrong, we have code to initialize it to loopback_dev,
unfortunately the order is still not correct.

loopback_dev is registered very early during boot, we lose a chance
to re-initialize it in notifier. addrconf_init() is called after
ip6_route_init(), which means we have no chance to correct it.

Fix it by moving this initialization explicitly after
ipv6_add_dev(init_net.loopback_dev) in addrconf_init().
Reported-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Tested-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
parent 1d9afaa5
...@@ -77,6 +77,7 @@ static inline struct dst_entry *ip6_route_output(struct net *net, ...@@ -77,6 +77,7 @@ static inline struct dst_entry *ip6_route_output(struct net *net,
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
int flags); int flags);
void ip6_route_init_special_entries(void);
int ip6_route_init(void); int ip6_route_init(void);
void ip6_route_cleanup(void); void ip6_route_cleanup(void);
......
...@@ -5801,6 +5801,8 @@ int __init addrconf_init(void) ...@@ -5801,6 +5801,8 @@ int __init addrconf_init(void)
goto errlo; goto errlo;
} }
ip6_route_init_special_entries();
for (i = 0; i < IN6_ADDR_HSIZE; i++) for (i = 0; i < IN6_ADDR_HSIZE; i++)
INIT_HLIST_HEAD(&inet6_addr_lst[i]); INIT_HLIST_HEAD(&inet6_addr_lst[i]);
......
...@@ -3362,6 +3362,21 @@ static struct notifier_block ip6_route_dev_notifier = { ...@@ -3362,6 +3362,21 @@ static struct notifier_block ip6_route_dev_notifier = {
.priority = 0, .priority = 0,
}; };
void __init ip6_route_init_special_entries(void)
{
/* Registering of the loopback is done before this portion of code,
* the loopback reference in rt6_info will not be taken, do it
* manually for init_net */
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#endif
}
int __init ip6_route_init(void) int __init ip6_route_init(void)
{ {
int ret; int ret;
...@@ -3387,17 +3402,6 @@ int __init ip6_route_init(void) ...@@ -3387,17 +3402,6 @@ int __init ip6_route_init(void)
ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
/* Registering of the loopback is done before this portion of code,
* the loopback reference in rt6_info will not be taken, do it
* manually for init_net */
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
#endif
ret = fib6_init(); ret = fib6_init();
if (ret) if (ret)
goto out_register_subsys; goto out_register_subsys;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment