diff options
-rw-r--r-- | patches/cve/CVE-2016-8666.patch | 166 |
1 files changed, 166 insertions, 0 deletions
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 @@ | |||
1 | From 066b300e5be43cb61697539e2a3a9aac5afb422f Mon Sep 17 00:00:00 2001 | ||
2 | From: Jesse Gross <jesse@kernel.org> | ||
3 | Date: Sat, 19 Mar 2016 09:32:01 -0700 | ||
4 | Subject: tunnels: Don't apply GRO to multiple layers of encapsulation. | ||
5 | |||
6 | [ Upstream commit fac8e0f579695a3ecbc4d3cac369139d7f819971 ] | ||
7 | |||
8 | When drivers express support for TSO of encapsulated packets, they | ||
9 | only mean that they can do it for one layer of encapsulation. | ||
10 | Supporting additional levels would mean updating, at a minimum, | ||
11 | more IP length fields and they are unaware of this. | ||
12 | |||
13 | No encapsulation device expresses support for handling offloaded | ||
14 | encapsulated packets, so we won't generate these types of frames | ||
15 | in the transmit path. However, GRO doesn't have a check for | ||
16 | multiple levels of encapsulation and will attempt to build them. | ||
17 | |||
18 | UDP tunnel GRO actually does prevent this situation but it only | ||
19 | handles multiple UDP tunnels stacked on top of each other. This | ||
20 | generalizes that solution to prevent any kind of tunnel stacking | ||
21 | that would cause problems. | ||
22 | |||
23 | Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=066b300e5be43cb61697539e2a3a9aac5afb422f] | ||
24 | CVE: CVE-2016-8666 | ||
25 | |||
26 | Fixes: bf5a755f ("net-gre-gro: Add GRE support to the GRO stack") | ||
27 | Signed-off-by: Jesse Gross <jesse@kernel.org> | ||
28 | Signed-off-by: David S. Miller <davem@davemloft.net> | ||
29 | Signed-off-by: Sasha Levin <alexander.levin@verizon.com> | ||
30 | Signed-off-by: Adrian Stratulat <adrian.stratulat@enea.com> | ||
31 | --- | ||
32 | include/linux/netdevice.h | 4 ++-- | ||
33 | net/core/dev.c | 2 +- | ||
34 | net/ipv4/af_inet.c | 15 ++++++++++++++- | ||
35 | net/ipv4/gre_offload.c | 5 +++++ | ||
36 | net/ipv4/udp_offload.c | 6 +++--- | ||
37 | net/ipv6/ip6_offload.c | 13 +++++++++++++ | ||
38 | 6 files changed, 38 insertions(+), 7 deletions(-) | ||
39 | |||
40 | diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h | ||
41 | index ddd47c3a757d..c11f9d1963c3 100644 | ||
42 | --- a/include/linux/netdevice.h | ||
43 | +++ b/include/linux/netdevice.h | ||
44 | @@ -1949,8 +1949,8 @@ struct napi_gro_cb { | ||
45 | /* This is non-zero if the packet may be of the same flow. */ | ||
46 | u8 same_flow:1; | ||
47 | |||
48 | - /* Used in udp_gro_receive */ | ||
49 | - u8 udp_mark:1; | ||
50 | + /* Used in tunnel GRO receive */ | ||
51 | + u8 encap_mark:1; | ||
52 | |||
53 | /* GRO checksum is valid */ | ||
54 | u8 csum_valid:1; | ||
55 | diff --git a/net/core/dev.c b/net/core/dev.c | ||
56 | index 56d820fc2707..0f9289ff0f2a 100644 | ||
57 | --- a/net/core/dev.c | ||
58 | +++ b/net/core/dev.c | ||
59 | @@ -4158,8 +4158,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | ||
60 | NAPI_GRO_CB(skb)->same_flow = 0; | ||
61 | NAPI_GRO_CB(skb)->flush = 0; | ||
62 | NAPI_GRO_CB(skb)->free = 0; | ||
63 | - NAPI_GRO_CB(skb)->udp_mark = 0; | ||
64 | NAPI_GRO_CB(skb)->recursion_counter = 0; | ||
65 | + NAPI_GRO_CB(skb)->encap_mark = 0; | ||
66 | NAPI_GRO_CB(skb)->gro_remcsum_start = 0; | ||
67 | |||
68 | /* Setup for GRO checksum validation */ | ||
69 | diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c | ||
70 | index f952caa5cfe1..84e46837610b 100644 | ||
71 | --- a/net/ipv4/af_inet.c | ||
72 | +++ b/net/ipv4/af_inet.c | ||
73 | @@ -1388,6 +1388,19 @@ out: | ||
74 | return pp; | ||
75 | } | ||
76 | |||
77 | +static struct sk_buff **ipip_gro_receive(struct sk_buff **head, | ||
78 | + struct sk_buff *skb) | ||
79 | +{ | ||
80 | + if (NAPI_GRO_CB(skb)->encap_mark) { | ||
81 | + NAPI_GRO_CB(skb)->flush = 1; | ||
82 | + return NULL; | ||
83 | + } | ||
84 | + | ||
85 | + NAPI_GRO_CB(skb)->encap_mark = 1; | ||
86 | + | ||
87 | + return inet_gro_receive(head, skb); | ||
88 | +} | ||
89 | + | ||
90 | int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | ||
91 | { | ||
92 | if (sk->sk_family == AF_INET) | ||
93 | @@ -1646,7 +1659,7 @@ static struct packet_offload ip_packet_offload __read_mostly = { | ||
94 | static const struct net_offload ipip_offload = { | ||
95 | .callbacks = { | ||
96 | .gso_segment = inet_gso_segment, | ||
97 | - .gro_receive = inet_gro_receive, | ||
98 | + .gro_receive = ipip_gro_receive, | ||
99 | .gro_complete = inet_gro_complete, | ||
100 | }, | ||
101 | }; | ||
102 | diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c | ||
103 | index 53300b88d569..79ae0d7becbf 100644 | ||
104 | --- a/net/ipv4/gre_offload.c | ||
105 | +++ b/net/ipv4/gre_offload.c | ||
106 | @@ -128,6 +128,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, | ||
107 | struct packet_offload *ptype; | ||
108 | __be16 type; | ||
109 | |||
110 | + if (NAPI_GRO_CB(skb)->encap_mark) | ||
111 | + goto out; | ||
112 | + | ||
113 | + NAPI_GRO_CB(skb)->encap_mark = 1; | ||
114 | + | ||
115 | off = skb_gro_offset(skb); | ||
116 | hlen = off + sizeof(*greh); | ||
117 | greh = skb_gro_header_fast(skb, off); | ||
118 | diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c | ||
119 | index 2af7b7e1a0f6..dfcab88c3e74 100644 | ||
120 | --- a/net/ipv4/udp_offload.c | ||
121 | +++ b/net/ipv4/udp_offload.c | ||
122 | @@ -299,14 +299,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, | ||
123 | unsigned int off = skb_gro_offset(skb); | ||
124 | int flush = 1; | ||
125 | |||
126 | - if (NAPI_GRO_CB(skb)->udp_mark || | ||
127 | + if (NAPI_GRO_CB(skb)->encap_mark || | ||
128 | (skb->ip_summed != CHECKSUM_PARTIAL && | ||
129 | NAPI_GRO_CB(skb)->csum_cnt == 0 && | ||
130 | !NAPI_GRO_CB(skb)->csum_valid)) | ||
131 | goto out; | ||
132 | |||
133 | - /* mark that this skb passed once through the udp gro layer */ | ||
134 | - NAPI_GRO_CB(skb)->udp_mark = 1; | ||
135 | + /* mark that this skb passed once through the tunnel gro layer */ | ||
136 | + NAPI_GRO_CB(skb)->encap_mark = 1; | ||
137 | |||
138 | rcu_read_lock(); | ||
139 | uo_priv = rcu_dereference(udp_offload_base); | ||
140 | diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c | ||
141 | index db0b8428d248..9b01da54d475 100644 | ||
142 | --- a/net/ipv6/ip6_offload.c | ||
143 | +++ b/net/ipv6/ip6_offload.c | ||
144 | @@ -260,6 +260,19 @@ out: | ||
145 | return pp; | ||
146 | } | ||
147 | |||
148 | +static struct sk_buff **sit_gro_receive(struct sk_buff **head, | ||
149 | + struct sk_buff *skb) | ||
150 | +{ | ||
151 | + if (NAPI_GRO_CB(skb)->encap_mark) { | ||
152 | + NAPI_GRO_CB(skb)->flush = 1; | ||
153 | + return NULL; | ||
154 | + } | ||
155 | + | ||
156 | + NAPI_GRO_CB(skb)->encap_mark = 1; | ||
157 | + | ||
158 | + return ipv6_gro_receive(head, skb); | ||
159 | +} | ||
160 | + | ||
161 | static int ipv6_gro_complete(struct sk_buff *skb, int nhoff) | ||
162 | { | ||
163 | const struct net_offload *ops; | ||
164 | -- | ||
165 | cgit 1.2-0.3.lf.el7 | ||
166 | |||