Re: [PATCH 01/10] mm/vma: don't leak the commit charge on mmap failure

From: Lance Yang

Date: Sun Oct 18 2026 - 02:06:38 EST



On Thu, Oct 15, 2026 at 06:07:07PM +0200, David Hildenbrand (Arm) wrote:
>From: Josef Bacik <josef@xxxxxxxxxxxxxx>
>
>When an accountable mapping replaces existing mappings (MAP_FIXED),
>__mmap_setup() only charges the difference between the size of the new
>mapping and the VM_ACCOUNT pages it replaces. It then zeroes
>vms->nr_accounted so that unmapping the old VMAs does not return their
>charge, which now backs the new mapping.
>
>If the operation fails after that point, the error path returns
>map->charged, i.e. only the difference. By then vms_clean_up_area() has
>zapped the page tables and closed the old VMAs, so
>vms_abort_munmap_vmas() cannot reattach them. It leaves a gap and
>finishes the unmap with vms_complete_munmap_vmas(), which uncharges
>vms->nr_accounted == 0 pages. The old VMAs are gone, the new one was
>never created, and the charge of the old ones is never returned, not
>even when the process exits.
>
>No privilege is needed to hit this, only a file whose mmap hook fails,
>for example a socket (sock_no_mmap() returns -ENODEV):
>
> p = mmap(NULL, len, PROT_READ | PROT_WRITE,
> MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> mmap(p, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
> socket_fd, 0);
>
>Every iteration adds len to Committed_AS for good. With
>vm.overcommit_memory=2 this lets any user make all further accountable
>allocations in the system fail with -ENOMEM.
>
>Once the new mapping has taken over the charge of the mappings it
>replaces, it owns the charge for all of its pages. Record that in
>map->charged, so that the error path returns all of it.
>
>A failure in __mmap_setup() itself is not affected: it happens before
>the charge is taken over and the old VMAs are reattached with their
>charge intact.
>
>Original fix generated by an LLM and sent in private by Josef.
>
>Fixes: 4f87153e82c4 ("mm: change failure of MAP_FIXED to restoring the gap on failure")
>Cc: stable@xxxxxxxxxxxxxxx
>Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
>Reviewed-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
>[ david: call variable "uncharged" and make it const, adjust/simplify comments ]
>Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
>---

Reviewed-by: Lance Yang <lance.yang@xxxxxxxxx>