Re: [PATCH] mm/vmalloc: reject overflowing vm_map_ram page counts

From: Shubhang

Date: Fri Oct 23 2026 - 02:12:17 EST


Hi Andrew,

On Thu, 22 Oct 2026, Andrew Morton wrote:

On Thu, 22 Oct 2026 16:35:20 -0700 "Shubhang Kaushik (Ampere)" <sh@xxxxxxxxxx> wrote:

vm_map_ram() converts its unsigned int page count to an unsigned long
byte size without checking for overflow.

On 32-bit kernels, a count greater than ULONG_MAX >> PAGE_SHIFT wraps
the byte size. vm_map_ram() passes that size to both alloc_vmap_area()
and vmap_pages_range(), so it can allocate and map only the wrapped
number of pages while returning success for the original larger request.

For example, with 4 KiB pages, a count of 1048577 produces a
PAGE_SIZE byte size after wrapping, allowing a one-page mapping.

Reject page counts whose byte size cannot be represented.

Thanks,

When fixing a bug, please always fully describe the worst-case
userspace-visible runtime effects of that bug.

AI tells me:

: On 32-bit kernels an overflowing count can currently cause vm_map_ram()
: to return a non-NULL pointer to a mapping smaller than requested. The
: patch makes such requests fail before allocating anything.
:
: However, I haven't identified a kernel caller through which
: userspace can trigger this condition. The callers I've examined
: appear to constrain the page count appropriately.
:
: So I'd describe this as hardening against invalid kernel API
: arguments rather than fixing a demonstrated userspace-visible
: failure.


Also,

: On 64-bit kernels count is an unsigned int, so the comparison against
: ULONG_MAX >> PAGE_SHIFT is always false. Clang W=1 can warn about
: this, potentially breaking WERROR builds.
:
: Could we instead use:
:
: if (check_mul_overflow((unsigned long)count, PAGE_SIZE, &size))
: return NULL;


Thanks, agreed. I'll respin this using check_mul_overflow().

I'll also expand the changelog to describe the failure mode. On a 32-bit
kernel, converting a requested page count to a byte size can overflow. vm_map_ram() can then return success after mapping fewer pages than requested. If a caller later accesses the returned address as if all requested pages were mapped, an access to one of the omitted pages can fault. If another vmalloc mapping occupies that virtual address, the access can instead reach unrelated kernel memory. Userspace can observe this as a failed operation or a kernel oops/panic; in the worst case, the erroneous access can corrupt kernel memory.

I found that udmabuf can pass a userspace-controlled page count to
vm_map_ram() when a DMA-BUF importer invokes its vmap operation. However, for the same oversized count, udmabuf also truncates both the advertised DMA-BUF size and the byte length used for its SG table.
That said, I have not found a current in-tree importer that accesses the returned mapping as if it covered all of the originally requested pages.

Regards,
Shubhang Kaushik