[PATCH] memalign: Add alignment overflow check (CVE-2026-0861)
Wilco Dijkstra
Wilco.Dijkstra@arm.com
Thu Jan 15 08:00:00 GMT 2026
Hi Siddhesh,
Firstly it seems best to move the code that ensures alignment is a power
of 2 into __libc_memalign since that is the only case that needs it - at that
point you enter _mid_memalign with an alignment that is a power of 2
(whether we want to allow 0 as an alignment doesn't matter since we will
call __libc_malloc for all small alignments - also note the alignment < MINSIZE
check is redundant since that is typically the next larger alignment anyway).
+ if (!powerof2 (alignment))
+ alignment = (size_t) 2 << (sizeof (size_t) * 8
+ - __builtin_clzl (alignment - 1) - 1);
+
+ if (__glibc_unlikely (alignment == 0))
Why not use 2 << (__builtin_clzl (1) - __builtin_clzl (alignment))? And the
overflow check should be inside the first if since we're not checking alignment
for zero.
The total allocation is:
checked_request2size (checked_request2size (bytes) + alignment + MINSIZE)
Each checked_request2size can add at most MINSIZE to the total (depending
on the size) and limits its *input* to PTRDIFF_MAX. So checking overflow
of bytes + alignment + MINSIZE is still incorrect.
>From the formula we can conclude that alignment == PTRDIFF_MAX + 1
should always return NULL and set ENOMEM. Thus the trivial fix is:
if (bytes > PTRDIFF_MAX || alignment > PTRDIFF_MAX)
{
__set_errno (ENOMEM);
return NULL;
}
at the start of _int_memalign. That way we don't do a complex overflow check
in a different function (and it doesn't go wrong if _int_memalign changes).
Cheers,
Wilco
More information about the Libc-alpha
mailing list