FROMLIST: mm/mmap: write-lock VMAs in vma_adjust

vma_adjust modifies a VMA and possibly its neighbors. Write-lock them
before making the modifications.

Signed-off-by: Suren Baghdasaryan <surenb@google.com>

Link: https://lore.kernel.org/all/20230109205336.3665937-21-surenb@google.com/
[surenb: using older v1 of patchset due to __vma_adjust() being removed
in 6.2-rc4]
[surenb: minor fixes in next_next locking inside __vma_adjust]

Bug: 161210518
Change-Id: I9ab2f88c82a7071fe2f1a14c51a2e6f1b6196681
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan 2023-01-09 12:53:15 -08:00 committed by Carlos Llamas
parent 998ec9f54d
commit 57b3f8a5ab

View file

@ -618,6 +618,12 @@ nomem:
* The following helper function should be used when such adjustments
* are necessary. The "insert" vma (if any) is to be inserted
* before we drop the necessary locks.
* 'expand' vma is always locked before it's passed to __vma_adjust()
* from vma_merge() because vma should not change from the moment
* can_vma_merge_{before|after} decision is made.
* 'insert' vma is used only by __split_vma() and it's always a brand
* new vma which is not yet added into mm's vma tree, therefore no need
* to lock it.
*/
int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
@ -637,6 +643,10 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
MA_STATE(mas, &mm->mm_mt, start, end - 1);
struct vm_area_struct *exporter = NULL, *importer = NULL;
vma_start_write(vma);
if (next)
vma_start_write(next);
if (next && !insert) {
if (end >= next->vm_end) {
/*
@ -666,8 +676,11 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
* remove_next == 1 is case 1 or 7.
*/
remove_next = 1 + (end > next->vm_end);
if (remove_next == 2)
if (remove_next == 2) {
next_next = find_vma(mm, next->vm_end);
if (next_next)
vma_start_write(next_next);
}
VM_WARN_ON(remove_next == 2 &&
end != next_next->vm_end);