• Andrea Arcangeli's avatar
    userfaultfd: non-cooperative: fix fork use after free · 384632e6
    Andrea Arcangeli authored
    When reading the event from the uffd, we put it on a temporary
    fork_event list to detect if we can still access it after releasing and
    retaking the event_wqh.lock.
    
    If fork aborts and removes the event from the fork_event all is fine as
    long as we're still in the userfault read context and fork_event head is
    still alive.
    
    We've to put the event allocated in the fork kernel stack, back from
    fork_event list-head to the event_wqh head, before returning from
    userfaultfd_ctx_read, because the fork_event head lifetime is limited to
    the userfaultfd_ctx_read stack lifetime.
    
    Forgetting to move the event back to its event_wqh place then results in
    __remove_wait_queue(&ctx->event_wqh, &ewq->wq); in
    userfaultfd_event_wait_completion to remove it from a head that has been
    already freed from the reader stack.
    
    This could only happen if resolve_userfault_fork failed (for example if
    there are no file descriptors available to allocate the fork uffd).  If
    it succeeded it was put back correctly.
    
    Furthermore, after find_userfault_evt receives a fork event, the forked
    userfault context in fork_nctx and uwq->msg.arg.reserved.reserved1 can
    be released by the fork thread as soon as the event_wqh.lock is
    released.  Taking a reference on the fork_nctx before dropping the lock
    prevents an use after free in resolve_userfault_fork().
    
    If the fork side aborted and it already released everything, we still
    try to succeed resolve_userfault_fork(), if possible.
    
    Fixes: 893e26e6 ("userfaultfd: non-cooperative: Add fork() event")
    Link: http://lkml.kernel.org/r/20170920180413.26713-1-aarcange@redhat.comSigned-off-by: 's avatarAndrea Arcangeli <aarcange@redhat.com>
    Reported-by: 's avatarMark Rutland <mark.rutland@arm.com>
    Tested-by: 's avatarMark Rutland <mark.rutland@arm.com>
    Cc: Pavel Emelyanov <xemul@virtuozzo.com>
    Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
    Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
    Cc: Mike Kravetz <mike.kravetz@oracle.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: 's avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: 's avatarLinus Torvalds <torvalds@linux-foundation.org>
    384632e6