]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Aug 2020 09:20:25 +0000 (11:20 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Aug 2020 09:20:25 +0000 (11:20 +0200)
added patches:
ipv6-check-skb-protocol-before-lookup-for-nexthop.patch

queue-4.4/ipv6-check-skb-protocol-before-lookup-for-nexthop.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/ipv6-check-skb-protocol-before-lookup-for-nexthop.patch b/queue-4.4/ipv6-check-skb-protocol-before-lookup-for-nexthop.patch
new file mode 100644 (file)
index 0000000..8961e97
--- /dev/null
@@ -0,0 +1,100 @@
+From 199ab00f3cdb6f154ea93fa76fd80192861a821d Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Tue, 25 Apr 2017 14:37:15 -0700
+Subject: ipv6: check skb->protocol before lookup for nexthop
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+commit 199ab00f3cdb6f154ea93fa76fd80192861a821d upstream.
+
+Andrey reported a out-of-bound access in ip6_tnl_xmit(), this
+is because we use an ipv4 dst in ip6_tnl_xmit() and cast an IPv4
+neigh key as an IPv6 address:
+
+        neigh = dst_neigh_lookup(skb_dst(skb),
+                                 &ipv6_hdr(skb)->daddr);
+        if (!neigh)
+                goto tx_err_link_failure;
+
+        addr6 = (struct in6_addr *)&neigh->primary_key; // <=== HERE
+        addr_type = ipv6_addr_type(addr6);
+
+        if (addr_type == IPV6_ADDR_ANY)
+                addr6 = &ipv6_hdr(skb)->daddr;
+
+        memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+
+Also the network header of the skb at this point should be still IPv4
+for 4in6 tunnels, we shold not just use it as IPv6 header.
+
+This patch fixes it by checking if skb->protocol is ETH_P_IPV6: if it
+is, we are safe to do the nexthop lookup using skb_dst() and
+ipv6_hdr(skb)->daddr; if not (aka IPv4), we have no clue about which
+dest address we can pick here, we have to rely on callers to fill it
+from tunnel config, so just fall to ip6_route_output() to make the
+decision.
+
+Fixes: ea3dc9601bda ("ip6_tunnel: Add support for wildcard tunnel endpoints.")
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Alessio Balsini <balsini@android.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv6/ip6_tunnel.c |   42 ++++++++++++++++++++++--------------------
+ 1 file changed, 22 insertions(+), 20 deletions(-)
+
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -972,26 +972,28 @@ static int ip6_tnl_xmit2(struct sk_buff
+       /* NBMA tunnel */
+       if (ipv6_addr_any(&t->parms.raddr)) {
+-              struct in6_addr *addr6;
+-              struct neighbour *neigh;
+-              int addr_type;
+-
+-              if (!skb_dst(skb))
+-                      goto tx_err_link_failure;
+-
+-              neigh = dst_neigh_lookup(skb_dst(skb),
+-                                       &ipv6_hdr(skb)->daddr);
+-              if (!neigh)
+-                      goto tx_err_link_failure;
+-
+-              addr6 = (struct in6_addr *)&neigh->primary_key;
+-              addr_type = ipv6_addr_type(addr6);
+-
+-              if (addr_type == IPV6_ADDR_ANY)
+-                      addr6 = &ipv6_hdr(skb)->daddr;
+-
+-              memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+-              neigh_release(neigh);
++              if (skb->protocol == htons(ETH_P_IPV6)) {
++                      struct in6_addr *addr6;
++                      struct neighbour *neigh;
++                      int addr_type;
++
++                      if (!skb_dst(skb))
++                              goto tx_err_link_failure;
++
++                      neigh = dst_neigh_lookup(skb_dst(skb),
++                                               &ipv6_hdr(skb)->daddr);
++                      if (!neigh)
++                              goto tx_err_link_failure;
++
++                      addr6 = (struct in6_addr *)&neigh->primary_key;
++                      addr_type = ipv6_addr_type(addr6);
++
++                      if (addr_type == IPV6_ADDR_ANY)
++                              addr6 = &ipv6_hdr(skb)->daddr;
++
++                      memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
++                      neigh_release(neigh);
++              }
+       } else if (!fl6->flowi6_mark)
+               dst = dst_cache_get(&t->dst_cache);
index c38d90223d50625094b9dd544ccf1e4c84cbc9c2..9158618a78195172222d4618d5dd61ffcd427c6d 100644 (file)
@@ -146,3 +146,4 @@ mfd-dln2-run-event-handler-loop-under-spinlock.patch
 alsa-echoaudio-fix-potential-oops-in-snd_echo_resume.patch
 sh-landisk-add-missing-initialization-of-sh_io_port_.patch
 drm-radeon-fix-fb_div-check-in-ni_init_smc_spll_table.patch
+ipv6-check-skb-protocol-before-lookup-for-nexthop.patch