From f1900fb5eca2cf9b96837e4931165003918d7d29 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 19 Oct 2015 08:26:05 -0700 Subject: net: Really fix vti6 with oif in dst lookups 6e28b000825d ("net: Fix vti use case with oif in dst lookups for IPv6") is missing the checks on FLOWI_FLAG_SKIP_NH_OIF. Add them. Fixes: 42a7b32b73d6 ("xfrm: Add oif to dst lookups") Cc: Steffen Klassert Signed-off-by: David Ahern Acked-by: Steffen Klassert Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 61d403ee1031..d03d6da772f3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -877,7 +877,8 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, #ifdef CONFIG_IPV6_SUBTREES ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) || #endif - (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) { + (!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) && + (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) { dst_release(dst); dst = NULL; } -- cgit v1.2.3 From b72a2b01b686f242028038f630555513c9e4de38 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 16 Oct 2015 11:32:43 +0200 Subject: ipv6: protect mtu calculation of wrap-around and infinite loop by rounding issues Raw sockets with hdrincl enabled can insert ipv6 extension headers right into the data stream. In case we need to fragment those packets, we reparse the options header to find the place where we can insert the fragment header. If the extension headers exceed the link's MTU we actually cannot make progress in such a case. Instead of ending up in broken arithmetic or rounding towards 0 and entering an endless loop in ip6_fragment, just prevent those cases by aborting early and signal -EMSGSIZE to user space. Reported-by: Dmitry Vyukov Cc: Dmitry Vyukov Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net/ipv6/ip6_output.c') diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d03d6da772f3..8dddb45c433e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -584,7 +585,10 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb, if (np->frag_size) mtu = np->frag_size; } - mtu -= hlen + sizeof(struct frag_hdr); + + if (overflow_usub(mtu, hlen + sizeof(struct frag_hdr), &mtu) || + mtu <= 7) + goto fail_toobig; frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr, &ipv6_hdr(skb)->saddr); -- cgit v1.2.3