[PATCH] mm/mremap: allow undocumented mremap() shrink behaviour

From: Lorenzo Stoakes
Date: Sun Jul 20 2025 - 06:41:48 EST


It turns out that, in apparent contradiction to the man page, and at odds
with every other mremap() operation - we are allowed to specify an input
addr, old_len range that spans any number of VMAs and any number of gaps,
as long as we shrink that range to the point at which the new range spans
only one.

In order to accommodate this, adjust the remap validity check to account
for this.

Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx>
Reported-by: kernel test robot <oliver.sang@xxxxxxxxx>
Closes: https://lore.kernel.org/oe-lkp/202507201002.69144b74-lkp@xxxxxxxxx
---
mm/mremap.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index 20844fb91755..11a8321a90b8 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1339,11 +1339,18 @@ static int remap_is_valid(struct vma_remap_struct *vrm)
(vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)))
return -EINVAL;

+ /*
+ * We permit crossing of boundaries for the range being unmapped due to
+ * a shrink.
+ */
+ if (vrm->remap_type == MREMAP_SHRINK)
+ old_len = new_len;
+
/* We can't remap across vm area boundaries */
if (old_len > vma->vm_end - addr)
return -EFAULT;

- if (new_len <= old_len)
+ if (new_len == old_len)
return 0;

/* Need to be careful about a growing mapping */
--
2.50.1