[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240806212808.1885309-3-pedro.falcato@gmail.com>
Date: Tue, 6 Aug 2024 22:28:03 +0100
From: Pedro Falcato <pedro.falcato@...il.com>
To: Andrew Morton <akpm@...ux-foundation.org>,
"Liam R. Howlett" <Liam.Howlett@...cle.com>,
Vlastimil Babka <vbabka@...e.cz>,
Lorenzo Stoakes <lorenzo.stoakes@...cle.com>
Cc: linux-mm@...ck.org,
linux-kernel@...r.kernel.org,
oliver.sang@...el.com,
torvalds@...ux-foundation.org,
jeffxu@...gle.com,
Michael Ellerman <mpe@...erman.id.au>,
Pedro Falcato <pedro.falcato@...il.com>
Subject: [PATCH 2/7] mm/munmap: Replace can_modify_mm with can_modify_vma
We were doing an extra mmap tree traversal just to check if the entire
range is modifiable. This can be done when we iterate through the VMAs
instead.
Note that this removes the arch_unmap() callsites and therefore isn't
quite ready for Proper(tm) upstreaming.
Signed-off-by: Pedro Falcato <pedro.falcato@...il.com>
---
mm/mmap.c | 36 +++++++++++++-----------------------
1 file changed, 13 insertions(+), 23 deletions(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index d0dfc85b209..b88666f618b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2660,6 +2660,12 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count)
goto map_count_exceeded;
+ /* Don't bother splitting the VMA if we can't unmap it anyway */
+ if (!can_modify_vma(vma)) {
+ error = -EPERM;
+ goto start_split_failed;
+ }
+
error = __split_vma(vmi, vma, start, 1);
if (error)
goto start_split_failed;
@@ -2671,6 +2677,11 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
*/
next = vma;
do {
+ if (!can_modify_vma(vma)) {
+ error = -EPERM;
+ goto modify_vma_failed;
+ }
+
/* Does it split the end? */
if (next->vm_end > end) {
error = __split_vma(vmi, next, end, 0);
@@ -2763,6 +2774,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
__mt_destroy(&mt_detach);
return 0;
+modify_vma_failed:
clear_tree_failed:
userfaultfd_error:
munmap_gather_failed:
@@ -2808,17 +2820,6 @@ int do_vmi_munmap(struct vma_iterator *vmi, struct mm_struct *mm,
if (end == start)
return -EINVAL;
- /*
- * Check if memory is sealed before arch_unmap.
- * Prevent unmapping a sealed VMA.
- * can_modify_mm assumes we have acquired the lock on MM.
- */
- if (unlikely(!can_modify_mm(mm, start, end)))
- return -EPERM;
-
- /* arch_unmap() might do unmaps itself. */
- arch_unmap(mm, start, end);
-
/* Find the first overlapping VMA */
vma = vma_find(vmi, end);
if (!vma) {
@@ -3229,18 +3230,7 @@ int do_vma_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
unsigned long start, unsigned long end, struct list_head *uf,
bool unlock)
{
- struct mm_struct *mm = vma->vm_mm;
-
- /*
- * Check if memory is sealed before arch_unmap.
- * Prevent unmapping a sealed VMA.
- * can_modify_mm assumes we have acquired the lock on MM.
- */
- if (unlikely(!can_modify_mm(mm, start, end)))
- return -EPERM;
-
- arch_unmap(mm, start, end);
- return do_vmi_align_munmap(vmi, vma, mm, start, end, uf, unlock);
+ return do_vmi_align_munmap(vmi, vma, vma->vm_mm, start, end, uf, unlock);
}
/*
--
2.46.0
Powered by blists - more mailing lists