Skip to content

Commit

Permalink
userfaultfd: shmem: handle coredumping in handle_userfault()
Browse files Browse the repository at this point in the history
Anon and hugetlbfs handle FOLL_DUMP set by get_dump_page() internally to
__get_user_pages().

shmem as opposed has no special FOLL_DUMP handling there so
handle_mm_fault() is invoked without mmap_sem and ends up calling
handle_userfault() that isn't expecting to be invoked without mmap_sem
held.

This makes handle_userfault() fail immediately if invoked through
shmem_vm_ops->fault during coredumping and solves the problem.

The side effect is a BUG_ON with no lock held triggered by the
coredumping process which exits.  Only 4.11 is affected, pre-4.11 anon
memory holes are skipped in __get_user_pages by checking FOLL_DUMP
explicitly against empty pagetables (mm/gup.c:no_page_table()).

It's zero cost as we already had a check for current->flags to prevent
futex to trigger userfaults during exit (PF_EXITING).

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Andrea Arcangeli <[email protected]>
Reported-by: "Dr. David Alan Gilbert" <[email protected]>
Cc: <[email protected]>	[4.11+]
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
aagit authored and torvalds committed Jun 16, 2017
1 parent 3c226c6 commit 64c2b20
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions fs/userfaultfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,28 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
bool must_wait, return_to_userland;
long blocking_state;

BUG_ON(!rwsem_is_locked(&mm->mmap_sem));

ret = VM_FAULT_SIGBUS;

/*
* We don't do userfault handling for the final child pid update.
*
* We also don't do userfault handling during
* coredumping. hugetlbfs has the special
* follow_hugetlb_page() to skip missing pages in the
* FOLL_DUMP case, anon memory also checks for FOLL_DUMP with
* the no_page_table() helper in follow_page_mask(), but the
* shmem_vm_ops->fault method is invoked even during
* coredumping without mmap_sem and it ends up here.
*/
if (current->flags & (PF_EXITING|PF_DUMPCORE))
goto out;

/*
* Coredumping runs without mmap_sem so we can only check that
* the mmap_sem is held, if PF_DUMPCORE was not set.
*/
WARN_ON_ONCE(!rwsem_is_locked(&mm->mmap_sem));

ctx = vmf->vma->vm_userfaultfd_ctx.ctx;
if (!ctx)
goto out;
Expand All @@ -360,12 +379,6 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
if (unlikely(ACCESS_ONCE(ctx->released)))
goto out;

/*
* We don't do userfault handling for the final child pid update.
*/
if (current->flags & PF_EXITING)
goto out;

/*
* Check that we can return VM_FAULT_RETRY.
*
Expand Down

0 comments on commit 64c2b20

Please sign in to comment.