wok-4.x view glibc/stuff/patches/glibc-2.22-CVE-2018-6485.patch @ rev 12476

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