glibc40/glibc-2.24-CVE-2018-6485.patch

87 lines
3.3 KiB
Diff
Raw Permalink Normal View History

From 8e448310d74b283c5cd02b9ed7fb997b47bf9b22 Mon Sep 17 00:00:00 2001
From: Arjun Shankar <arjun.is@lostca.se>
Date: Thu, 18 Jan 2018 16:47:06 +0000
Subject: [PATCH] Fix integer overflows in internal memalign and malloc
functions [BZ #22343]
When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT
and a requested size close to SIZE_MAX, it falls back to malloc code
(because the alignment of a block returned by malloc is sufficient to
satisfy the call). In this case, an integer overflow in _int_malloc leads
to posix_memalign incorrectly returning successfully.
Upon fixing this and writing a somewhat thorough regression test, it was
discovered that when posix_memalign is called with an alignment larger than
MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size
close to SIZE_MAX, a different integer overflow in _int_memalign leads to
posix_memalign incorrectly returning successfully.
Both integer overflows affect other memory allocation functions that use
_int_malloc (one affected malloc in x86) or _int_memalign as well.
This commit fixes both integer overflows. In addition to this, it adds a
regression test to guard against false successful allocations by the
following memory allocation functions when called with too-large allocation
sizes and, where relevant, various valid alignments:
malloc, realloc, calloc, reallocarray, memalign, posix_memalign,
aligned_alloc, valloc, and pvalloc.
---
ChangeLog | 10 ++
malloc/Makefile | 1 +
malloc/malloc.c | 30 +++--
malloc/tst-malloc-too-large.c | 253 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 286 insertions(+), 8 deletions(-)
create mode 100644 malloc/tst-malloc-too-large.c
diff --git a/malloc/malloc.c b/malloc/malloc.c
index f5aafd2..7889fb1 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1224,14 +1224,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
-/* Same, except also perform argument check */
-
-#define checked_request2size(req, sz) \
- if (REQUEST_OUT_OF_RANGE (req)) { \
- __set_errno (ENOMEM); \
- return 0; \
- } \
- (sz) = request2size (req);
+/* Same, except also perform an argument and result check. First, we check
+ that the padding done by request2size didn't result in an integer
+ overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting
+ size isn't so large that a later alignment would lead to another integer
+ overflow. */
+#define checked_request2size(req, sz) \
+({ \
+ (sz) = request2size (req); \
+ if (((sz) < (req)) \
+ || REQUEST_OUT_OF_RANGE (sz)) \
+ { \
+ __set_errno (ENOMEM); \
+ return 0; \
+ } \
+})
/*
--------------- Physical chunk operations ---------------
@@ -4678,6 +4685,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
*/
+ /* Check for overflow. */
+ if (nb > SIZE_MAX - alignment - MINSIZE)
+ {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
/* Call malloc with worst case padding to hit alignment. */
m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
--
2.9.3