memalign: reinstate alignment overflow check (CVE-2026-0861)

The change to cap valid sizes to PTRDIFF_MAX inadvertently dropped the
overflow check for alignment in memalign functions, _mid_memalign and
_int_memalign.  Reinstate the overflow check in _int_memalign, aligned
with the PTRDIFF_MAX change since that is directly responsible for the
CVE.  The missing _mid_memalign check is not relevant (and does not have
a security impact) and may need a different approach to fully resolve,
so it has been omitted.

CVE-Id: CVE-2026-0861
Vulnerable-Commit: 9bf8e29ca1
Reported-by: Igor Morgenstern, Aisle Research
Fixes: BZ #33796
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
This commit is contained in:
Siddhesh Poyarekar 2026-01-15 06:06:40 -05:00
parent 289d3283b6
commit c9188d3337
2 changed files with 7 additions and 10 deletions

View File

@ -4703,14 +4703,17 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
{ {
mchunkptr p, newp; mchunkptr p, newp;
if (bytes > PTRDIFF_MAX) if (bytes > PTRDIFF_MAX || alignment > PTRDIFF_MAX)
{ {
__set_errno (ENOMEM); __set_errno (ENOMEM);
return NULL; return NULL;
} }
size_t nb = checked_request2size (bytes); size_t nb = checked_request2size (bytes);
/* Call malloc with worst case padding to hit alignment. */ /* Call malloc with worst case padding to hit alignment. ALIGNMENT is a
power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of
space to add MINSIZE and whatever checked_request2size adds to BYTES to
get NB. Consequently, total below also does not overflow. */
void *m = _int_malloc (av, nb + alignment + MINSIZE); void *m = _int_malloc (av, nb + alignment + MINSIZE);
if (m == NULL) if (m == NULL)

View File

@ -152,7 +152,6 @@ test_large_allocations (size_t size)
} }
static long pagesize;
/* This function tests the following aligned memory allocation functions /* This function tests the following aligned memory allocation functions
using several valid alignments and precedes each allocation test with a using several valid alignments and precedes each allocation test with a
@ -171,8 +170,8 @@ test_large_aligned_allocations (size_t size)
/* All aligned memory allocation functions expect an alignment that is a /* All aligned memory allocation functions expect an alignment that is a
power of 2. Given this, we test each of them with every valid power of 2. Given this, we test each of them with every valid
alignment from 1 thru PAGESIZE. */ alignment for the type of ALIGN, i.e. until it wraps to 0. */
for (align = 1; align <= pagesize; align *= 2) for (align = 1; align > 0; align <<= 1)
{ {
test_setup (); test_setup ();
#if __GNUC_PREREQ (7, 0) #if __GNUC_PREREQ (7, 0)
@ -265,11 +264,6 @@ do_test (void)
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
#endif #endif
/* Aligned memory allocation functions need to be tested up to alignment
size equivalent to page size, which should be a power of 2. */
pagesize = sysconf (_SC_PAGESIZE);
TEST_VERIFY_EXIT (powerof2 (pagesize));
/* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.