From: Hui Peng <benquike@gmail.com>
To: akpm@linux-foundation.org, liam@infradead.org, ljs@kernel.org
Cc: vbabka@kernel.org, jannh@google.com, pfalcato@suse.de,
bgeffon@google.com, linux-mm@kvack.org,
linux-kernel@vger.kernel.org
Subject: [PATCH] mm/mremap: account unmoved locked pages in dontunmap_complete()
Date: Sat, 19 Sep 2026 21:06:12 +0000 [thread overview]
Message-ID: <20260919210612.3028241-1-benquike@gmail.com> (raw)
When MREMAP_DONTUNMAP is performed on a VM_LOCKED VMA,
dontunmap_complete() clears VMA_LOCKED_MASK on the entire source VMA
(vrm->vma) before vrm_stat_account() runs. This assumes that the entire
source VMA was moved into a distinct destination VMA (new_vma != vma) of
equal size, transferring the VM_LOCKED accounting 1:1 from vma to
new_vma.
However, two cases violate this assumption:
1. Partial MREMAP_DONTUNMAP on a multi-page VM_LOCKED VMA (vrm->old_len
< vma->vm_end - vma->vm_start): vma_clear_flags_mask(vma,
VMA_LOCKED_MASK) clears VM_LOCKED on the entire source VMA of size
vma_pages(vma), while new_vma only inherits VM_LOCKED for
vrm->old_len >> PAGE_SHIFT pages. The remaining unmoved pages in vma
lose VM_LOCKED without decrementing mm->locked_vm.
2. Self-merge in copy_vma() (new_vma == vma, when new_addr is
immediately adjacent to vma): copy_vma() expands vma by vrm->new_len,
and dontunmap_complete() then clears VMA_LOCKED_MASK on the combined
VMA. All originally locked pages lose VM_LOCKED without decrementing
mm->locked_vm.
In both cases, subsequent munmap() of the VMAs sees VM_LOCKED cleared
and does not decrement mm->locked_vm, permanently leaking mm->locked_vm
until process exit and allowing unprivileged processes to exhaust
RLIMIT_MEMLOCK.
Fix this in dontunmap_complete() by subtracting the number of pages that
lose VM_LOCKED from current->mm->locked_vm before clearing
VMA_LOCKED_MASK.
Fixes: e346b3813067 ("mm/mremap: add MREMAP_DONTUNMAP to mremap()")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
mm/mremap.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/mm/mremap.c b/mm/mremap.c
index 7c368440fafe..ff794e24f78f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1335,6 +1335,16 @@ static void dontunmap_complete(struct vma_remap_struct *vrm,
unsigned long old_start = vma->vm_start;
unsigned long old_end = vma->vm_end;
+ if (vma_test(vma, VMA_LOCKED_BIT)) {
+ unsigned long unl_pages = vma_pages(vma);
+
+ if (new_vma != vma)
+ unl_pages -= vrm->old_len >> PAGE_SHIFT;
+ else
+ unl_pages -= vrm->new_len >> PAGE_SHIFT;
+ current->mm->locked_vm -= unl_pages;
+ }
+
/* We always clear VMA_LOCKED[ONFAULT]_BIT on the old VMA. */
vma_clear_flags_mask(vma, VMA_LOCKED_MASK);
--
2.55.0.1082.g2b9226bbc0-goog
next reply other threads:[~2026-09-19 21:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 21:06 Hui Peng [this message]
2026-09-20 10:15 ` [PATCH] mm/mremap: account unmoved locked pages in dontunmap_complete() Lorenzo Stoakes (ARM)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260919210612.3028241-1-benquike@gmail.com \
--to=benquike@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=bgeffon@google.com \
--cc=jannh@google.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=pfalcato@suse.de \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.