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 <torvalds@linuxfoundation.org>
Suggested-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Cc: Jann Horn <jannh@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

(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 <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan 2023-08-04 08:27:24 -07:00
parent 0f0b09c02c
commit 939d4b1ccc

View File

@ -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);