Patch "ipv6: Avoid creating RTF_CACHE from a rt that is not managed by fib6 tree" has been added to the 4.2-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
ipv6: Avoid creating RTF_CACHE from a rt that is not managed by fib6 tree
to the 4.2-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ipv6-avoid-creating-rtf_cache-from-a-rt-that-is-not-managed-by-fib6-tree.patch
and it can be found in the queue-4.2 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Fri Dec 11 11:38:35 EST 2015
From: Martin KaFai Lau <[email protected]>
Date: Wed, 11 Nov 2015 11:51:06 -0800
Subject: ipv6: Avoid creating RTF_CACHE from a rt that is not managed by fib6 tree
From: Martin KaFai Lau <[email protected]>
[ Upstream commit 0d3f6d297bfb7af24d0508460fdb3d1ec4903fa3 ]
The original bug report:
https://bugzilla.redhat.com/show_bug.cgi?id=1272571
The setup has a IPv4 GRE tunnel running in a IPSec. The bug happens when ndisc starts sending router solicitation at the gre interface. The simplified oops stack is like:
__lock_acquire+0x1b2/0x1c30 lock_acquire+0xb9/0x140 _raw_write_lock_bh+0x3f/0x50 __ip6_ins_rt+0x2e/0x60 ip6_ins_rt+0x49/0x50 ~~~~~~~~ __ip6_rt_update_pmtu.part.54+0x145/0x250 ip6_rt_update_pmtu+0x2e/0x40 ~~~~~~~~ ip_tunnel_xmit+0x1f1/0xf40 __gre_xmit+0x7a/0x90 ipgre_xmit+0x15a/0x220 dev_hard_start_xmit+0x2bd/0x480 __dev_queue_xmit+0x696/0x730 dev_queue_xmit+0x10/0x20 neigh_direct_output+0x11/0x20 ip6_finish_output2+0x21f/0x770 ip6_finish_output+0xa7/0x1d0 ip6_output+0x56/0x190 ~~~~~~~~ ndisc_send_skb+0x1d9/0x400 ndisc_send_rs+0x88/0xc0
~~~~~~~~
The rt passed to ip6_rt_update_pmtu() is created by icmp6_dst_alloc() and it is not managed by the fib6 tree, so its rt6i_table == NULL. When __ip6_rt_update_pmtu() creates a RTF_CACHE clone, the newly created clone also has rt6i_table == NULL and it causes the ip6_ins_rt() oops.
During pmtu update, we only want to create a RTF_CACHE clone from a rt which is currently managed (or owned) by the fib6 tree. It means either rt->rt6i_node != NULL or rt is a RTF_PCPU clone.
It is worth to note that rt6i_table may not be NULL even it is not (yet) managed by the fib6 tree (e.g. addrconf_dst_alloc()). Hence, rt6i_node is a better check instead of rt6i_table.
--- net/ipv6/route.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
net/ipv6/route.c +7 -1
@@ -1326,6 +1326,12 @@ static void rt6_do_update_pmtu(struct rtrt6_update_expires (rt, net->ipv6.sysctl.ip6_rt_mtu_expires); } +static bool rt6_cache_allowed_for_pmtu (const struct rt6_info *rt) +{ +return !(rt->rt6i_flags &RTF_CACHE ) && + (rt->rt6i_flags &RTF_PCPU || rt->rt6i_node); +} +static void __ip6_rt_update_pmtu (struct dst_entry *dst,const struct sock *sk,const struct ipv6hdr *iph,u32 mtu) {
@@ -1339,7 +1345,7 @@ static void __ip6_rt_update_pmtu(structif (mtu >=dst_mtu (dst))return ; -if (rt6->rt6i_flags &RTF_CACHE ) { +if (!rt6_cache_allowed_for_pmtu (rt6)) {rt6_do_update_pmtu (rt6, mtu); }else {const struct in6_addr *daddr, *saddr;
Patches currently in stable-queue which might be from [email protected] are
queue-4.2/ipv6-check-rt-dst.from-for-the-dst_nocache-route.patch queue-4.2/ipv6-avoid-creating-rtf_cache-from-a-rt-that-is-not-managed-by-fib6-tree.patch queue-4.2/ipv6-check-expire-on-dst_nocache-route.patch