Skip to content

Commit 606c812

Browse files
howletttorvalds
authored andcommitted
mm/mmap: Fix error path in do_vmi_align_munmap()
The error unrolling was leaving the VMAs detached in many cases and leaving the locked_vm statistic altered, and skipping the unrolling entirely in the case of the vma tree write failing. Fix the error path by re-attaching the detached VMAs and adding the necessary goto for the failed vma tree write, and fix the locked_vm statistic by only updating after the vma tree write succeeds. Fixes: 763ecb0 ("mm: remove the vma linked list") Reported-by: Vegard Nossum <vegard.nossum@oracle.com> Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 1b29d27 commit 606c812

File tree

1 file changed

+17
-20
lines changed

1 file changed

+17
-20
lines changed

mm/mmap.c

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,21 +2318,6 @@ int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
23182318
return __split_vma(vmi, vma, addr, new_below);
23192319
}
23202320

2321-
static inline int munmap_sidetree(struct vm_area_struct *vma,
2322-
struct ma_state *mas_detach)
2323-
{
2324-
vma_start_write(vma);
2325-
mas_set_range(mas_detach, vma->vm_start, vma->vm_end - 1);
2326-
if (mas_store_gfp(mas_detach, vma, GFP_KERNEL))
2327-
return -ENOMEM;
2328-
2329-
vma_mark_detached(vma, true);
2330-
if (vma->vm_flags & VM_LOCKED)
2331-
vma->vm_mm->locked_vm -= vma_pages(vma);
2332-
2333-
return 0;
2334-
}
2335-
23362321
/*
23372322
* do_vmi_align_munmap() - munmap the aligned region from @start to @end.
23382323
* @vmi: The vma iterator
@@ -2354,6 +2339,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
23542339
struct maple_tree mt_detach;
23552340
int count = 0;
23562341
int error = -ENOMEM;
2342+
unsigned long locked_vm = 0;
23572343
MA_STATE(mas_detach, &mt_detach, 0, 0);
23582344
mt_init_flags(&mt_detach, vmi->mas.tree->ma_flags & MT_FLAGS_LOCK_MASK);
23592345
mt_set_external_lock(&mt_detach, &mm->mmap_lock);
@@ -2399,9 +2385,13 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
23992385
if (error)
24002386
goto end_split_failed;
24012387
}
2402-
error = munmap_sidetree(next, &mas_detach);
2403-
if (error)
2404-
goto munmap_sidetree_failed;
2388+
vma_start_write(next);
2389+
mas_set_range(&mas_detach, next->vm_start, next->vm_end - 1);
2390+
if (mas_store_gfp(&mas_detach, next, GFP_KERNEL))
2391+
goto munmap_gather_failed;
2392+
vma_mark_detached(next, true);
2393+
if (next->vm_flags & VM_LOCKED)
2394+
locked_vm += vma_pages(next);
24052395

24062396
count++;
24072397
#ifdef CONFIG_DEBUG_VM_MAPLE_TREE
@@ -2447,10 +2437,12 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
24472437
}
24482438
#endif
24492439
/* Point of no return */
2440+
error = -ENOMEM;
24502441
vma_iter_set(vmi, start);
24512442
if (vma_iter_clear_gfp(vmi, start, end, GFP_KERNEL))
2452-
return -ENOMEM;
2443+
goto clear_tree_failed;
24532444

2445+
mm->locked_vm -= locked_vm;
24542446
mm->map_count -= count;
24552447
/*
24562448
* Do not downgrade mmap_lock if we are next to VM_GROWSDOWN or
@@ -2480,9 +2472,14 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
24802472
validate_mm(mm);
24812473
return downgrade ? 1 : 0;
24822474

2475+
clear_tree_failed:
24832476
userfaultfd_error:
2484-
munmap_sidetree_failed:
2477+
munmap_gather_failed:
24852478
end_split_failed:
2479+
mas_set(&mas_detach, 0);
2480+
mas_for_each(&mas_detach, next, end)
2481+
vma_mark_detached(next, false);
2482+
24862483
__mt_destroy(&mt_detach);
24872484
start_split_failed:
24882485
map_count_exceeded:

0 commit comments

Comments
 (0)