summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Wellving <andreas.wellving@enea.com>2018-10-17 14:49:40 +0200
committerAdrian Mangeac <Adrian.Mangeac@enea.com>2018-10-24 12:45:37 +0200
commita6b0b1077b78acbeb4766ccf1a742efa59d6312e (patch)
tree81167312fa649401ec65504c44087ad99db4dfc6
parentc380c25c485c1a2ef86f89a9e2b971c55f3c1b2c (diff)
downloadenea-kernel-cache-a6b0b1077b78acbeb4766ccf1a742efa59d6312e.tar.gz
ipv6: CVE-2017-9074
ipv6: Prevent overrun when parsing v6 header options References: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.1.y&id=e7f05ff30b0cd72b00c8ca7be3cd48fedf96550f Change-Id: I68b0cc05c982bfe649ac3dfafb876e39ffa0e64f Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
-rw-r--r--patches/cve/4.1.x.scc3
-rw-r--r--patches/cve/CVE-2017-9074-ipv6-Prevent-overrun-when-parsing-v6-header-options.patch236
2 files changed, 239 insertions, 0 deletions
diff --git a/patches/cve/4.1.x.scc b/patches/cve/4.1.x.scc
index 17685e1..341f0f2 100644
--- a/patches/cve/4.1.x.scc
+++ b/patches/cve/4.1.x.scc
@@ -12,3 +12,6 @@ patch CVE-2017-7895-nfsd-stricter-decoding-of-write-like-NFSv2-v3-ops.patch
12patch CVE-2017-10661-timerfd-Protect-the-might-cancel-mechanism-proper.patch 12patch CVE-2017-10661-timerfd-Protect-the-might-cancel-mechanism-proper.patch
13patch CVE-2017-18221-mlock-fix-mlock-count-can-not-decrease-in-race-condi.patch 13patch CVE-2017-18221-mlock-fix-mlock-count-can-not-decrease-in-race-condi.patch
14patch CVE-2017-7308-net-packet-fix-overflow-in-check-for-priv-area-size.patch 14patch CVE-2017-7308-net-packet-fix-overflow-in-check-for-priv-area-size.patch
15
16#fixed in 4.1.42
17patch CVE-2017-9074-ipv6-Prevent-overrun-when-parsing-v6-header-options.patch
diff --git a/patches/cve/CVE-2017-9074-ipv6-Prevent-overrun-when-parsing-v6-header-options.patch b/patches/cve/CVE-2017-9074-ipv6-Prevent-overrun-when-parsing-v6-header-options.patch
new file mode 100644
index 0000000..ade9eaa
--- /dev/null
+++ b/patches/cve/CVE-2017-9074-ipv6-Prevent-overrun-when-parsing-v6-header-options.patch
@@ -0,0 +1,236 @@
1From e7f05ff30b0cd72b00c8ca7be3cd48fedf96550f Mon Sep 17 00:00:00 2001
2From: Craig Gallek <kraig@google.com>
3Date: Tue, 16 May 2017 14:36:23 -0400
4Subject: [PATCH] ipv6: Prevent overrun when parsing v6 header options
5
6[ Upstream commit 2423496af35d94a87156b063ea5cedffc10a70a1 ]
7
8The KASAN warning repoted below was discovered with a syzkaller
9program. The reproducer is basically:
10 int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP);
11 send(s, &one_byte_of_data, 1, MSG_MORE);
12 send(s, &more_than_mtu_bytes_data, 2000, 0);
13
14The socket() call sets the nexthdr field of the v6 header to
15NEXTHDR_HOP, the first send call primes the payload with a non zero
16byte of data, and the second send call triggers the fragmentation path.
17
18The fragmentation code tries to parse the header options in order
19to figure out where to insert the fragment option. Since nexthdr points
20to an invalid option, the calculation of the size of the network header
21can made to be much larger than the linear section of the skb and data
22is read outside of it.
23
24This fix makes ip6_find_1stfrag return an error if it detects
25running out-of-bounds.
26
27[ 42.361487] ==================================================================
28[ 42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730
29[ 42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789
30[ 42.366469]
31[ 42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41
32[ 42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
33[ 42.368824] Call Trace:
34[ 42.369183] dump_stack+0xb3/0x10b
35[ 42.369664] print_address_description+0x73/0x290
36[ 42.370325] kasan_report+0x252/0x370
37[ 42.370839] ? ip6_fragment+0x11c8/0x3730
38[ 42.371396] check_memory_region+0x13c/0x1a0
39[ 42.371978] memcpy+0x23/0x50
40[ 42.372395] ip6_fragment+0x11c8/0x3730
41[ 42.372920] ? nf_ct_expect_unregister_notifier+0x110/0x110
42[ 42.373681] ? ip6_copy_metadata+0x7f0/0x7f0
43[ 42.374263] ? ip6_forward+0x2e30/0x2e30
44[ 42.374803] ip6_finish_output+0x584/0x990
45[ 42.375350] ip6_output+0x1b7/0x690
46[ 42.375836] ? ip6_finish_output+0x990/0x990
47[ 42.376411] ? ip6_fragment+0x3730/0x3730
48[ 42.376968] ip6_local_out+0x95/0x160
49[ 42.377471] ip6_send_skb+0xa1/0x330
50[ 42.377969] ip6_push_pending_frames+0xb3/0xe0
51[ 42.378589] rawv6_sendmsg+0x2051/0x2db0
52[ 42.379129] ? rawv6_bind+0x8b0/0x8b0
53[ 42.379633] ? _copy_from_user+0x84/0xe0
54[ 42.380193] ? debug_check_no_locks_freed+0x290/0x290
55[ 42.380878] ? ___sys_sendmsg+0x162/0x930
56[ 42.381427] ? rcu_read_lock_sched_held+0xa3/0x120
57[ 42.382074] ? sock_has_perm+0x1f6/0x290
58[ 42.382614] ? ___sys_sendmsg+0x167/0x930
59[ 42.383173] ? lock_downgrade+0x660/0x660
60[ 42.383727] inet_sendmsg+0x123/0x500
61[ 42.384226] ? inet_sendmsg+0x123/0x500
62[ 42.384748] ? inet_recvmsg+0x540/0x540
63[ 42.385263] sock_sendmsg+0xca/0x110
64[ 42.385758] SYSC_sendto+0x217/0x380
65[ 42.386249] ? SYSC_connect+0x310/0x310
66[ 42.386783] ? __might_fault+0x110/0x1d0
67[ 42.387324] ? lock_downgrade+0x660/0x660
68[ 42.387880] ? __fget_light+0xa1/0x1f0
69[ 42.388403] ? __fdget+0x18/0x20
70[ 42.388851] ? sock_common_setsockopt+0x95/0xd0
71[ 42.389472] ? SyS_setsockopt+0x17f/0x260
72[ 42.390021] ? entry_SYSCALL_64_fastpath+0x5/0xbe
73[ 42.390650] SyS_sendto+0x40/0x50
74[ 42.391103] entry_SYSCALL_64_fastpath+0x1f/0xbe
75[ 42.391731] RIP: 0033:0x7fbbb711e383
76[ 42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
77[ 42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383
78[ 42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003
79[ 42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018
80[ 42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad
81[ 42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00
82[ 42.397257]
83[ 42.397411] Allocated by task 3789:
84[ 42.397702] save_stack_trace+0x16/0x20
85[ 42.398005] save_stack+0x46/0xd0
86[ 42.398267] kasan_kmalloc+0xad/0xe0
87[ 42.398548] kasan_slab_alloc+0x12/0x20
88[ 42.398848] __kmalloc_node_track_caller+0xcb/0x380
89[ 42.399224] __kmalloc_reserve.isra.32+0x41/0xe0
90[ 42.399654] __alloc_skb+0xf8/0x580
91[ 42.400003] sock_wmalloc+0xab/0xf0
92[ 42.400346] __ip6_append_data.isra.41+0x2472/0x33d0
93[ 42.400813] ip6_append_data+0x1a8/0x2f0
94[ 42.401122] rawv6_sendmsg+0x11ee/0x2db0
95[ 42.401505] inet_sendmsg+0x123/0x500
96[ 42.401860] sock_sendmsg+0xca/0x110
97[ 42.402209] ___sys_sendmsg+0x7cb/0x930
98[ 42.402582] __sys_sendmsg+0xd9/0x190
99[ 42.402941] SyS_sendmsg+0x2d/0x50
100[ 42.403273] entry_SYSCALL_64_fastpath+0x1f/0xbe
101[ 42.403718]
102[ 42.403871] Freed by task 1794:
103[ 42.404146] save_stack_trace+0x16/0x20
104[ 42.404515] save_stack+0x46/0xd0
105[ 42.404827] kasan_slab_free+0x72/0xc0
106[ 42.405167] kfree+0xe8/0x2b0
107[ 42.405462] skb_free_head+0x74/0xb0
108[ 42.405806] skb_release_data+0x30e/0x3a0
109[ 42.406198] skb_release_all+0x4a/0x60
110[ 42.406563] consume_skb+0x113/0x2e0
111[ 42.406910] skb_free_datagram+0x1a/0xe0
112[ 42.407288] netlink_recvmsg+0x60d/0xe40
113[ 42.407667] sock_recvmsg+0xd7/0x110
114[ 42.408022] ___sys_recvmsg+0x25c/0x580
115[ 42.408395] __sys_recvmsg+0xd6/0x190
116[ 42.408753] SyS_recvmsg+0x2d/0x50
117[ 42.409086] entry_SYSCALL_64_fastpath+0x1f/0xbe
118[ 42.409513]
119[ 42.409665] The buggy address belongs to the object at ffff88000969e780
120[ 42.409665] which belongs to the cache kmalloc-512 of size 512
121[ 42.410846] The buggy address is located 24 bytes inside of
122[ 42.410846] 512-byte region [ffff88000969e780, ffff88000969e980)
123[ 42.411941] The buggy address belongs to the page:
124[ 42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0
125[ 42.413298] flags: 0x100000000008100(slab|head)
126[ 42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c
127[ 42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000
128[ 42.415074] page dumped because: kasan: bad access detected
129[ 42.415604]
130[ 42.415757] Memory state around the buggy address:
131[ 42.416222] ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
132[ 42.416904] ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
133[ 42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
134[ 42.418273] ^
135[ 42.418588] ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
136[ 42.419273] ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
137[ 42.419882] ==================================================================
138
139CVE: CVE-2017-9074
140Upstream-Status: Backport
141
142Reported-by: Andrey Konovalov <andreyknvl@google.com>
143Signed-off-by: Craig Gallek <kraig@google.com>
144Signed-off-by: David S. Miller <davem@davemloft.net>
145Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
146Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
147---
148 net/ipv6/ip6_offload.c | 2 ++
149 net/ipv6/ip6_output.c | 4 ++++
150 net/ipv6/output_core.c | 14 ++++++++------
151 net/ipv6/udp_offload.c | 2 ++
152 4 files changed, 16 insertions(+), 6 deletions(-)
153
154diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
155index 9b01da5..ff400ad 100644
156--- a/net/ipv6/ip6_offload.c
157+++ b/net/ipv6/ip6_offload.c
158@@ -122,6 +122,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
159
160 if (udpfrag) {
161 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
162+ if (unfrag_ip6hlen < 0)
163+ return ERR_PTR(unfrag_ip6hlen);
164 fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
165 fptr->frag_off = htons(offset);
166 if (skb->next)
167diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
168index 06bf401..5f4faa5 100644
169--- a/net/ipv6/ip6_output.c
170+++ b/net/ipv6/ip6_output.c
171@@ -560,6 +560,10 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
172 struct net *net = dev_net(skb_dst(skb)->dev);
173
174 hlen = ip6_find_1stfragopt(skb, &prevhdr);
175+ if (hlen < 0) {
176+ err = hlen;
177+ goto fail;
178+ }
179 nexthdr = *prevhdr;
180
181 mtu = ip6_skb_dst_mtu(skb);
182diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
183index 85892af..3f6ee41 100644
184--- a/net/ipv6/output_core.c
185+++ b/net/ipv6/output_core.c
186@@ -77,14 +77,13 @@ EXPORT_SYMBOL(ipv6_select_ident);
187 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
188 {
189 u16 offset = sizeof(struct ipv6hdr);
190- struct ipv6_opt_hdr *exthdr =
191- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
192 unsigned int packet_len = skb_tail_pointer(skb) -
193 skb_network_header(skb);
194 int found_rhdr = 0;
195 *nexthdr = &ipv6_hdr(skb)->nexthdr;
196
197- while (offset + 1 <= packet_len) {
198+ while (offset <= packet_len) {
199+ struct ipv6_opt_hdr *exthdr;
200
201 switch (**nexthdr) {
202
203@@ -105,13 +104,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
204 return offset;
205 }
206
207- offset += ipv6_optlen(exthdr);
208- *nexthdr = &exthdr->nexthdr;
209+ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
210+ return -EINVAL;
211+
212 exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
213 offset);
214+ offset += ipv6_optlen(exthdr);
215+ *nexthdr = &exthdr->nexthdr;
216 }
217
218- return offset;
219+ return -EINVAL;
220 }
221 EXPORT_SYMBOL(ip6_find_1stfragopt);
222
223diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
224index 7441e1e..04ed91d 100644
225--- a/net/ipv6/udp_offload.c
226+++ b/net/ipv6/udp_offload.c
227@@ -98,6 +98,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
228 * bytes to insert fragment header.
229 */
230 unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
231+ if (unfrag_ip6hlen < 0)
232+ return ERR_PTR(unfrag_ip6hlen);
233 nexthdr = *prevhdr;
234 *prevhdr = NEXTHDR_FRAGMENT;
235 unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
236--