From af13b16401b4c2a033bd0f74162530b2d4587f5a Mon Sep 17 00:00:00 2001 From: Adrian Stratulat Date: Wed, 30 Oct 2019 12:12:27 +0100 Subject: tunnels: CVE-2016-8666 tunnels: Don't apply GRO to multiple layers of encapsulation References: https://nvd.nist.gov/vuln/detail/CVE-2016-8666 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fac8e0f579695a3ecbc4d3cac369139d7f819971 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=066b300e5be43cb61697539e2a3a9aac5afb422f Change-Id: I55c79f32e2ce1c06c59f40ab087015e461388795 Signed-off-by: Adrian Stratulat --- patches/cve/CVE-2016-8666.patch | 166 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 patches/cve/CVE-2016-8666.patch diff --git a/patches/cve/CVE-2016-8666.patch b/patches/cve/CVE-2016-8666.patch new file mode 100644 index 0000000..cac0a09 --- /dev/null +++ b/patches/cve/CVE-2016-8666.patch @@ -0,0 +1,166 @@ +From 066b300e5be43cb61697539e2a3a9aac5afb422f Mon Sep 17 00:00:00 2001 +From: Jesse Gross +Date: Sat, 19 Mar 2016 09:32:01 -0700 +Subject: tunnels: Don't apply GRO to multiple layers of encapsulation. + +[ Upstream commit fac8e0f579695a3ecbc4d3cac369139d7f819971 ] + +When drivers express support for TSO of encapsulated packets, they +only mean that they can do it for one layer of encapsulation. +Supporting additional levels would mean updating, at a minimum, +more IP length fields and they are unaware of this. + +No encapsulation device expresses support for handling offloaded +encapsulated packets, so we won't generate these types of frames +in the transmit path. However, GRO doesn't have a check for +multiple levels of encapsulation and will attempt to build them. + +UDP tunnel GRO actually does prevent this situation but it only +handles multiple UDP tunnels stacked on top of each other. This +generalizes that solution to prevent any kind of tunnel stacking +that would cause problems. + +Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=066b300e5be43cb61697539e2a3a9aac5afb422f] +CVE: CVE-2016-8666 + +Fixes: bf5a755f ("net-gre-gro: Add GRE support to the GRO stack") +Signed-off-by: Jesse Gross +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Adrian Stratulat +--- + include/linux/netdevice.h | 4 ++-- + net/core/dev.c | 2 +- + net/ipv4/af_inet.c | 15 ++++++++++++++- + net/ipv4/gre_offload.c | 5 +++++ + net/ipv4/udp_offload.c | 6 +++--- + net/ipv6/ip6_offload.c | 13 +++++++++++++ + 6 files changed, 38 insertions(+), 7 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index ddd47c3a757d..c11f9d1963c3 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1949,8 +1949,8 @@ struct napi_gro_cb { + /* This is non-zero if the packet may be of the same flow. */ + u8 same_flow:1; + +- /* Used in udp_gro_receive */ +- u8 udp_mark:1; ++ /* Used in tunnel GRO receive */ ++ u8 encap_mark:1; + + /* GRO checksum is valid */ + u8 csum_valid:1; +diff --git a/net/core/dev.c b/net/core/dev.c +index 56d820fc2707..0f9289ff0f2a 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4158,8 +4158,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff + NAPI_GRO_CB(skb)->same_flow = 0; + NAPI_GRO_CB(skb)->flush = 0; + NAPI_GRO_CB(skb)->free = 0; +- NAPI_GRO_CB(skb)->udp_mark = 0; + NAPI_GRO_CB(skb)->recursion_counter = 0; ++ NAPI_GRO_CB(skb)->encap_mark = 0; + NAPI_GRO_CB(skb)->gro_remcsum_start = 0; + + /* Setup for GRO checksum validation */ +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index f952caa5cfe1..84e46837610b 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1388,6 +1388,19 @@ out: + return pp; + } + ++static struct sk_buff **ipip_gro_receive(struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (NAPI_GRO_CB(skb)->encap_mark) { ++ NAPI_GRO_CB(skb)->flush = 1; ++ return NULL; ++ } ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ ++ return inet_gro_receive(head, skb); ++} ++ + int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + if (sk->sk_family == AF_INET) +@@ -1646,7 +1659,7 @@ static struct packet_offload ip_packet_offload __read_mostly = { + static const struct net_offload ipip_offload = { + .callbacks = { + .gso_segment = inet_gso_segment, +- .gro_receive = inet_gro_receive, ++ .gro_receive = ipip_gro_receive, + .gro_complete = inet_gro_complete, + }, + }; +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index 53300b88d569..79ae0d7becbf 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -128,6 +128,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, + struct packet_offload *ptype; + __be16 type; + ++ if (NAPI_GRO_CB(skb)->encap_mark) ++ goto out; ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ + off = skb_gro_offset(skb); + hlen = off + sizeof(*greh); + greh = skb_gro_header_fast(skb, off); +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index 2af7b7e1a0f6..dfcab88c3e74 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -299,14 +299,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, + unsigned int off = skb_gro_offset(skb); + int flush = 1; + +- if (NAPI_GRO_CB(skb)->udp_mark || ++ if (NAPI_GRO_CB(skb)->encap_mark || + (skb->ip_summed != CHECKSUM_PARTIAL && + NAPI_GRO_CB(skb)->csum_cnt == 0 && + !NAPI_GRO_CB(skb)->csum_valid)) + goto out; + +- /* mark that this skb passed once through the udp gro layer */ +- NAPI_GRO_CB(skb)->udp_mark = 1; ++ /* mark that this skb passed once through the tunnel gro layer */ ++ NAPI_GRO_CB(skb)->encap_mark = 1; + + rcu_read_lock(); + uo_priv = rcu_dereference(udp_offload_base); +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index db0b8428d248..9b01da54d475 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -260,6 +260,19 @@ out: + return pp; + } + ++static struct sk_buff **sit_gro_receive(struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (NAPI_GRO_CB(skb)->encap_mark) { ++ NAPI_GRO_CB(skb)->flush = 1; ++ return NULL; ++ } ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ ++ return ipv6_gro_receive(head, skb); ++} ++ + static int ipv6_gro_complete(struct sk_buff *skb, int nhoff) + { + const struct net_offload *ops; +-- +cgit 1.2-0.3.lf.el7 + -- cgit v1.2.3-54-g00ecf