From 939d4b1ccc068d96bb8d10ea705f9bd464e53807 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Fri, 4 Aug 2023 08:27:24 -0700 Subject: [PATCH] BACKPORT: FROMGIT: mm: move vma locking out of vma_prepare and dup_anon_vma vma_prepare() is currently the central place where vmas are being locked before vma_complete() applies changes to them. While this is convenient, it also obscures vma locking and makes it harder to follow the locking rules. Move vma locking out of vma_prepare() and take vma locks explicitly at the locations where vmas are being modified. Move vma locking and replace it with an assertion inside dup_anon_vma() to further clarify the locking pattern inside vma_merge(). Link: https://lkml.kernel.org/r/20230804152724.3090321-7-surenb@google.com Suggested-by: Linus Torvalds Suggested-by: Liam R. Howlett Signed-off-by: Suren Baghdasaryan Cc: Jann Horn Signed-off-by: Andrew Morton (cherry picked from commit b1985ca5e7e6464d205a98a78cca229224346c21 https: //git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-unstable) [surenb: skip changes in vma_prepare() which does not exist, skip changes in vma_merge() since required locks are already in __vma_adjust(), skip change in dup_anon_vma() since required locks are already in place, skip unnecessary lock in do_brk_flags()] Bug: 293665307 Change-Id: I99261aa1db3bec73795e63c333768bc68da8045c Signed-off-by: Suren Baghdasaryan --- mm/mmap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index bfe139bf94af..bd2140cfcf36 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -531,6 +531,7 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, struct file *file = vma->vm_file; bool remove_next = false; + vma_start_write(vma); if (next && (vma != next) && (end == next->vm_end)) { remove_next = true; /* Lock the VMA before removing it */ @@ -539,7 +540,6 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, int error; anon_vma = next->anon_vma; - vma_start_write(vma); vma->anon_vma = anon_vma; error = anon_vma_clone(vma, next); if (error) @@ -556,7 +556,6 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, if (mas_preallocate(mas, vma, GFP_KERNEL)) goto nomem; - vma_start_write(vma); vma_adjust_trans_huge(vma, start, end, 0); if (file) { @@ -2433,6 +2432,9 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); + vma_start_write(vma); + vma_start_write(new); + if (new_below) err = vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff + ((addr - new->vm_start) >> PAGE_SHIFT), new);