aboutsummaryrefslogtreecommitdiff
path: root/malloc/malloc.c
diff options
context:
space:
mode:
authorArjun Shankar <arjun.is@lostca.se>2018-01-18 16:47:06 +0000
committerArjun Shankar <arjun@redhat.com>2018-01-18 17:55:45 +0100
commit8e448310d74b283c5cd02b9ed7fb997b47bf9b22 (patch)
treea5cb99be6773177cf14683cbf10ecbc34a7dc82c /malloc/malloc.c
parent80647883cf5847c8b6b0197e9703eb04222496b6 (diff)
downloadglibc-8e448310d74b283c5cd02b9ed7fb997b47bf9b22.zip
glibc-8e448310d74b283c5cd02b9ed7fb997b47bf9b22.tar.gz
glibc-8e448310d74b283c5cd02b9ed7fb997b47bf9b22.tar.bz2
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.
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r--malloc/malloc.c30
1 files changed, 22 insertions, 8 deletions
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));