aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2013-10-24 01:48:24 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-20 15:27:46 -0500
commit8ffff756458db53555ca36a97766f1731f6719cc (patch)
tree9732bc331d5feb7937ba1e6531d9a04cac243b0d
parentb9099fea22395af057dec42c678f47cf746cc998 (diff)
ipv6: ip6_dst_check needs to check for expired dst_entries
[ Upstream commit e3bc10bd95d7fcc3f2ac690c6ff22833ea6781d6 ] On receiving a packet too big icmp error we check if our current cached dst_entry in the socket is still valid. This validation check did not care about the expiration of the (cached) route. The error path I traced down: The socket receives a packet too big mtu notification. It still has a valid dst_entry and thus issues the ip6_rt_pmtu_update on this dst_entry, setting RTF_EXPIRE and updates the dst.expiration value (which could fail because of not up-to-date expiration values, see previous patch). In some seldom cases we race with a) the ip6_fib gc or b) another routing lookup which would result in a recreation of the cached rt6_info from its parent non-cached rt6_info. While copying the rt6_info we reinitialize the metrics store by copying it over from the parent thus invalidating the just installed pmtu update (both dsts use the same key to the inetpeer storage). The dst_entry with the just invalidated metrics data would just get its RTF_EXPIRES flag cleared and would continue to stay valid for the socket. We should have not issued the pmtu update on the already expired dst_entry in the first placed. By checking the expiration on the dst entry and doing a relookup in case it is out of date we close the race because we would install a new rt6_info into the fib before we issue the pmtu update, thus closing this race. Not reliably updating the dst.expire value was fixed by the patch "ipv6: reset dst.expires value when clearing expire flag". Reported-by: Steinar H. Gunderson <sgunderson@bigfoot.com> Reported-by: Valentijn Sessink <valentyn@blub.net> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Tested-by: Valentijn Sessink <valentyn@blub.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/ipv6/route.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3c1f493ccc63..548a1f7c1a29 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1084,10 +1084,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1084 if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) 1084 if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
1085 return NULL; 1085 return NULL;
1086 1086
1087 if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) 1087 if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
1088 return dst; 1088 return NULL;
1089 1089
1090 return NULL; 1090 if (rt6_check_expired(rt))
1091 return NULL;
1092
1093 return dst;
1091} 1094}
1092 1095
1093static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) 1096static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)