Skip to content

Commit 5117f03

Browse files
congwanggregkh
authored andcommitted
ipv6: initialize route null entry in addrconf_init()
[ Upstream commit 2f460933f58eee3393aba64f0f6d14acb08d1724 ] 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>
1 parent 545f144 commit 5117f03

3 files changed

Lines changed: 18 additions & 11 deletions

File tree

include/net/ip6_route.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static inline struct dst_entry *ip6_route_output(struct net *net,
7777
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
7878
int flags);
7979

80+
void ip6_route_init_special_entries(void);
8081
int ip6_route_init(void);
8182
void ip6_route_cleanup(void);
8283

net/ipv6/addrconf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5940,6 +5940,8 @@ int __init addrconf_init(void)
59405940
goto errlo;
59415941
}
59425942

5943+
ip6_route_init_special_entries();
5944+
59435945
for (i = 0; i < IN6_ADDR_HSIZE; i++)
59445946
INIT_HLIST_HEAD(&inet6_addr_lst[i]);
59455947

net/ipv6/route.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3681,6 +3681,21 @@ static struct notifier_block ip6_route_dev_notifier = {
36813681
.priority = 0,
36823682
};
36833683

3684+
void __init ip6_route_init_special_entries(void)
3685+
{
3686+
/* Registering of the loopback is done before this portion of code,
3687+
* the loopback reference in rt6_info will not be taken, do it
3688+
* manually for init_net */
3689+
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
3690+
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3691+
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
3692+
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
3693+
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3694+
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
3695+
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3696+
#endif
3697+
}
3698+
36843699
int __init ip6_route_init(void)
36853700
{
36863701
int ret;
@@ -3707,17 +3722,6 @@ int __init ip6_route_init(void)
37073722

37083723
ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
37093724

3710-
/* Registering of the loopback is done before this portion of code,
3711-
* the loopback reference in rt6_info will not be taken, do it
3712-
* manually for init_net */
3713-
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
3714-
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3715-
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
3716-
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
3717-
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3718-
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
3719-
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3720-
#endif
37213725
ret = fib6_init();
37223726
if (ret)
37233727
goto out_register_subsys;

0 commit comments

Comments
 (0)