Skip to content

Commit 6c28ca6

Browse files
howlettakpm00
authored andcommitted
mmap: fix do_brk_flags() modifying obviously incorrect VMAs
Add more sanity checks to the VMA that do_brk_flags() will expand. Ensure the VMA matches basic merge requirements within the function before calling can_vma_merge_after(). Drop the duplicate checks from vm_brk_flags() since they will be enforced later. The old code would expand file VMAs on brk(), which is functionally wrong and also dangerous in terms of locking because the brk() path isn't designed for file VMAs and therefore doesn't lock the file mapping. Checking can_vma_merge_after() ensures that new anonymous VMAs can't be merged into file VMAs. See https://lore.kernel.org/linux-mm/CAG48ez1tJZTOjS_FjRZhvtDA-STFmdw8PEizPDwMGFd_ui0Nrw@mail.gmail.com/ Link: https://lkml.kernel.org/r/[email protected] Fixes: 2e7ce7d ("mm/mmap: change do_brk_flags() to expand existing VMA and add do_brk_munmap()") Signed-off-by: Liam R. Howlett <[email protected]> Suggested-by: Jann Horn <[email protected]> Cc: Jason A. Donenfeld <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: SeongJae Park <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Yu Zhao <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 630dc25 commit 6c28ca6

File tree

1 file changed

+3
-8
lines changed

1 file changed

+3
-8
lines changed

mm/mmap.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,9 +2948,9 @@ static int do_brk_flags(struct ma_state *mas, struct vm_area_struct *vma,
29482948
* Expand the existing vma if possible; Note that singular lists do not
29492949
* occur after forking, so the expand will only happen on new VMAs.
29502950
*/
2951-
if (vma &&
2952-
(!vma->anon_vma || list_is_singular(&vma->anon_vma_chain)) &&
2953-
((vma->vm_flags & ~VM_SOFTDIRTY) == flags)) {
2951+
if (vma && vma->vm_end == addr && !vma_policy(vma) &&
2952+
can_vma_merge_after(vma, flags, NULL, NULL,
2953+
addr >> PAGE_SHIFT, NULL_VM_UFFD_CTX, NULL)) {
29542954
mas_set_range(mas, vma->vm_start, addr + len - 1);
29552955
if (mas_preallocate(mas, vma, GFP_KERNEL))
29562956
return -ENOMEM;
@@ -3037,11 +3037,6 @@ int vm_brk_flags(unsigned long addr, unsigned long request, unsigned long flags)
30373037
goto munmap_failed;
30383038

30393039
vma = mas_prev(&mas, 0);
3040-
if (!vma || vma->vm_end != addr || vma_policy(vma) ||
3041-
!can_vma_merge_after(vma, flags, NULL, NULL,
3042-
addr >> PAGE_SHIFT, NULL_VM_UFFD_CTX, NULL))
3043-
vma = NULL;
3044-
30453040
ret = do_brk_flags(&mas, vma, addr, len, flags);
30463041
populate = ((mm->def_flags & VM_LOCKED) != 0);
30473042
mmap_write_unlock(mm);

0 commit comments

Comments
 (0)