[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