[PATCH v2 0/3] mm/vmalloc: stop truncating byte counts derived from nr_pages

From: Artem Lytkin

Date: Thu Jul 30 2026 - 05:11:01 EST


Andrew asked for a v2 of the nr_pages widening, rebased on mm-new, with
the changelog clarified on what has actually been observed.

The widening reverts the two casts added by the patches I sent on 25
July, so it needs those in the tree first, and they are not in mm-new,
mm-unstable or mm-hotfixes-unstable today. They are here as 1/3 and 2/3 so
that the series applies and Sashiko can chew on it. 2/3 is byte for byte
what I sent; 1/3 has one corrected sentence in its changelog and the same
one-line diff.

Keeping the three separate is deliberate. 1/3 is a one-line fix for a
v7.2 regression and carries a Fixes: tag, so it is the part that wants to
go in on its own. 3/3 is a type change across the file.

On what has been seen in practice, since v1 of 3/3 read as though the bug
had been hit: it has not. There is no report behind any of this, I found
it reading the code. What is reachable is the 4 GiB truncation in
vread_iter(), which needs a machine with more than 4 GiB of memory and
nothing else, and makes /proc/kcore return zeros for such an area while
reporting a successful read. The vrealloc() case has the same cause but
stays latent, no in-tree caller grows an allocation that far. The rest is
unexercised, and 3/3 now separates the two thresholds instead of lumping
them together: 2^32 pages, where the field truncates, is 16 TiB and out
of reach of any hardware, while 2^31, where the plain int page indexes
break, is 8 TiB and only out of reach because nothing asks for an area
that large.

Changes in v2:
- rebased on mm-new
- 3/3: the changelog separates what is reachable, what is latent and what
is merely unexercised, and answers the 16 TiB question directly
- 3/3: the note on the mapping path no longer calls the int *nr cursor a
cap, since it is an overflow and not a bound, and no longer claims that
every user outside mm/vmalloc.c only indexes or shifts the count. Three
of them pass it to a narrower parameter, which is now named
- 1/3: dropped the claim that alloc_large_system_hash() cannot reach a
4 GiB area. Its cap is a sixteenth of memory, so it can on a 64 GiB
machine, just not without an explicit table size on the command line

v1 of 3/3:
https://lore.kernel.org/linux-mm/20260729175708.7074-1-iprintercanon@xxxxxxxxx/
1/3 and 2/3 as first posted:
https://lore.kernel.org/linux-mm/20260725132201.88279-1-iprintercanon@xxxxxxxxx/

Checked on x86-64: vmlinux and modules build clean, and mm/vmalloc.c plus
every file that touches vm_struct::nr_pages are clean at W=1, with
HAVE_ARCH_HUGE_VMALLOC, NUMA, KEXEC_HANDOVER, DEBUG_KMEMLEAK,
DMA_API_DEBUG and PROC_KCORE enabled. sizeof(struct vm_struct) measured
against the real headers: 72 bytes before and after with
HAVE_ARCH_HUGE_VMALLOC=n, 72 to 80 with it enabled, both sizes inside the
kmalloc-96 bucket that __get_vm_area_node() already allocates from.

Artem Lytkin (3):
mm/vmalloc: fix 32-bit truncation of the area size in vread_iter()
mm/vmalloc: fix 32-bit truncation in the vrealloc() grow-in-place
check
mm/vmalloc: make vm_struct.nr_pages an unsigned long

include/linux/vmalloc.h | 2 +-
mm/vmalloc.c | 58 ++++++++++++++++++++---------------------
2 files changed, 29 insertions(+), 31 deletions(-)


base-commit: eee677bbc48890b2bcaa42ea7942478302937a09
--
2.43.0