summaryrefslogtreecommitdiffstats
path: root/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch')
-rw-r--r--recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch401
1 files changed, 401 insertions, 0 deletions
diff --git a/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch b/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch
new file mode 100644
index 0000000..cb766c4
--- /dev/null
+++ b/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch
@@ -0,0 +1,401 @@
1From 5d7411e9ec03cae8e9bb5df4b515744e5065a64c Mon Sep 17 00:00:00 2001
2From: Andreas Wellving <andreas.wellving@enea.com>
3Date: Mon, 22 Oct 2018 13:54:54 +0200
4Subject: [PATCH] Fix integer overflows in internal memalign and malloc [BZ #22343] [BZ #22774]
5
6When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT
7and 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
9satisfy the call). In this case, an integer overflow in _int_malloc leads
10to posix_memalign incorrectly returning successfully.
11
12Upon fixing this and writing a somewhat thorough regression test, it was
13discovered that when posix_memalign is called with an alignment larger than
14MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size
15close to SIZE_MAX, a different integer overflow in _int_memalign leads to
16posix_memalign incorrectly returning successfully.
17
18Both integer overflows affect other memory allocation functions that use
19_int_malloc (one affected malloc in x86) or _int_memalign as well.
20
21This commit fixes both integer overflows. In addition to this, it adds a
22regression test to guard against false successful allocations by the
23following memory allocation functions when called with too-large allocation
24sizes and, where relevant, various valid alignments:
25malloc, realloc, calloc, memalign, posix_memalign, aligned_alloc, valloc,
26and pvalloc.
27
28(cherry picked from commit 8e448310d74b283c5cd02b9ed7fb997b47bf9b22)
29
30CVE: CVE-2018-6551
31Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=8e448310d74b283c5cd02b9ed7fb997b47bf9b22]
32
33Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
34---
35 ChangeLog | 13 +++
36 NEWS | 11 ++
37 malloc/Makefile | 1 +
38 malloc/malloc.c | 30 ++++--
39 malloc/tst-malloc-too-large.c | 237 ++++++++++++++++++++++++++++++++++++++++++
40 5 files changed, 284 insertions(+), 8 deletions(-)
41 create mode 100644 malloc/tst-malloc-too-large.c
42
43diff --git a/ChangeLog b/ChangeLog
44index ad380fd..48b095b 100644
45--- a/ChangeLog
46+++ b/ChangeLog
47@@ -1,3 +1,16 @@
48+2018-01-18 Arjun Shankar <arjun@redhat.com>
49+
50+ [BZ #22343]
51+ [BZ #22774]
52+ CVE-2018-6485
53+ CVE-2018-6551
54+ * malloc/malloc.c (checked_request2size): call REQUEST_OUT_OF_RANGE
55+ after padding.
56+ (_int_memalign): check for integer overflow before calling
57+ _int_malloc.
58+ * malloc/tst-malloc-too-large.c: New test.
59+ * malloc/Makefile: Add tst-malloc-too-large.
60+
61 2017-12-30 Aurelien Jarno <aurelien@aurel32.net>
62 Dmitry V. Levin <ldv@altlinux.org>
63
64diff --git a/NEWS b/NEWS
65index 195c06d..5134f34 100644
66--- a/NEWS
67+++ b/NEWS
68@@ -1,3 +1,4 @@
69+
70 GNU C Library NEWS -- history of user-visible changes.
71 Copyright (C) 1992-2017 Free Software Foundation, Inc.
72 See the end for copying conditions.
73@@ -218,6 +219,14 @@ Security related changes:
74 for AT_SECURE or SUID binaries could be used to load libraries from the
75 current directory.
76
77+ CVE-2018-6485: The posix_memalign and memalign functions, when called with
78+ an object size near the value of SIZE_MAX, would return a pointer to a
79+ buffer which is too small, instead of NULL. Reported by Jakub Wilk.
80+
81+ CVE-2018-6551: The malloc function, when called with an object size near
82+ the value of SIZE_MAX, would return a pointer to a buffer which is too
83+ small, instead of NULL.
84+
85 The following bugs are resolved with this release:
86
87 [4099] stdio: Overly agressive caching by stream i/o functions.
88@@ -365,6 +374,8 @@ The following bugs are resolved with this release:
89 [21073] libc: tunables: insecure environment variables passed to
90 subprocesses with AT_SECURE
91 [21081] string: Missing vzeroupper in memset-vec-unaligned-erms.S
92+ [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485)
93+ [22774] malloc: Integer overflow in malloc (CVE-2018-6551)
94
95 Version 2.24
96
97diff --git a/malloc/Makefile b/malloc/Makefile
98index e93b83b..ab9e795 100644
99--- a/malloc/Makefile
100+++ b/malloc/Makefile
101@@ -33,6 +33,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
102 tst-mallocfork2 \
103 tst-interpose-nothread \
104 tst-interpose-thread \
105+ tst-malloc-too-large \
106
107 tests-static := \
108 tst-interpose-static-nothread \
109diff --git a/malloc/malloc.c b/malloc/malloc.c
110index 4885793..a82555d 100644
111--- a/malloc/malloc.c
112+++ b/malloc/malloc.c
113@@ -1202,14 +1202,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 MINSIZE : \
115 ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
116
117-/* Same, except also perform argument check */
118-
119-#define checked_request2size(req, sz) \
120- if (REQUEST_OUT_OF_RANGE (req)) { \
121- __set_errno (ENOMEM); \
122- return 0; \
123- } \
124- (sz) = request2size (req);
125+/* Same, except also perform an argument and result check. First, we check
126+ that the padding done by request2size didn't result in an integer
127+ overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting
128+ size isn't so large that a later alignment would lead to another integer
129+ overflow. */
130+#define checked_request2size(req, sz) \
131+({ \
132+ (sz) = request2size (req); \
133+ if (((sz) < (req)) \
134+ || REQUEST_OUT_OF_RANGE (sz)) \
135+ { \
136+ __set_errno (ENOMEM); \
137+ return 0; \
138+ } \
139+})
140
141 /*
142 --------------- Physical chunk operations ---------------
143@@ -4423,6 +4430,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
144 */
145
146
147+ /* Check for overflow. */
148+ if (nb > SIZE_MAX - alignment - MINSIZE)
149+ {
150+ __set_errno (ENOMEM);
151+ return 0;
152+ }
153+
154 /* Call malloc with worst case padding to hit alignment. */
155
156 m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
157diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
158new file mode 100644
159index 0000000..1f7bf29
160--- /dev/null
161+++ b/malloc/tst-malloc-too-large.c
162@@ -0,0 +1,237 @@
163+/* Test and verify that too-large memory allocations fail with ENOMEM.
164+ Copyright (C) 2018 Free Software Foundation, Inc.
165+ This file is part of the GNU C Library.
166+
167+ The GNU C Library is free software; you can redistribute it and/or
168+ modify it under the terms of the GNU Lesser General Public
169+ License as published by the Free Software Foundation; either
170+ version 2.1 of the License, or (at your option) any later version.
171+
172+ The GNU C Library is distributed in the hope that it will be useful,
173+ but WITHOUT ANY WARRANTY; without even the implied warranty of
174+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
175+ Lesser General Public License for more details.
176+
177+ You should have received a copy of the GNU Lesser General Public
178+ License along with the GNU C Library; if not, see
179+ <http://www.gnu.org/licenses/>. */
180+
181+/* Bug 22375 reported a regression in malloc where if after malloc'ing then
182+ free'ing a small block of memory, malloc is then called with a really
183+ large size argument (close to SIZE_MAX): instead of returning NULL and
184+ setting errno to ENOMEM, malloc incorrectly returns the previously
185+ allocated block instead. Bug 22343 reported a similar case where
186+ posix_memalign incorrectly returns successfully when called with an with
187+ a really large size argument.
188+
189+ Both of these were caused by integer overflows in the allocator when it
190+ was trying to pad the requested size to allow for book-keeping or
191+ alignment. This test guards against such bugs by repeatedly allocating
192+ and freeing small blocks of memory then trying to allocate various block
193+ sizes larger than the memory bus width of 64-bit targets, or almost
194+ as large as SIZE_MAX on 32-bit targets supported by glibc. In each case,
195+ it verifies that such impossibly large allocations correctly fail. */
196+
197+
198+#include <stdlib.h>
199+#include <malloc.h>
200+#include <errno.h>
201+#include <stdint.h>
202+#include <sys/resource.h>
203+#include <libc-internal.h>
204+#include <support/check.h>
205+#include <unistd.h>
206+#include <sys/param.h>
207+
208+
209+/* This function prepares for each 'too-large memory allocation' test by
210+ performing a small successful malloc/free and resetting errno prior to
211+ the actual test. */
212+static void
213+test_setup (void)
214+{
215+ void *volatile ptr = malloc (16);
216+ TEST_VERIFY_EXIT (ptr != NULL);
217+ free (ptr);
218+ errno = 0;
219+}
220+
221+
222+/* This function tests each of:
223+ - malloc (SIZE)
224+ - realloc (PTR_FOR_REALLOC, SIZE)
225+ - for various values of NMEMB:
226+ - calloc (NMEMB, SIZE/NMEMB)
227+ - calloc (SIZE/NMEMB, NMEMB)
228+ and precedes each of these tests with a small malloc/free before it. */
229+static void
230+test_large_allocations (size_t size)
231+{
232+ void * ptr_to_realloc;
233+
234+ test_setup ();
235+ TEST_VERIFY (malloc (size) == NULL);
236+ TEST_VERIFY (errno == ENOMEM);
237+
238+ ptr_to_realloc = malloc (16);
239+ TEST_VERIFY_EXIT (ptr_to_realloc != NULL);
240+ test_setup ();
241+ TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL);
242+ TEST_VERIFY (errno == ENOMEM);
243+ free (ptr_to_realloc);
244+
245+ for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2)
246+ if ((size % nmemb) == 0)
247+ {
248+ test_setup ();
249+ TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL);
250+ TEST_VERIFY (errno == ENOMEM);
251+
252+ test_setup ();
253+ TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL);
254+ TEST_VERIFY (errno == ENOMEM);
255+ }
256+ else
257+ break;
258+}
259+
260+
261+static long pagesize;
262+
263+/* This function tests the following aligned memory allocation functions
264+ using several valid alignments and precedes each allocation test with a
265+ small malloc/free before it:
266+ memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */
267+static void
268+test_large_aligned_allocations (size_t size)
269+{
270+ /* ptr stores the result of posix_memalign but since all those calls
271+ should fail, posix_memalign should never change ptr. We set it to
272+ NULL here and later on we check that it remains NULL after each
273+ posix_memalign call. */
274+ void * ptr = NULL;
275+
276+ size_t align;
277+
278+ /* All aligned memory allocation functions expect an alignment that is a
279+ power of 2. Given this, we test each of them with every valid
280+ alignment from 1 thru PAGESIZE. */
281+ for (align = 1; align <= pagesize; align *= 2)
282+ {
283+ test_setup ();
284+ TEST_VERIFY (memalign (align, size) == NULL);
285+ TEST_VERIFY (errno == ENOMEM);
286+
287+ /* posix_memalign expects an alignment that is a power of 2 *and* a
288+ multiple of sizeof (void *). */
289+ if ((align % sizeof (void *)) == 0)
290+ {
291+ test_setup ();
292+ TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM);
293+ TEST_VERIFY (ptr == NULL);
294+ }
295+
296+ /* aligned_alloc expects a size that is a multiple of alignment. */
297+ if ((size % align) == 0)
298+ {
299+ test_setup ();
300+ TEST_VERIFY (aligned_alloc (align, size) == NULL);
301+ TEST_VERIFY (errno == ENOMEM);
302+ }
303+ }
304+
305+ /* Both valloc and pvalloc return page-aligned memory. */
306+
307+ test_setup ();
308+ TEST_VERIFY (valloc (size) == NULL);
309+ TEST_VERIFY (errno == ENOMEM);
310+
311+ test_setup ();
312+ TEST_VERIFY (pvalloc (size) == NULL);
313+ TEST_VERIFY (errno == ENOMEM);
314+}
315+
316+
317+#define FOURTEEN_ON_BITS ((1UL << 14) - 1)
318+#define FIFTY_ON_BITS ((1UL << 50) - 1)
319+
320+
321+static int
322+do_test (void)
323+{
324+
325+#if __WORDSIZE >= 64
326+
327+ /* This test assumes that none of the supported targets have an address
328+ bus wider than 50 bits, and that therefore allocations for sizes wider
329+ than 50 bits will fail. Here, we ensure that the assumption continues
330+ to be true in the future when we might have address buses wider than 50
331+ bits. */
332+
333+ struct rlimit alloc_size_limit
334+ = {
335+ .rlim_cur = FIFTY_ON_BITS,
336+ .rlim_max = FIFTY_ON_BITS
337+ };
338+
339+ setrlimit (RLIMIT_AS, &alloc_size_limit);
340+
341+#endif /* __WORDSIZE >= 64 */
342+
343+ DIAG_PUSH_NEEDS_COMMENT;
344+#if __GNUC_PREREQ (7, 0)
345+ /* GCC 7 warns about too-large allocations; here we want to test
346+ that they fail. */
347+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
348+#endif
349+
350+ /* Aligned memory allocation functions need to be tested up to alignment
351+ size equivalent to page size, which should be a power of 2. */
352+ pagesize = sysconf (_SC_PAGESIZE);
353+ TEST_VERIFY_EXIT (powerof2 (pagesize));
354+
355+ /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
356+ in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
357+
358+ We can expect that this range of allocation sizes will always lead to
359+ an allocation failure on both 64 and 32 bit targets, because:
360+
361+ 1. no currently supported 64-bit target has an address bus wider than
362+ 50 bits -- and (2^64 - 2^14) is much wider than that;
363+
364+ 2. on 32-bit targets, even though 2^32 is only 4 GB and potentially
365+ addressable, glibc itself is more than 2^14 bytes in size, and
366+ therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain
367+ available. */
368+
369+ for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++)
370+ {
371+ test_large_allocations (SIZE_MAX - i);
372+ test_large_aligned_allocations (SIZE_MAX - i);
373+ }
374+
375+#if __WORDSIZE >= 64
376+ /* On 64-bit targets, we need to test a much wider range of too-large
377+ sizes, so we test at intervals of (1 << 50) that allocation sizes
378+ ranging from SIZE_MAX down to (1 << 50) fail:
379+ The 14 MSBs are decremented starting from "all ON" going down to 1,
380+ the 50 LSBs are "all ON" and then "all OFF" during every iteration. */
381+ for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--)
382+ {
383+ size_t size = (msbs << 50) | FIFTY_ON_BITS;
384+ test_large_allocations (size);
385+ test_large_aligned_allocations (size);
386+
387+ size = msbs << 50;
388+ test_large_allocations (size);
389+ test_large_aligned_allocations (size);
390+ }
391+#endif /* __WORDSIZE >= 64 */
392+
393+ DIAG_POP_NEEDS_COMMENT;
394+
395+ return 0;
396+}
397+
398+
399+#include <support/test-driver.c>
400
401