Skip to content

Commit 6b7339f

Browse files
kiryltorvalds
authored andcommitted
mm: avoid setting up anonymous pages into file mapping
Reading page fault handler code I've noticed that under right circumstances kernel would map anonymous pages into file mappings: if the VMA doesn't have vm_ops->fault() and the VMA wasn't fully populated on ->mmap(), kernel would handle page fault to not populated pte with do_anonymous_page(). Let's change page fault handler to use do_anonymous_page() only on anonymous VMA (->vm_ops == NULL) and make sure that the VMA is not shared. For file mappings without vm_ops->fault() or shred VMA without vm_ops, page fault on pte_none() entry would lead to SIGBUS. Signed-off-by: Kirill A. Shutemov <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Willy Tarreau <[email protected]> Cc: [email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 883a2df commit 6b7339f

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

mm/memory.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,6 +2670,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
26702670

26712671
pte_unmap(page_table);
26722672

2673+
/* File mapping without ->vm_ops ? */
2674+
if (vma->vm_flags & VM_SHARED)
2675+
return VM_FAULT_SIGBUS;
2676+
26732677
/* Check if we need to add a guard page to the stack */
26742678
if (check_stack_guard_page(vma, address) < 0)
26752679
return VM_FAULT_SIGSEGV;
@@ -3099,6 +3103,9 @@ static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
30993103
- vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
31003104

31013105
pte_unmap(page_table);
3106+
/* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
3107+
if (!vma->vm_ops->fault)
3108+
return VM_FAULT_SIGBUS;
31023109
if (!(flags & FAULT_FLAG_WRITE))
31033110
return do_read_fault(mm, vma, address, pmd, pgoff, flags,
31043111
orig_pte);
@@ -3244,13 +3251,12 @@ static int handle_pte_fault(struct mm_struct *mm,
32443251
barrier();
32453252
if (!pte_present(entry)) {
32463253
if (pte_none(entry)) {
3247-
if (vma->vm_ops) {
3248-
if (likely(vma->vm_ops->fault))
3249-
return do_fault(mm, vma, address, pte,
3250-
pmd, flags, entry);
3251-
}
3252-
return do_anonymous_page(mm, vma, address,
3253-
pte, pmd, flags);
3254+
if (vma->vm_ops)
3255+
return do_fault(mm, vma, address, pte, pmd,
3256+
flags, entry);
3257+
3258+
return do_anonymous_page(mm, vma, address, pte, pmd,
3259+
flags);
32543260
}
32553261
return do_swap_page(mm, vma, address,
32563262
pte, pmd, flags, entry);

0 commit comments

Comments
 (0)