Change-Id: I581fd4cff3f414cb1d71a293a9b73a05a211e4cd
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/4821
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Dheeraj S Shetty <dheerajs@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,344 @@ |
0 |
+From 9331dbdcd7aa8e997eb4caa9b1b0cb6c804320c8 Mon Sep 17 00:00:00 2001 |
|
1 |
+From: Arjun Shankar <arjun@redhat.com> |
|
2 |
+Date: Thu, 18 Jan 2018 16:47:06 +0000 |
|
3 |
+Subject: [PATCH] Fix integer overflows in internal memalign and malloc [BZ |
|
4 |
+ #22343] [BZ #22774] |
|
5 |
+ |
|
6 |
+When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT |
|
7 |
+and a requested size close to SIZE_MAX, it falls back to malloc code |
|
8 |
+(because the alignment of a block returned by malloc is sufficient to |
|
9 |
+satisfy the call). In this case, an integer overflow in _int_malloc leads |
|
10 |
+to posix_memalign incorrectly returning successfully. |
|
11 |
+ |
|
12 |
+Upon fixing this and writing a somewhat thorough regression test, it was |
|
13 |
+discovered that when posix_memalign is called with an alignment larger than |
|
14 |
+MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size |
|
15 |
+close to SIZE_MAX, a different integer overflow in _int_memalign leads to |
|
16 |
+posix_memalign incorrectly returning successfully. |
|
17 |
+ |
|
18 |
+Both integer overflows affect other memory allocation functions that use |
|
19 |
+_int_malloc (one affected malloc in x86) or _int_memalign as well. |
|
20 |
+ |
|
21 |
+This commit fixes both integer overflows. In addition to this, it adds a |
|
22 |
+regression test to guard against false successful allocations by the |
|
23 |
+following memory allocation functions when called with too-large allocation |
|
24 |
+sizes and, where relevant, various valid alignments: |
|
25 |
+malloc, realloc, calloc, memalign, posix_memalign, aligned_alloc, valloc, |
|
26 |
+and pvalloc. |
|
27 |
+ |
|
28 |
+(cherry picked from commit 8e448310d74b283c5cd02b9ed7fb997b47bf9b22) |
|
29 |
+--- |
|
30 |
+ ChangeLog | 13 +++ |
|
31 |
+ NEWS | 10 ++ |
|
32 |
+ malloc/Makefile | 1 + |
|
33 |
+ malloc/malloc.c | 30 ++++-- |
|
34 |
+ malloc/tst-malloc-too-large.c | 237 ++++++++++++++++++++++++++++++++++++++++++ |
|
35 |
+ 5 files changed, 283 insertions(+), 8 deletions(-) |
|
36 |
+ create mode 100644 malloc/tst-malloc-too-large.c |
|
37 |
+ |
|
38 |
+diff --git a/malloc/Makefile b/malloc/Makefile |
|
39 |
+index 89fce91..9b40e87 100644 |
|
40 |
+--- a/malloc/Makefile |
|
41 |
+@@ -34,6 +34,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ |
|
42 |
+ tst-interpose-nothread \ |
|
43 |
+ tst-interpose-thread \ |
|
44 |
+ tst-alloc_buffer \ |
|
45 |
++ tst-malloc-too-large \ |
|
46 |
+ |
|
47 |
+ tests-static := \ |
|
48 |
+ tst-interpose-static-nothread \ |
|
49 |
+diff --git a/malloc/malloc.c b/malloc/malloc.c |
|
50 |
+index 4e07663..0686e5d 100644 |
|
51 |
+--- a/malloc/malloc.c |
|
52 |
+@@ -1202,14 +1202,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|
53 |
+ MINSIZE : \ |
|
54 |
+ ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) |
|
55 |
+ |
|
56 |
+-/* Same, except also perform argument check */ |
|
57 |
+- |
|
58 |
+-#define checked_request2size(req, sz) \ |
|
59 |
+- if (REQUEST_OUT_OF_RANGE (req)) { \ |
|
60 |
+- __set_errno (ENOMEM); \ |
|
61 |
+- return 0; \ |
|
62 |
+- } \ |
|
63 |
+- (sz) = request2size (req); |
|
64 |
++/* Same, except also perform an argument and result check. First, we check |
|
65 |
++ that the padding done by request2size didn't result in an integer |
|
66 |
++ overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting |
|
67 |
++ size isn't so large that a later alignment would lead to another integer |
|
68 |
++ overflow. */ |
|
69 |
++#define checked_request2size(req, sz) \ |
|
70 |
++({ \ |
|
71 |
++ (sz) = request2size (req); \ |
|
72 |
++ if (((sz) < (req)) \ |
|
73 |
++ || REQUEST_OUT_OF_RANGE (sz)) \ |
|
74 |
++ { \ |
|
75 |
++ __set_errno (ENOMEM); \ |
|
76 |
++ return 0; \ |
|
77 |
++ } \ |
|
78 |
++}) |
|
79 |
+ |
|
80 |
+ /* |
|
81 |
+ --------------- Physical chunk operations --------------- |
|
82 |
+@@ -4423,6 +4430,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) |
|
83 |
+ */ |
|
84 |
+ |
|
85 |
+ |
|
86 |
++ /* Check for overflow. */ |
|
87 |
++ if (nb > SIZE_MAX - alignment - MINSIZE) |
|
88 |
++ { |
|
89 |
++ __set_errno (ENOMEM); |
|
90 |
++ return 0; |
|
91 |
++ } |
|
92 |
++ |
|
93 |
+ /* Call malloc with worst case padding to hit alignment. */ |
|
94 |
+ |
|
95 |
+ m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); |
|
96 |
+diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c |
|
97 |
+new file mode 100644 |
|
98 |
+index 0000000..1f7bf29 |
|
99 |
+--- /dev/null |
|
100 |
+@@ -0,0 +1,237 @@ |
|
101 |
++/* Test and verify that too-large memory allocations fail with ENOMEM. |
|
102 |
++ Copyright (C) 2018 Free Software Foundation, Inc. |
|
103 |
++ This file is part of the GNU C Library. |
|
104 |
++ |
|
105 |
++ The GNU C Library is free software; you can redistribute it and/or |
|
106 |
++ modify it under the terms of the GNU Lesser General Public |
|
107 |
++ License as published by the Free Software Foundation; either |
|
108 |
++ version 2.1 of the License, or (at your option) any later version. |
|
109 |
++ |
|
110 |
++ The GNU C Library is distributed in the hope that it will be useful, |
|
111 |
++ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
112 |
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
113 |
++ Lesser General Public License for more details. |
|
114 |
++ |
|
115 |
++ You should have received a copy of the GNU Lesser General Public |
|
116 |
++ License along with the GNU C Library; if not, see |
|
117 |
++ <http://www.gnu.org/licenses/>. */ |
|
118 |
++ |
|
119 |
++/* Bug 22375 reported a regression in malloc where if after malloc'ing then |
|
120 |
++ free'ing a small block of memory, malloc is then called with a really |
|
121 |
++ large size argument (close to SIZE_MAX): instead of returning NULL and |
|
122 |
++ setting errno to ENOMEM, malloc incorrectly returns the previously |
|
123 |
++ allocated block instead. Bug 22343 reported a similar case where |
|
124 |
++ posix_memalign incorrectly returns successfully when called with an with |
|
125 |
++ a really large size argument. |
|
126 |
++ |
|
127 |
++ Both of these were caused by integer overflows in the allocator when it |
|
128 |
++ was trying to pad the requested size to allow for book-keeping or |
|
129 |
++ alignment. This test guards against such bugs by repeatedly allocating |
|
130 |
++ and freeing small blocks of memory then trying to allocate various block |
|
131 |
++ sizes larger than the memory bus width of 64-bit targets, or almost |
|
132 |
++ as large as SIZE_MAX on 32-bit targets supported by glibc. In each case, |
|
133 |
++ it verifies that such impossibly large allocations correctly fail. */ |
|
134 |
++ |
|
135 |
++ |
|
136 |
++#include <stdlib.h> |
|
137 |
++#include <malloc.h> |
|
138 |
++#include <errno.h> |
|
139 |
++#include <stdint.h> |
|
140 |
++#include <sys/resource.h> |
|
141 |
++#include <libc-internal.h> |
|
142 |
++#include <support/check.h> |
|
143 |
++#include <unistd.h> |
|
144 |
++#include <sys/param.h> |
|
145 |
++ |
|
146 |
++ |
|
147 |
++/* This function prepares for each 'too-large memory allocation' test by |
|
148 |
++ performing a small successful malloc/free and resetting errno prior to |
|
149 |
++ the actual test. */ |
|
150 |
++static void |
|
151 |
++test_setup (void) |
|
152 |
++{ |
|
153 |
++ void *volatile ptr = malloc (16); |
|
154 |
++ TEST_VERIFY_EXIT (ptr != NULL); |
|
155 |
++ free (ptr); |
|
156 |
++ errno = 0; |
|
157 |
++} |
|
158 |
++ |
|
159 |
++ |
|
160 |
++/* This function tests each of: |
|
161 |
++ - malloc (SIZE) |
|
162 |
++ - realloc (PTR_FOR_REALLOC, SIZE) |
|
163 |
++ - for various values of NMEMB: |
|
164 |
++ - calloc (NMEMB, SIZE/NMEMB) |
|
165 |
++ - calloc (SIZE/NMEMB, NMEMB) |
|
166 |
++ and precedes each of these tests with a small malloc/free before it. */ |
|
167 |
++static void |
|
168 |
++test_large_allocations (size_t size) |
|
169 |
++{ |
|
170 |
++ void * ptr_to_realloc; |
|
171 |
++ |
|
172 |
++ test_setup (); |
|
173 |
++ TEST_VERIFY (malloc (size) == NULL); |
|
174 |
++ TEST_VERIFY (errno == ENOMEM); |
|
175 |
++ |
|
176 |
++ ptr_to_realloc = malloc (16); |
|
177 |
++ TEST_VERIFY_EXIT (ptr_to_realloc != NULL); |
|
178 |
++ test_setup (); |
|
179 |
++ TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL); |
|
180 |
++ TEST_VERIFY (errno == ENOMEM); |
|
181 |
++ free (ptr_to_realloc); |
|
182 |
++ |
|
183 |
++ for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2) |
|
184 |
++ if ((size % nmemb) == 0) |
|
185 |
++ { |
|
186 |
++ test_setup (); |
|
187 |
++ TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL); |
|
188 |
++ TEST_VERIFY (errno == ENOMEM); |
|
189 |
++ |
|
190 |
++ test_setup (); |
|
191 |
++ TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL); |
|
192 |
++ TEST_VERIFY (errno == ENOMEM); |
|
193 |
++ } |
|
194 |
++ else |
|
195 |
++ break; |
|
196 |
++} |
|
197 |
++ |
|
198 |
++ |
|
199 |
++static long pagesize; |
|
200 |
++ |
|
201 |
++/* This function tests the following aligned memory allocation functions |
|
202 |
++ using several valid alignments and precedes each allocation test with a |
|
203 |
++ small malloc/free before it: |
|
204 |
++ memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */ |
|
205 |
++static void |
|
206 |
++test_large_aligned_allocations (size_t size) |
|
207 |
++{ |
|
208 |
++ /* ptr stores the result of posix_memalign but since all those calls |
|
209 |
++ should fail, posix_memalign should never change ptr. We set it to |
|
210 |
++ NULL here and later on we check that it remains NULL after each |
|
211 |
++ posix_memalign call. */ |
|
212 |
++ void * ptr = NULL; |
|
213 |
++ |
|
214 |
++ size_t align; |
|
215 |
++ |
|
216 |
++ /* All aligned memory allocation functions expect an alignment that is a |
|
217 |
++ power of 2. Given this, we test each of them with every valid |
|
218 |
++ alignment from 1 thru PAGESIZE. */ |
|
219 |
++ for (align = 1; align <= pagesize; align *= 2) |
|
220 |
++ { |
|
221 |
++ test_setup (); |
|
222 |
++ TEST_VERIFY (memalign (align, size) == NULL); |
|
223 |
++ TEST_VERIFY (errno == ENOMEM); |
|
224 |
++ |
|
225 |
++ /* posix_memalign expects an alignment that is a power of 2 *and* a |
|
226 |
++ multiple of sizeof (void *). */ |
|
227 |
++ if ((align % sizeof (void *)) == 0) |
|
228 |
++ { |
|
229 |
++ test_setup (); |
|
230 |
++ TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM); |
|
231 |
++ TEST_VERIFY (ptr == NULL); |
|
232 |
++ } |
|
233 |
++ |
|
234 |
++ /* aligned_alloc expects a size that is a multiple of alignment. */ |
|
235 |
++ if ((size % align) == 0) |
|
236 |
++ { |
|
237 |
++ test_setup (); |
|
238 |
++ TEST_VERIFY (aligned_alloc (align, size) == NULL); |
|
239 |
++ TEST_VERIFY (errno == ENOMEM); |
|
240 |
++ } |
|
241 |
++ } |
|
242 |
++ |
|
243 |
++ /* Both valloc and pvalloc return page-aligned memory. */ |
|
244 |
++ |
|
245 |
++ test_setup (); |
|
246 |
++ TEST_VERIFY (valloc (size) == NULL); |
|
247 |
++ TEST_VERIFY (errno == ENOMEM); |
|
248 |
++ |
|
249 |
++ test_setup (); |
|
250 |
++ TEST_VERIFY (pvalloc (size) == NULL); |
|
251 |
++ TEST_VERIFY (errno == ENOMEM); |
|
252 |
++} |
|
253 |
++ |
|
254 |
++ |
|
255 |
++#define FOURTEEN_ON_BITS ((1UL << 14) - 1) |
|
256 |
++#define FIFTY_ON_BITS ((1UL << 50) - 1) |
|
257 |
++ |
|
258 |
++ |
|
259 |
++static int |
|
260 |
++do_test (void) |
|
261 |
++{ |
|
262 |
++ |
|
263 |
++#if __WORDSIZE >= 64 |
|
264 |
++ |
|
265 |
++ /* This test assumes that none of the supported targets have an address |
|
266 |
++ bus wider than 50 bits, and that therefore allocations for sizes wider |
|
267 |
++ than 50 bits will fail. Here, we ensure that the assumption continues |
|
268 |
++ to be true in the future when we might have address buses wider than 50 |
|
269 |
++ bits. */ |
|
270 |
++ |
|
271 |
++ struct rlimit alloc_size_limit |
|
272 |
++ = { |
|
273 |
++ .rlim_cur = FIFTY_ON_BITS, |
|
274 |
++ .rlim_max = FIFTY_ON_BITS |
|
275 |
++ }; |
|
276 |
++ |
|
277 |
++ setrlimit (RLIMIT_AS, &alloc_size_limit); |
|
278 |
++ |
|
279 |
++#endif /* __WORDSIZE >= 64 */ |
|
280 |
++ |
|
281 |
++ DIAG_PUSH_NEEDS_COMMENT; |
|
282 |
++#if __GNUC_PREREQ (7, 0) |
|
283 |
++ /* GCC 7 warns about too-large allocations; here we want to test |
|
284 |
++ that they fail. */ |
|
285 |
++ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); |
|
286 |
++#endif |
|
287 |
++ |
|
288 |
++ /* Aligned memory allocation functions need to be tested up to alignment |
|
289 |
++ size equivalent to page size, which should be a power of 2. */ |
|
290 |
++ pagesize = sysconf (_SC_PAGESIZE); |
|
291 |
++ TEST_VERIFY_EXIT (powerof2 (pagesize)); |
|
292 |
++ |
|
293 |
++ /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. |
|
294 |
++ in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. |
|
295 |
++ |
|
296 |
++ We can expect that this range of allocation sizes will always lead to |
|
297 |
++ an allocation failure on both 64 and 32 bit targets, because: |
|
298 |
++ |
|
299 |
++ 1. no currently supported 64-bit target has an address bus wider than |
|
300 |
++ 50 bits -- and (2^64 - 2^14) is much wider than that; |
|
301 |
++ |
|
302 |
++ 2. on 32-bit targets, even though 2^32 is only 4 GB and potentially |
|
303 |
++ addressable, glibc itself is more than 2^14 bytes in size, and |
|
304 |
++ therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain |
|
305 |
++ available. */ |
|
306 |
++ |
|
307 |
++ for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++) |
|
308 |
++ { |
|
309 |
++ test_large_allocations (SIZE_MAX - i); |
|
310 |
++ test_large_aligned_allocations (SIZE_MAX - i); |
|
311 |
++ } |
|
312 |
++ |
|
313 |
++#if __WORDSIZE >= 64 |
|
314 |
++ /* On 64-bit targets, we need to test a much wider range of too-large |
|
315 |
++ sizes, so we test at intervals of (1 << 50) that allocation sizes |
|
316 |
++ ranging from SIZE_MAX down to (1 << 50) fail: |
|
317 |
++ The 14 MSBs are decremented starting from "all ON" going down to 1, |
|
318 |
++ the 50 LSBs are "all ON" and then "all OFF" during every iteration. */ |
|
319 |
++ for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--) |
|
320 |
++ { |
|
321 |
++ size_t size = (msbs << 50) | FIFTY_ON_BITS; |
|
322 |
++ test_large_allocations (size); |
|
323 |
++ test_large_aligned_allocations (size); |
|
324 |
++ |
|
325 |
++ size = msbs << 50; |
|
326 |
++ test_large_allocations (size); |
|
327 |
++ test_large_aligned_allocations (size); |
|
328 |
++ } |
|
329 |
++#endif /* __WORDSIZE >= 64 */ |
|
330 |
++ |
|
331 |
++ DIAG_POP_NEEDS_COMMENT; |
|
332 |
++ |
|
333 |
++ return 0; |
|
334 |
++} |
|
335 |
++ |
|
336 |
++ |
|
337 |
++#include <support/test-driver.c> |
|
338 |
+-- |
|
339 |
+2.9.3 |
|
340 |
+ |
... | ... |
@@ -4,7 +4,7 @@ |
4 | 4 |
Summary: Main C library |
5 | 5 |
Name: glibc |
6 | 6 |
Version: 2.26 |
7 |
-Release: 9%{?dist} |
|
7 |
+Release: 10%{?dist} |
|
8 | 8 |
License: LGPLv2+ |
9 | 9 |
URL: http://www.gnu.org/software/libc |
10 | 10 |
Group: Applications/System |
... | ... |
@@ -23,6 +23,7 @@ Patch5: glibc-fix-CVE-2017-15804.patch |
23 | 23 |
Patch6: glibc-fix-CVE-2017-17426.patch |
24 | 24 |
Patch7: glibc-fix-CVE-2017-16997.patch |
25 | 25 |
Patch8: glibc-fix-CVE-2018-1000001.patch |
26 |
+Patch9: glibc-fix-CVE-2018-6485.patch |
|
26 | 27 |
Provides: rtld(GNU_HASH) |
27 | 28 |
Requires: filesystem |
28 | 29 |
%description |
... | ... |
@@ -85,6 +86,7 @@ sed -i 's/\\$$(pwd)/`pwd`/' timezone/Makefile |
85 | 85 |
%patch6 -p1 |
86 | 86 |
%patch7 -p1 |
87 | 87 |
%patch8 -p1 |
88 |
+%patch9 -p1 |
|
88 | 89 |
install -vdm 755 %{_builddir}/%{name}-build |
89 | 90 |
# do not try to explicitly provide GLIBC_PRIVATE versioned libraries |
90 | 91 |
%define __find_provides %{_builddir}/%{name}-%{version}/find_provides.sh |
... | ... |
@@ -288,6 +290,8 @@ grep "^FAIL: nptl/tst-eintr1" tests.sum >/dev/null && n=$((n+1)) ||: |
288 | 288 |
|
289 | 289 |
|
290 | 290 |
%changelog |
291 |
+* Tue Jan 20 2018 Xiaolin Li <xiaolinl@vmware.com> 2.26-10 |
|
292 |
+- Fix CVE-2018-6485 |
|
291 | 293 |
* Tue Jan 20 2018 Xiaolin Li <xiaolinl@vmware.com> 2.26-9 |
292 | 294 |
- Fix CVE-2018-1000001 |
293 | 295 |
* Mon Jan 08 2018 Xiaolin Li <xiaolinl@vmware.com> 2.26-8 |