mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 01:49:46 +00:00
ipv6: initialize route null entry in addrconf_init()
[ Upstream commit 2f460933f5 ]
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: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5d8e07740c
commit
ecbd3ed2dd
@@ -84,6 +84,7 @@ struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
|
||||
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
||||
int ifindex, struct flowi6 *fl6, int flags);
|
||||
|
||||
void ip6_route_init_special_entries(void);
|
||||
int ip6_route_init(void);
|
||||
void ip6_route_cleanup(void);
|
||||
|
||||
|
||||
@@ -6264,6 +6264,8 @@ int __init addrconf_init(void)
|
||||
goto errlo;
|
||||
}
|
||||
|
||||
ip6_route_init_special_entries();
|
||||
|
||||
for (i = 0; i < IN6_ADDR_HSIZE; i++)
|
||||
INIT_HLIST_HEAD(&inet6_addr_lst[i]);
|
||||
|
||||
|
||||
@@ -3798,6 +3798,21 @@ static struct notifier_block ip6_route_dev_notifier = {
|
||||
.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 ret;
|
||||
@@ -3824,17 +3839,6 @@ int __init ip6_route_init(void)
|
||||
|
||||
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();
|
||||
if (ret)
|
||||
goto out_register_subsys;
|
||||
|
||||
Reference in New Issue
Block a user