2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* fs/userfaultfd.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
|
|
|
|
* Copyright (C) 2008-2009 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
|
|
|
* Some part derived from fs/eventfd.c (anon inode setup) and
|
|
|
|
* mm/ksm.c (mm hashing).
|
|
|
|
*/
|
|
|
|
|
2017-02-22 23:42:21 +00:00
|
|
|
#include <linux/list.h>
|
2015-09-04 22:46:31 +00:00
|
|
|
#include <linux/hashtable.h>
|
2017-02-02 18:15:33 +00:00
|
|
|
#include <linux/sched/signal.h>
|
2017-02-08 17:51:29 +00:00
|
|
|
#include <linux/sched/mm.h>
|
2015-09-04 22:46:31 +00:00
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/poll.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
#include <linux/file.h>
|
|
|
|
#include <linux/bug.h>
|
|
|
|
#include <linux/anon_inodes.h>
|
|
|
|
#include <linux/syscalls.h>
|
|
|
|
#include <linux/userfaultfd_k.h>
|
|
|
|
#include <linux/mempolicy.h>
|
|
|
|
#include <linux/ioctl.h>
|
|
|
|
#include <linux/security.h>
|
2017-02-22 23:43:04 +00:00
|
|
|
#include <linux/hugetlb.h>
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2015-09-04 22:46:48 +00:00
|
|
|
static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
enum userfaultfd_state {
|
|
|
|
UFFD_STATE_WAIT_API,
|
|
|
|
UFFD_STATE_RUNNING,
|
|
|
|
};
|
|
|
|
|
2015-09-04 22:46:48 +00:00
|
|
|
/*
|
|
|
|
* Start with fault_pending_wqh and fault_wqh so they're more likely
|
|
|
|
* to be in the same cacheline.
|
|
|
|
*/
|
2015-09-04 22:46:31 +00:00
|
|
|
struct userfaultfd_ctx {
|
2015-09-04 22:46:44 +00:00
|
|
|
/* waitqueue head for the pending (i.e. not read) userfaults */
|
|
|
|
wait_queue_head_t fault_pending_wqh;
|
|
|
|
/* waitqueue head for the userfaults */
|
2015-09-04 22:46:31 +00:00
|
|
|
wait_queue_head_t fault_wqh;
|
|
|
|
/* waitqueue head for the pseudo fd to wakeup poll/read */
|
|
|
|
wait_queue_head_t fd_wqh;
|
2017-02-22 23:42:21 +00:00
|
|
|
/* waitqueue head for events */
|
|
|
|
wait_queue_head_t event_wqh;
|
2015-09-04 22:47:23 +00:00
|
|
|
/* a refile sequence protected by fault_pending_wqh lock */
|
|
|
|
struct seqcount refile_seq;
|
2015-09-04 22:46:48 +00:00
|
|
|
/* pseudo fd refcounting */
|
|
|
|
atomic_t refcount;
|
2015-09-04 22:46:31 +00:00
|
|
|
/* userfaultfd syscall flags */
|
|
|
|
unsigned int flags;
|
2017-02-22 23:42:21 +00:00
|
|
|
/* features requested from the userspace */
|
|
|
|
unsigned int features;
|
2015-09-04 22:46:31 +00:00
|
|
|
/* state machine */
|
|
|
|
enum userfaultfd_state state;
|
|
|
|
/* released */
|
|
|
|
bool released;
|
|
|
|
/* mm with one ore more vmas attached to this userfaultfd_ctx */
|
|
|
|
struct mm_struct *mm;
|
|
|
|
};
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
struct userfaultfd_fork_ctx {
|
|
|
|
struct userfaultfd_ctx *orig;
|
|
|
|
struct userfaultfd_ctx *new;
|
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
2017-02-24 22:58:22 +00:00
|
|
|
struct userfaultfd_unmap_ctx {
|
|
|
|
struct userfaultfd_ctx *ctx;
|
|
|
|
unsigned long start;
|
|
|
|
unsigned long end;
|
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
struct userfaultfd_wait_queue {
|
2015-09-04 22:46:37 +00:00
|
|
|
struct uffd_msg msg;
|
2015-09-04 22:46:31 +00:00
|
|
|
wait_queue_t wq;
|
|
|
|
struct userfaultfd_ctx *ctx;
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
bool waken;
|
2015-09-04 22:46:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct userfaultfd_wake_range {
|
|
|
|
unsigned long start;
|
|
|
|
unsigned long len;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int userfaultfd_wake_function(wait_queue_t *wq, unsigned mode,
|
|
|
|
int wake_flags, void *key)
|
|
|
|
{
|
|
|
|
struct userfaultfd_wake_range *range = key;
|
|
|
|
int ret;
|
|
|
|
struct userfaultfd_wait_queue *uwq;
|
|
|
|
unsigned long start, len;
|
|
|
|
|
|
|
|
uwq = container_of(wq, struct userfaultfd_wait_queue, wq);
|
|
|
|
ret = 0;
|
|
|
|
/* len == 0 means wake all */
|
|
|
|
start = range->start;
|
|
|
|
len = range->len;
|
2015-09-04 22:46:37 +00:00
|
|
|
if (len && (start > uwq->msg.arg.pagefault.address ||
|
|
|
|
start + len <= uwq->msg.arg.pagefault.address))
|
2015-09-04 22:46:31 +00:00
|
|
|
goto out;
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
WRITE_ONCE(uwq->waken, true);
|
|
|
|
/*
|
|
|
|
* The implicit smp_mb__before_spinlock in try_to_wake_up()
|
|
|
|
* renders uwq->waken visible to other CPUs before the task is
|
|
|
|
* waken.
|
|
|
|
*/
|
2015-09-04 22:46:31 +00:00
|
|
|
ret = wake_up_state(wq->private, mode);
|
|
|
|
if (ret)
|
|
|
|
/*
|
|
|
|
* Wake only once, autoremove behavior.
|
|
|
|
*
|
|
|
|
* After the effect of list_del_init is visible to the
|
|
|
|
* other CPUs, the waitqueue may disappear from under
|
|
|
|
* us, see the !list_empty_careful() in
|
|
|
|
* handle_userfault(). try_to_wake_up() has an
|
|
|
|
* implicit smp_mb__before_spinlock, and the
|
|
|
|
* wq->private is read before calling the extern
|
|
|
|
* function "wake_up_state" (which in turns calls
|
|
|
|
* try_to_wake_up). While the spin_lock;spin_unlock;
|
|
|
|
* wouldn't be enough, the smp_mb__before_spinlock is
|
|
|
|
* enough to avoid an explicit smp_mb() here.
|
|
|
|
*/
|
|
|
|
list_del_init(&wq->task_list);
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* userfaultfd_ctx_get - Acquires a reference to the internal userfaultfd
|
|
|
|
* context.
|
|
|
|
* @ctx: [in] Pointer to the userfaultfd context.
|
|
|
|
*
|
|
|
|
* Returns: In case of success, returns not zero.
|
|
|
|
*/
|
|
|
|
static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
|
|
|
|
{
|
|
|
|
if (!atomic_inc_not_zero(&ctx->refcount))
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* userfaultfd_ctx_put - Releases a reference to the internal userfaultfd
|
|
|
|
* context.
|
|
|
|
* @ctx: [in] Pointer to userfaultfd context.
|
|
|
|
*
|
|
|
|
* The userfaultfd context reference must have been previously acquired either
|
|
|
|
* with userfaultfd_ctx_get() or userfaultfd_ctx_fdget().
|
|
|
|
*/
|
|
|
|
static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
|
|
|
|
{
|
|
|
|
if (atomic_dec_and_test(&ctx->refcount)) {
|
|
|
|
VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock));
|
|
|
|
VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh));
|
|
|
|
VM_BUG_ON(spin_is_locked(&ctx->fault_wqh.lock));
|
|
|
|
VM_BUG_ON(waitqueue_active(&ctx->fault_wqh));
|
2017-02-22 23:42:21 +00:00
|
|
|
VM_BUG_ON(spin_is_locked(&ctx->event_wqh.lock));
|
|
|
|
VM_BUG_ON(waitqueue_active(&ctx->event_wqh));
|
2015-09-04 22:46:31 +00:00
|
|
|
VM_BUG_ON(spin_is_locked(&ctx->fd_wqh.lock));
|
|
|
|
VM_BUG_ON(waitqueue_active(&ctx->fd_wqh));
|
2016-05-20 23:58:36 +00:00
|
|
|
mmdrop(ctx->mm);
|
2015-09-04 22:46:48 +00:00
|
|
|
kmem_cache_free(userfaultfd_ctx_cachep, ctx);
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:37 +00:00
|
|
|
static inline void msg_init(struct uffd_msg *msg)
|
2015-09-04 22:46:31 +00:00
|
|
|
{
|
2015-09-04 22:46:37 +00:00
|
|
|
BUILD_BUG_ON(sizeof(struct uffd_msg) != 32);
|
|
|
|
/*
|
|
|
|
* Must use memset to zero out the paddings or kernel data is
|
|
|
|
* leaked to userland.
|
|
|
|
*/
|
|
|
|
memset(msg, 0, sizeof(struct uffd_msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct uffd_msg userfault_msg(unsigned long address,
|
|
|
|
unsigned int flags,
|
|
|
|
unsigned long reason)
|
|
|
|
{
|
|
|
|
struct uffd_msg msg;
|
|
|
|
msg_init(&msg);
|
|
|
|
msg.event = UFFD_EVENT_PAGEFAULT;
|
|
|
|
msg.arg.pagefault.address = address;
|
2015-09-04 22:46:31 +00:00
|
|
|
if (flags & FAULT_FLAG_WRITE)
|
|
|
|
/*
|
2017-02-22 23:42:09 +00:00
|
|
|
* If UFFD_FEATURE_PAGEFAULT_FLAG_WP was set in the
|
2015-09-04 22:46:37 +00:00
|
|
|
* uffdio_api.features and UFFD_PAGEFAULT_FLAG_WRITE
|
|
|
|
* was not set in a UFFD_EVENT_PAGEFAULT, it means it
|
|
|
|
* was a read fault, otherwise if set it means it's
|
|
|
|
* a write fault.
|
2015-09-04 22:46:31 +00:00
|
|
|
*/
|
2015-09-04 22:46:37 +00:00
|
|
|
msg.arg.pagefault.flags |= UFFD_PAGEFAULT_FLAG_WRITE;
|
2015-09-04 22:46:31 +00:00
|
|
|
if (reason & VM_UFFD_WP)
|
|
|
|
/*
|
2015-09-04 22:46:37 +00:00
|
|
|
* If UFFD_FEATURE_PAGEFAULT_FLAG_WP was set in the
|
|
|
|
* uffdio_api.features and UFFD_PAGEFAULT_FLAG_WP was
|
|
|
|
* not set in a UFFD_EVENT_PAGEFAULT, it means it was
|
|
|
|
* a missing fault, otherwise if set it means it's a
|
|
|
|
* write protect fault.
|
2015-09-04 22:46:31 +00:00
|
|
|
*/
|
2015-09-04 22:46:37 +00:00
|
|
|
msg.arg.pagefault.flags |= UFFD_PAGEFAULT_FLAG_WP;
|
|
|
|
return msg;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
|
2017-02-22 23:43:10 +00:00
|
|
|
#ifdef CONFIG_HUGETLB_PAGE
|
|
|
|
/*
|
|
|
|
* Same functionality as userfaultfd_must_wait below with modifications for
|
|
|
|
* hugepmd ranges.
|
|
|
|
*/
|
|
|
|
static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long address,
|
|
|
|
unsigned long flags,
|
|
|
|
unsigned long reason)
|
|
|
|
{
|
|
|
|
struct mm_struct *mm = ctx->mm;
|
|
|
|
pte_t *pte;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
|
|
|
|
|
|
|
|
pte = huge_pte_offset(mm, address);
|
|
|
|
if (!pte)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lockless access: we're in a wait_event so it's ok if it
|
|
|
|
* changes under us.
|
|
|
|
*/
|
|
|
|
if (huge_pte_none(*pte))
|
|
|
|
ret = true;
|
|
|
|
if (!huge_pte_write(*pte) && (reason & VM_UFFD_WP))
|
|
|
|
ret = true;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline bool userfaultfd_huge_must_wait(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long address,
|
|
|
|
unsigned long flags,
|
|
|
|
unsigned long reason)
|
|
|
|
{
|
|
|
|
return false; /* should never get here */
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_HUGETLB_PAGE */
|
|
|
|
|
userfaultfd: solve the race between UFFDIO_COPY|ZEROPAGE and read
Solve in-kernel the race between UFFDIO_COPY|ZEROPAGE and
userfaultfd_read if they are run on different threads simultaneously.
Until now qemu solved the race in userland: the race was explicitly
and intentionally left for userland to solve. However we can also
solve it in kernel.
Requiring all users to solve this race if they use two threads (one
for the background transfer and one for the userfault reads) isn't
very attractive from an API prospective, furthermore this allows to
remove a whole bunch of mutex and bitmap code from qemu, making it
faster. The cost of __get_user_pages_fast should be insignificant
considering it scales perfectly and the pagetables are already hot in
the CPU cache, compared to the overhead in userland to maintain those
structures.
Applying this patch is backwards compatible with respect to the
userfaultfd userland API, however reverting this change wouldn't be
backwards compatible anymore.
Without this patch qemu in the background transfer thread, has to read
the old state, and do UFFDIO_WAKE if old_state is missing but it
become REQUESTED by the time it tries to set it to RECEIVED (signaling
the other side received an userfault).
vcpu background_thr userfault_thr
----- ----- -----
vcpu0 handle_mm_fault()
postcopy_place_page
read old_state -> MISSING
UFFDIO_COPY 0x7fb76a139000 (no wakeup, still pending)
vcpu0 fault at 0x7fb76a139000 enters handle_userfault
poll() is kicked
poll() -> POLLIN
read() -> 0x7fb76a139000
postcopy_pmi_change_state(MISSING, REQUESTED) -> REQUESTED
tmp_state = postcopy_pmi_change_state(old_state, RECEIVED) -> REQUESTED
/* check that no userfault raced with UFFDIO_COPY */
if (old_state == MISSING && tmp_state == REQUESTED)
UFFDIO_WAKE from background thread
And a second case where a UFFDIO_WAKE would be needed is in the userfault thread:
vcpu background_thr userfault_thr
----- ----- -----
vcpu0 handle_mm_fault()
postcopy_place_page
read old_state -> MISSING
UFFDIO_COPY 0x7fb76a139000 (no wakeup, still pending)
tmp_state = postcopy_pmi_change_state(old_state, RECEIVED) -> RECEIVED
vcpu0 fault at 0x7fb76a139000 enters handle_userfault
poll() is kicked
poll() -> POLLIN
read() -> 0x7fb76a139000
if (postcopy_pmi_change_state(MISSING, REQUESTED) == RECEIVED)
UFFDIO_WAKE from userfault thread
This patch removes the need of both UFFDIO_WAKE and of the associated
per-page tristate as well.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Cc: Sanidhya Kashyap <sanidhya.gatech@gmail.com>
Cc: zhang.zhanghailiang@huawei.com
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Andres Lagar-Cavilla <andreslc@google.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Hugh Dickins <hughd@google.com>
Cc: Peter Feiner <pfeiner@google.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Huangpeng (Peter)" <peter.huangpeng@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-09-04 22:46:51 +00:00
|
|
|
/*
|
|
|
|
* Verify the pagetables are still not ok after having reigstered into
|
|
|
|
* the fault_pending_wqh to avoid userland having to UFFDIO_WAKE any
|
|
|
|
* userfault that has already been resolved, if userfaultfd_read and
|
|
|
|
* UFFDIO_COPY|ZEROPAGE are being run simultaneously on two different
|
|
|
|
* threads.
|
|
|
|
*/
|
|
|
|
static inline bool userfaultfd_must_wait(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long address,
|
|
|
|
unsigned long flags,
|
|
|
|
unsigned long reason)
|
|
|
|
{
|
|
|
|
struct mm_struct *mm = ctx->mm;
|
|
|
|
pgd_t *pgd;
|
|
|
|
pud_t *pud;
|
|
|
|
pmd_t *pmd, _pmd;
|
|
|
|
pte_t *pte;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
|
|
|
|
|
|
|
|
pgd = pgd_offset(mm, address);
|
|
|
|
if (!pgd_present(*pgd))
|
|
|
|
goto out;
|
|
|
|
pud = pud_offset(pgd, address);
|
|
|
|
if (!pud_present(*pud))
|
|
|
|
goto out;
|
|
|
|
pmd = pmd_offset(pud, address);
|
|
|
|
/*
|
|
|
|
* READ_ONCE must function as a barrier with narrower scope
|
|
|
|
* and it must be equivalent to:
|
|
|
|
* _pmd = *pmd; barrier();
|
|
|
|
*
|
|
|
|
* This is to deal with the instability (as in
|
|
|
|
* pmd_trans_unstable) of the pmd.
|
|
|
|
*/
|
|
|
|
_pmd = READ_ONCE(*pmd);
|
|
|
|
if (!pmd_present(_pmd))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = false;
|
|
|
|
if (pmd_trans_huge(_pmd))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* the pmd is stable (as in !pmd_trans_unstable) so we can re-read it
|
|
|
|
* and use the standard pte_offset_map() instead of parsing _pmd.
|
|
|
|
*/
|
|
|
|
pte = pte_offset_map(pmd, address);
|
|
|
|
/*
|
|
|
|
* Lockless access: we're in a wait_event so it's ok if it
|
|
|
|
* changes under us.
|
|
|
|
*/
|
|
|
|
if (pte_none(*pte))
|
|
|
|
ret = true;
|
|
|
|
pte_unmap(pte);
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* The locking rules involved in returning VM_FAULT_RETRY depending on
|
|
|
|
* FAULT_FLAG_ALLOW_RETRY, FAULT_FLAG_RETRY_NOWAIT and
|
|
|
|
* FAULT_FLAG_KILLABLE are not straightforward. The "Caution"
|
|
|
|
* recommendation in __lock_page_or_retry is not an understatement.
|
|
|
|
*
|
|
|
|
* If FAULT_FLAG_ALLOW_RETRY is set, the mmap_sem must be released
|
|
|
|
* before returning VM_FAULT_RETRY only if FAULT_FLAG_RETRY_NOWAIT is
|
|
|
|
* not set.
|
|
|
|
*
|
|
|
|
* If FAULT_FLAG_ALLOW_RETRY is set but FAULT_FLAG_KILLABLE is not
|
|
|
|
* set, VM_FAULT_RETRY can still be returned if and only if there are
|
|
|
|
* fatal_signal_pending()s, and the mmap_sem must be released before
|
|
|
|
* returning it.
|
|
|
|
*/
|
2016-12-14 23:06:58 +00:00
|
|
|
int handle_userfault(struct vm_fault *vmf, unsigned long reason)
|
2015-09-04 22:46:31 +00:00
|
|
|
{
|
2016-12-14 23:06:58 +00:00
|
|
|
struct mm_struct *mm = vmf->vma->vm_mm;
|
2015-09-04 22:46:31 +00:00
|
|
|
struct userfaultfd_ctx *ctx;
|
|
|
|
struct userfaultfd_wait_queue uwq;
|
2015-09-04 22:46:41 +00:00
|
|
|
int ret;
|
2015-09-04 22:47:18 +00:00
|
|
|
bool must_wait, return_to_userland;
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
long blocking_state;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
|
|
|
|
|
2015-09-04 22:46:41 +00:00
|
|
|
ret = VM_FAULT_SIGBUS;
|
2016-12-14 23:06:58 +00:00
|
|
|
ctx = vmf->vma->vm_userfaultfd_ctx.ctx;
|
2015-09-04 22:46:31 +00:00
|
|
|
if (!ctx)
|
2015-09-04 22:46:41 +00:00
|
|
|
goto out;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
BUG_ON(ctx->mm != mm);
|
|
|
|
|
|
|
|
VM_BUG_ON(reason & ~(VM_UFFD_MISSING|VM_UFFD_WP));
|
|
|
|
VM_BUG_ON(!(reason & VM_UFFD_MISSING) ^ !!(reason & VM_UFFD_WP));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If it's already released don't get it. This avoids to loop
|
|
|
|
* in __get_user_pages if userfaultfd_release waits on the
|
|
|
|
* caller of handle_userfault to release the mmap_sem.
|
|
|
|
*/
|
|
|
|
if (unlikely(ACCESS_ONCE(ctx->released)))
|
2015-09-04 22:46:41 +00:00
|
|
|
goto out;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2016-03-01 19:56:22 +00:00
|
|
|
/*
|
|
|
|
* We don't do userfault handling for the final child pid update.
|
|
|
|
*/
|
|
|
|
if (current->flags & PF_EXITING)
|
|
|
|
goto out;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Check that we can return VM_FAULT_RETRY.
|
|
|
|
*
|
|
|
|
* NOTE: it should become possible to return VM_FAULT_RETRY
|
|
|
|
* even if FAULT_FLAG_TRIED is set without leading to gup()
|
|
|
|
* -EBUSY failures, if the userfaultfd is to be extended for
|
|
|
|
* VM_UFFD_WP tracking and we intend to arm the userfault
|
|
|
|
* without first stopping userland access to the memory. For
|
|
|
|
* VM_UFFD_MISSING userfaults this is enough for now.
|
|
|
|
*/
|
2016-12-14 23:06:58 +00:00
|
|
|
if (unlikely(!(vmf->flags & FAULT_FLAG_ALLOW_RETRY))) {
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Validate the invariant that nowait must allow retry
|
|
|
|
* to be sure not to return SIGBUS erroneously on
|
|
|
|
* nowait invocations.
|
|
|
|
*/
|
2016-12-14 23:06:58 +00:00
|
|
|
BUG_ON(vmf->flags & FAULT_FLAG_RETRY_NOWAIT);
|
2015-09-04 22:46:31 +00:00
|
|
|
#ifdef CONFIG_DEBUG_VM
|
|
|
|
if (printk_ratelimit()) {
|
|
|
|
printk(KERN_WARNING
|
2016-12-14 23:06:58 +00:00
|
|
|
"FAULT_FLAG_ALLOW_RETRY missing %x\n",
|
|
|
|
vmf->flags);
|
2015-09-04 22:46:31 +00:00
|
|
|
dump_stack();
|
|
|
|
}
|
|
|
|
#endif
|
2015-09-04 22:46:41 +00:00
|
|
|
goto out;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle nowait, not much to do other than tell it to retry
|
|
|
|
* and wait.
|
|
|
|
*/
|
2015-09-04 22:46:41 +00:00
|
|
|
ret = VM_FAULT_RETRY;
|
2016-12-14 23:06:58 +00:00
|
|
|
if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT)
|
2015-09-04 22:46:41 +00:00
|
|
|
goto out;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
/* take the reference before dropping the mmap_sem */
|
|
|
|
userfaultfd_ctx_get(ctx);
|
|
|
|
|
|
|
|
init_waitqueue_func_entry(&uwq.wq, userfaultfd_wake_function);
|
|
|
|
uwq.wq.private = current;
|
2016-12-14 23:06:58 +00:00
|
|
|
uwq.msg = userfault_msg(vmf->address, vmf->flags, reason);
|
2015-09-04 22:46:31 +00:00
|
|
|
uwq.ctx = ctx;
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
uwq.waken = false;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2016-07-26 22:25:20 +00:00
|
|
|
return_to_userland =
|
2016-12-14 23:06:58 +00:00
|
|
|
(vmf->flags & (FAULT_FLAG_USER|FAULT_FLAG_KILLABLE)) ==
|
2015-09-04 22:47:18 +00:00
|
|
|
(FAULT_FLAG_USER|FAULT_FLAG_KILLABLE);
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
blocking_state = return_to_userland ? TASK_INTERRUPTIBLE :
|
|
|
|
TASK_KILLABLE;
|
2015-09-04 22:47:18 +00:00
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* After the __add_wait_queue the uwq is visible to userland
|
|
|
|
* through poll/read().
|
|
|
|
*/
|
2015-09-04 22:46:44 +00:00
|
|
|
__add_wait_queue(&ctx->fault_pending_wqh, &uwq.wq);
|
|
|
|
/*
|
|
|
|
* The smp_mb() after __set_current_state prevents the reads
|
|
|
|
* following the spin_unlock to happen before the list_add in
|
|
|
|
* __add_wait_queue.
|
|
|
|
*/
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
set_current_state(blocking_state);
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2017-02-22 23:43:10 +00:00
|
|
|
if (!is_vm_hugetlb_page(vmf->vma))
|
|
|
|
must_wait = userfaultfd_must_wait(ctx, vmf->address, vmf->flags,
|
|
|
|
reason);
|
|
|
|
else
|
|
|
|
must_wait = userfaultfd_huge_must_wait(ctx, vmf->address,
|
|
|
|
vmf->flags, reason);
|
userfaultfd: solve the race between UFFDIO_COPY|ZEROPAGE and read
Solve in-kernel the race between UFFDIO_COPY|ZEROPAGE and
userfaultfd_read if they are run on different threads simultaneously.
Until now qemu solved the race in userland: the race was explicitly
and intentionally left for userland to solve. However we can also
solve it in kernel.
Requiring all users to solve this race if they use two threads (one
for the background transfer and one for the userfault reads) isn't
very attractive from an API prospective, furthermore this allows to
remove a whole bunch of mutex and bitmap code from qemu, making it
faster. The cost of __get_user_pages_fast should be insignificant
considering it scales perfectly and the pagetables are already hot in
the CPU cache, compared to the overhead in userland to maintain those
structures.
Applying this patch is backwards compatible with respect to the
userfaultfd userland API, however reverting this change wouldn't be
backwards compatible anymore.
Without this patch qemu in the background transfer thread, has to read
the old state, and do UFFDIO_WAKE if old_state is missing but it
become REQUESTED by the time it tries to set it to RECEIVED (signaling
the other side received an userfault).
vcpu background_thr userfault_thr
----- ----- -----
vcpu0 handle_mm_fault()
postcopy_place_page
read old_state -> MISSING
UFFDIO_COPY 0x7fb76a139000 (no wakeup, still pending)
vcpu0 fault at 0x7fb76a139000 enters handle_userfault
poll() is kicked
poll() -> POLLIN
read() -> 0x7fb76a139000
postcopy_pmi_change_state(MISSING, REQUESTED) -> REQUESTED
tmp_state = postcopy_pmi_change_state(old_state, RECEIVED) -> REQUESTED
/* check that no userfault raced with UFFDIO_COPY */
if (old_state == MISSING && tmp_state == REQUESTED)
UFFDIO_WAKE from background thread
And a second case where a UFFDIO_WAKE would be needed is in the userfault thread:
vcpu background_thr userfault_thr
----- ----- -----
vcpu0 handle_mm_fault()
postcopy_place_page
read old_state -> MISSING
UFFDIO_COPY 0x7fb76a139000 (no wakeup, still pending)
tmp_state = postcopy_pmi_change_state(old_state, RECEIVED) -> RECEIVED
vcpu0 fault at 0x7fb76a139000 enters handle_userfault
poll() is kicked
poll() -> POLLIN
read() -> 0x7fb76a139000
if (postcopy_pmi_change_state(MISSING, REQUESTED) == RECEIVED)
UFFDIO_WAKE from userfault thread
This patch removes the need of both UFFDIO_WAKE and of the associated
per-page tristate as well.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Cc: Sanidhya Kashyap <sanidhya.gatech@gmail.com>
Cc: zhang.zhanghailiang@huawei.com
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Andres Lagar-Cavilla <andreslc@google.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Hugh Dickins <hughd@google.com>
Cc: Peter Feiner <pfeiner@google.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "Huangpeng (Peter)" <peter.huangpeng@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2015-09-04 22:46:51 +00:00
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
|
|
|
if (likely(must_wait && !ACCESS_ONCE(ctx->released) &&
|
2015-09-04 22:47:18 +00:00
|
|
|
(return_to_userland ? !signal_pending(current) :
|
|
|
|
!fatal_signal_pending(current)))) {
|
2015-09-04 22:46:31 +00:00
|
|
|
wake_up_poll(&ctx->fd_wqh, POLLIN);
|
|
|
|
schedule();
|
2015-09-04 22:46:41 +00:00
|
|
|
ret |= VM_FAULT_MAJOR;
|
userfaultfd: fix SIGBUS resulting from false rwsem wakeups
With >=32 CPUs the userfaultfd selftest triggered a graceful but
unexpected SIGBUS because VM_FAULT_RETRY was returned by
handle_userfault() despite the UFFDIO_COPY wasn't completed.
This seems caused by rwsem waking the thread blocked in
handle_userfault() and we can't run up_read() before the wait_event
sequence is complete.
Keeping the wait_even sequence identical to the first one, would require
running userfaultfd_must_wait() again to know if the loop should be
repeated, and it would also require retaking the rwsem and revalidating
the whole vma status.
It seems simpler to wait the targeted wakeup so that if false wakeups
materialize we still wait for our specific wakeup event, unless of
course there are signals or the uffd was released.
Debug code collecting the stack trace of the wakeup showed this:
$ ./userfaultfd 100 99999
nr_pages: 25600, nr_pages_per_cpu: 800
bounces: 99998, mode: racing ver poll, userfaults: 32 35 90 232 30 138 69 82 34 30 139 40 40 31 20 19 43 13 15 28 27 38 21 43 56 22 1 17 31 8 4 2
bounces: 99997, mode: rnd ver poll, Bus error (core dumped)
save_stack_trace+0x2b/0x50
try_to_wake_up+0x2a6/0x580
wake_up_q+0x32/0x70
rwsem_wake+0xe0/0x120
call_rwsem_wake+0x1b/0x30
up_write+0x3b/0x40
vm_mmap_pgoff+0x9c/0xc0
SyS_mmap_pgoff+0x1a9/0x240
SyS_mmap+0x22/0x30
entry_SYSCALL_64_fastpath+0x1f/0xbd
0xffffffffffffffff
FAULT_FLAG_ALLOW_RETRY missing 70
CPU: 24 PID: 1054 Comm: userfaultfd Tainted: G W 4.8.0+ #30
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014
Call Trace:
dump_stack+0xb8/0x112
handle_userfault+0x572/0x650
handle_mm_fault+0x12cb/0x1520
__do_page_fault+0x175/0x500
trace_do_page_fault+0x61/0x270
do_async_page_fault+0x19/0x90
async_page_fault+0x25/0x30
This always happens when the main userfault selftest thread is running
clone() while glibc runs either mprotect or mmap (both taking mmap_sem
down_write()) to allocate the thread stack of the background threads,
while locking/userfault threads already run at full throttle and are
susceptible to false wakeups that may cause handle_userfault() to return
before than expected (which results in graceful SIGBUS at the next
attempt).
This was reproduced only with >=32 CPUs because the loop to start the
thread where clone() is too quick with fewer CPUs, while with 32 CPUs
there's already significant activity on ~32 locking and userfault
threads when the last background threads are started with clone().
This >=32 CPUs SMP race condition is likely reproducible only with the
selftest because of the much heavier userfault load it generates if
compared to real apps.
We'll have to allow "one more" VM_FAULT_RETRY for the WP support and a
patch floating around that provides it also hidden this problem but in
reality only is successfully at hiding the problem.
False wakeups could still happen again the second time
handle_userfault() is invoked, even if it's a so rare race condition
that getting false wakeups twice in a row is impossible to reproduce.
This full fix is needed for correctness, the only alternative would be
to allow VM_FAULT_RETRY to be returned infinitely. With this fix the WP
support can stick to a strict "one more" VM_FAULT_RETRY logic (no need
of returning it infinite times to avoid the SIGBUS).
Link: http://lkml.kernel.org/r/20170111005535.13832-2-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Reported-by: Shubham Kumar Sharma <shubham.kumar.sharma@oracle.com>
Tested-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Michael Rapoport <RAPOPORT@il.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2017-01-24 23:17:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* False wakeups can orginate even from rwsem before
|
|
|
|
* up_read() however userfaults will wait either for a
|
|
|
|
* targeted wakeup on the specific uwq waitqueue from
|
|
|
|
* wake_userfault() or for signals or for uffd
|
|
|
|
* release.
|
|
|
|
*/
|
|
|
|
while (!READ_ONCE(uwq.waken)) {
|
|
|
|
/*
|
|
|
|
* This needs the full smp_store_mb()
|
|
|
|
* guarantee as the state write must be
|
|
|
|
* visible to other CPUs before reading
|
|
|
|
* uwq.waken from other CPUs.
|
|
|
|
*/
|
|
|
|
set_current_state(blocking_state);
|
|
|
|
if (READ_ONCE(uwq.waken) ||
|
|
|
|
READ_ONCE(ctx->released) ||
|
|
|
|
(return_to_userland ? signal_pending(current) :
|
|
|
|
fatal_signal_pending(current)))
|
|
|
|
break;
|
|
|
|
schedule();
|
|
|
|
}
|
2015-09-04 22:46:41 +00:00
|
|
|
}
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2015-09-04 22:46:41 +00:00
|
|
|
__set_current_state(TASK_RUNNING);
|
2015-09-04 22:46:44 +00:00
|
|
|
|
2015-09-04 22:47:18 +00:00
|
|
|
if (return_to_userland) {
|
|
|
|
if (signal_pending(current) &&
|
|
|
|
!fatal_signal_pending(current)) {
|
|
|
|
/*
|
|
|
|
* If we got a SIGSTOP or SIGCONT and this is
|
|
|
|
* a normal userland page fault, just let
|
|
|
|
* userland return so the signal will be
|
|
|
|
* handled and gdb debugging works. The page
|
|
|
|
* fault code immediately after we return from
|
|
|
|
* this function is going to release the
|
|
|
|
* mmap_sem and it's not depending on it
|
|
|
|
* (unlike gup would if we were not to return
|
|
|
|
* VM_FAULT_RETRY).
|
|
|
|
*
|
|
|
|
* If a fatal signal is pending we still take
|
|
|
|
* the streamlined VM_FAULT_RETRY failure path
|
|
|
|
* and there's no need to retake the mmap_sem
|
|
|
|
* in such case.
|
|
|
|
*/
|
|
|
|
down_read(&mm->mmap_sem);
|
2017-03-10 00:16:28 +00:00
|
|
|
ret = VM_FAULT_NOPAGE;
|
2015-09-04 22:47:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
/*
|
|
|
|
* Here we race with the list_del; list_add in
|
|
|
|
* userfaultfd_ctx_read(), however because we don't ever run
|
|
|
|
* list_del_init() to refile across the two lists, the prev
|
|
|
|
* and next pointers will never point to self. list_add also
|
|
|
|
* would never let any of the two pointers to point to
|
|
|
|
* self. So list_empty_careful won't risk to see both pointers
|
|
|
|
* pointing to self at any time during the list refile. The
|
|
|
|
* only case where list_del_init() is called is the full
|
|
|
|
* removal in the wake function and there we don't re-list_add
|
|
|
|
* and it's fine not to block on the spinlock. The uwq on this
|
|
|
|
* kernel stack can be released after the list_del_init.
|
|
|
|
*/
|
2015-09-04 22:46:41 +00:00
|
|
|
if (!list_empty_careful(&uwq.wq.task_list)) {
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
|
|
|
/*
|
|
|
|
* No need of list_del_init(), the uwq on the stack
|
|
|
|
* will be freed shortly anyway.
|
|
|
|
*/
|
|
|
|
list_del(&uwq.wq.task_list);
|
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ctx may go away after this if the userfault pseudo fd is
|
|
|
|
* already released.
|
|
|
|
*/
|
|
|
|
userfaultfd_ctx_put(ctx);
|
|
|
|
|
2015-09-04 22:46:41 +00:00
|
|
|
out:
|
|
|
|
return ret;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
|
|
|
|
struct userfaultfd_wait_queue *ewq)
|
2017-02-22 23:42:21 +00:00
|
|
|
{
|
2017-03-10 00:16:52 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = -1;
|
|
|
|
if (WARN_ON_ONCE(current->flags & PF_EXITING))
|
|
|
|
goto out;
|
2017-02-22 23:42:21 +00:00
|
|
|
|
2017-03-10 00:16:52 +00:00
|
|
|
ret = 0;
|
2017-02-22 23:42:21 +00:00
|
|
|
ewq->ctx = ctx;
|
|
|
|
init_waitqueue_entry(&ewq->wq, current);
|
|
|
|
|
|
|
|
spin_lock(&ctx->event_wqh.lock);
|
|
|
|
/*
|
|
|
|
* After the __add_wait_queue the uwq is visible to userland
|
|
|
|
* through poll/read().
|
|
|
|
*/
|
|
|
|
__add_wait_queue(&ctx->event_wqh, &ewq->wq);
|
|
|
|
for (;;) {
|
|
|
|
set_current_state(TASK_KILLABLE);
|
|
|
|
if (ewq->msg.event == 0)
|
|
|
|
break;
|
|
|
|
if (ACCESS_ONCE(ctx->released) ||
|
|
|
|
fatal_signal_pending(current)) {
|
|
|
|
ret = -1;
|
|
|
|
__remove_wait_queue(&ctx->event_wqh, &ewq->wq);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
|
|
|
|
wake_up_poll(&ctx->fd_wqh, POLLIN);
|
|
|
|
schedule();
|
|
|
|
|
|
|
|
spin_lock(&ctx->event_wqh.lock);
|
|
|
|
}
|
|
|
|
__set_current_state(TASK_RUNNING);
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ctx may go away after this if the userfault pseudo fd is
|
|
|
|
* already released.
|
|
|
|
*/
|
2017-03-10 00:16:52 +00:00
|
|
|
out:
|
2017-02-22 23:42:21 +00:00
|
|
|
userfaultfd_ctx_put(ctx);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void userfaultfd_event_complete(struct userfaultfd_ctx *ctx,
|
|
|
|
struct userfaultfd_wait_queue *ewq)
|
|
|
|
{
|
|
|
|
ewq->msg.event = 0;
|
|
|
|
wake_up_locked(&ctx->event_wqh);
|
|
|
|
__remove_wait_queue(&ctx->event_wqh, &ewq->wq);
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = NULL, *octx;
|
|
|
|
struct userfaultfd_fork_ctx *fctx;
|
|
|
|
|
|
|
|
octx = vma->vm_userfaultfd_ctx.ctx;
|
|
|
|
if (!octx || !(octx->features & UFFD_FEATURE_EVENT_FORK)) {
|
|
|
|
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
|
|
|
|
vma->vm_flags &= ~(VM_UFFD_WP | VM_UFFD_MISSING);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(fctx, fcs, list)
|
|
|
|
if (fctx->orig == octx) {
|
|
|
|
ctx = fctx->new;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ctx) {
|
|
|
|
fctx = kmalloc(sizeof(*fctx), GFP_KERNEL);
|
|
|
|
if (!fctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL);
|
|
|
|
if (!ctx) {
|
|
|
|
kfree(fctx);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
atomic_set(&ctx->refcount, 1);
|
|
|
|
ctx->flags = octx->flags;
|
|
|
|
ctx->state = UFFD_STATE_RUNNING;
|
|
|
|
ctx->features = octx->features;
|
|
|
|
ctx->released = false;
|
|
|
|
ctx->mm = vma->vm_mm;
|
2017-02-22 23:42:30 +00:00
|
|
|
atomic_inc(&ctx->mm->mm_count);
|
2017-02-22 23:42:27 +00:00
|
|
|
|
|
|
|
userfaultfd_ctx_get(octx);
|
|
|
|
fctx->orig = octx;
|
|
|
|
fctx->new = ctx;
|
|
|
|
list_add_tail(&fctx->list, fcs);
|
|
|
|
}
|
|
|
|
|
|
|
|
vma->vm_userfaultfd_ctx.ctx = ctx;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dup_fctx(struct userfaultfd_fork_ctx *fctx)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = fctx->orig;
|
|
|
|
struct userfaultfd_wait_queue ewq;
|
|
|
|
|
|
|
|
msg_init(&ewq.msg);
|
|
|
|
|
|
|
|
ewq.msg.event = UFFD_EVENT_FORK;
|
|
|
|
ewq.msg.arg.reserved.reserved1 = (unsigned long)fctx->new;
|
|
|
|
|
|
|
|
return userfaultfd_event_wait_completion(ctx, &ewq);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dup_userfaultfd_complete(struct list_head *fcs)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
struct userfaultfd_fork_ctx *fctx, *n;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(fctx, n, fcs, list) {
|
|
|
|
if (!ret)
|
|
|
|
ret = dup_fctx(fctx);
|
|
|
|
list_del(&fctx->list);
|
|
|
|
kfree(fctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:34 +00:00
|
|
|
void mremap_userfaultfd_prep(struct vm_area_struct *vma,
|
|
|
|
struct vm_userfaultfd_ctx *vm_ctx)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx;
|
|
|
|
|
|
|
|
ctx = vma->vm_userfaultfd_ctx.ctx;
|
|
|
|
if (ctx && (ctx->features & UFFD_FEATURE_EVENT_REMAP)) {
|
|
|
|
vm_ctx->ctx = ctx;
|
|
|
|
userfaultfd_ctx_get(ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:37 +00:00
|
|
|
void mremap_userfaultfd_complete(struct vm_userfaultfd_ctx *vm_ctx,
|
2017-02-22 23:42:34 +00:00
|
|
|
unsigned long from, unsigned long to,
|
|
|
|
unsigned long len)
|
|
|
|
{
|
2017-02-22 23:42:37 +00:00
|
|
|
struct userfaultfd_ctx *ctx = vm_ctx->ctx;
|
2017-02-22 23:42:34 +00:00
|
|
|
struct userfaultfd_wait_queue ewq;
|
|
|
|
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (to & ~PAGE_MASK) {
|
|
|
|
userfaultfd_ctx_put(ctx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg_init(&ewq.msg);
|
|
|
|
|
|
|
|
ewq.msg.event = UFFD_EVENT_REMAP;
|
|
|
|
ewq.msg.arg.remap.from = from;
|
|
|
|
ewq.msg.arg.remap.to = to;
|
|
|
|
ewq.msg.arg.remap.len = len;
|
|
|
|
|
|
|
|
userfaultfd_event_wait_completion(ctx, &ewq);
|
|
|
|
}
|
|
|
|
|
2017-02-24 22:56:02 +00:00
|
|
|
void userfaultfd_remove(struct vm_area_struct *vma,
|
|
|
|
struct vm_area_struct **prev,
|
|
|
|
unsigned long start, unsigned long end)
|
2017-02-22 23:42:40 +00:00
|
|
|
{
|
|
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
|
|
struct userfaultfd_ctx *ctx;
|
|
|
|
struct userfaultfd_wait_queue ewq;
|
|
|
|
|
|
|
|
ctx = vma->vm_userfaultfd_ctx.ctx;
|
2017-02-24 22:56:02 +00:00
|
|
|
if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_REMOVE))
|
2017-02-22 23:42:40 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
userfaultfd_ctx_get(ctx);
|
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
|
|
|
*prev = NULL; /* We wait for ACK w/o the mmap semaphore */
|
|
|
|
|
|
|
|
msg_init(&ewq.msg);
|
|
|
|
|
2017-02-24 22:56:02 +00:00
|
|
|
ewq.msg.event = UFFD_EVENT_REMOVE;
|
|
|
|
ewq.msg.arg.remove.start = start;
|
|
|
|
ewq.msg.arg.remove.end = end;
|
2017-02-22 23:42:40 +00:00
|
|
|
|
|
|
|
userfaultfd_event_wait_completion(ctx, &ewq);
|
|
|
|
|
|
|
|
down_read(&mm->mmap_sem);
|
|
|
|
}
|
|
|
|
|
2017-02-24 22:58:22 +00:00
|
|
|
static bool has_unmap_ctx(struct userfaultfd_ctx *ctx, struct list_head *unmaps,
|
|
|
|
unsigned long start, unsigned long end)
|
|
|
|
{
|
|
|
|
struct userfaultfd_unmap_ctx *unmap_ctx;
|
|
|
|
|
|
|
|
list_for_each_entry(unmap_ctx, unmaps, list)
|
|
|
|
if (unmap_ctx->ctx == ctx && unmap_ctx->start == start &&
|
|
|
|
unmap_ctx->end == end)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int userfaultfd_unmap_prep(struct vm_area_struct *vma,
|
|
|
|
unsigned long start, unsigned long end,
|
|
|
|
struct list_head *unmaps)
|
|
|
|
{
|
|
|
|
for ( ; vma && vma->vm_start < end; vma = vma->vm_next) {
|
|
|
|
struct userfaultfd_unmap_ctx *unmap_ctx;
|
|
|
|
struct userfaultfd_ctx *ctx = vma->vm_userfaultfd_ctx.ctx;
|
|
|
|
|
|
|
|
if (!ctx || !(ctx->features & UFFD_FEATURE_EVENT_UNMAP) ||
|
|
|
|
has_unmap_ctx(ctx, unmaps, start, end))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
unmap_ctx = kzalloc(sizeof(*unmap_ctx), GFP_KERNEL);
|
|
|
|
if (!unmap_ctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
userfaultfd_ctx_get(ctx);
|
|
|
|
unmap_ctx->ctx = ctx;
|
|
|
|
unmap_ctx->start = start;
|
|
|
|
unmap_ctx->end = end;
|
|
|
|
list_add_tail(&unmap_ctx->list, unmaps);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void userfaultfd_unmap_complete(struct mm_struct *mm, struct list_head *uf)
|
|
|
|
{
|
|
|
|
struct userfaultfd_unmap_ctx *ctx, *n;
|
|
|
|
struct userfaultfd_wait_queue ewq;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(ctx, n, uf, list) {
|
|
|
|
msg_init(&ewq.msg);
|
|
|
|
|
|
|
|
ewq.msg.event = UFFD_EVENT_UNMAP;
|
|
|
|
ewq.msg.arg.remove.start = ctx->start;
|
|
|
|
ewq.msg.arg.remove.end = ctx->end;
|
|
|
|
|
|
|
|
userfaultfd_event_wait_completion(ctx->ctx, &ewq);
|
|
|
|
|
|
|
|
list_del(&ctx->list);
|
|
|
|
kfree(ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
static int userfaultfd_release(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = file->private_data;
|
|
|
|
struct mm_struct *mm = ctx->mm;
|
|
|
|
struct vm_area_struct *vma, *prev;
|
|
|
|
/* len == 0 means wake all */
|
|
|
|
struct userfaultfd_wake_range range = { .len = 0, };
|
|
|
|
unsigned long new_flags;
|
|
|
|
|
|
|
|
ACCESS_ONCE(ctx->released) = true;
|
|
|
|
|
2016-05-20 23:58:36 +00:00
|
|
|
if (!mmget_not_zero(mm))
|
|
|
|
goto wakeup;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Flush page faults out of all CPUs. NOTE: all page faults
|
|
|
|
* must be retried without returning VM_FAULT_SIGBUS if
|
|
|
|
* userfaultfd_ctx_get() succeeds but vma->vma_userfault_ctx
|
|
|
|
* changes while handle_userfault released the mmap_sem. So
|
|
|
|
* it's critical that released is set to true (above), before
|
|
|
|
* taking the mmap_sem for writing.
|
|
|
|
*/
|
|
|
|
down_write(&mm->mmap_sem);
|
|
|
|
prev = NULL;
|
|
|
|
for (vma = mm->mmap; vma; vma = vma->vm_next) {
|
|
|
|
cond_resched();
|
|
|
|
BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^
|
|
|
|
!!(vma->vm_flags & (VM_UFFD_MISSING | VM_UFFD_WP)));
|
|
|
|
if (vma->vm_userfaultfd_ctx.ctx != ctx) {
|
|
|
|
prev = vma;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
|
|
|
|
prev = vma_merge(mm, prev, vma->vm_start, vma->vm_end,
|
|
|
|
new_flags, vma->anon_vma,
|
|
|
|
vma->vm_file, vma->vm_pgoff,
|
|
|
|
vma_policy(vma),
|
|
|
|
NULL_VM_UFFD_CTX);
|
|
|
|
if (prev)
|
|
|
|
vma = prev;
|
|
|
|
else
|
|
|
|
prev = vma;
|
|
|
|
vma->vm_flags = new_flags;
|
|
|
|
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
|
|
|
|
}
|
|
|
|
up_write(&mm->mmap_sem);
|
2016-05-20 23:58:36 +00:00
|
|
|
mmput(mm);
|
|
|
|
wakeup:
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
2015-09-04 22:46:44 +00:00
|
|
|
* After no new page faults can wait on this fault_*wqh, flush
|
2015-09-04 22:46:31 +00:00
|
|
|
* the last page faults that may have been already waiting on
|
2015-09-04 22:46:44 +00:00
|
|
|
* the fault_*wqh.
|
2015-09-04 22:46:31 +00:00
|
|
|
*/
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
2015-09-22 21:58:49 +00:00
|
|
|
__wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, &range);
|
|
|
|
__wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, &range);
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
wake_up_poll(&ctx->fd_wqh, POLLHUP);
|
|
|
|
userfaultfd_ctx_put(ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
/* fault_pending_wqh.lock must be hold by the caller */
|
2017-02-22 23:42:18 +00:00
|
|
|
static inline struct userfaultfd_wait_queue *find_userfault_in(
|
|
|
|
wait_queue_head_t *wqh)
|
2015-09-04 22:46:31 +00:00
|
|
|
{
|
|
|
|
wait_queue_t *wq;
|
2015-09-04 22:46:44 +00:00
|
|
|
struct userfaultfd_wait_queue *uwq;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2017-02-22 23:42:18 +00:00
|
|
|
VM_BUG_ON(!spin_is_locked(&wqh->lock));
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
uwq = NULL;
|
2017-02-22 23:42:18 +00:00
|
|
|
if (!waitqueue_active(wqh))
|
2015-09-04 22:46:44 +00:00
|
|
|
goto out;
|
|
|
|
/* walk in reverse to provide FIFO behavior to read userfaults */
|
2017-02-22 23:42:18 +00:00
|
|
|
wq = list_last_entry(&wqh->task_list, typeof(*wq), task_list);
|
2015-09-04 22:46:44 +00:00
|
|
|
uwq = container_of(wq, struct userfaultfd_wait_queue, wq);
|
|
|
|
out:
|
|
|
|
return uwq;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
2017-02-22 23:42:18 +00:00
|
|
|
|
|
|
|
static inline struct userfaultfd_wait_queue *find_userfault(
|
|
|
|
struct userfaultfd_ctx *ctx)
|
|
|
|
{
|
|
|
|
return find_userfault_in(&ctx->fault_pending_wqh);
|
|
|
|
}
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2017-02-22 23:42:21 +00:00
|
|
|
static inline struct userfaultfd_wait_queue *find_userfault_evt(
|
|
|
|
struct userfaultfd_ctx *ctx)
|
|
|
|
{
|
|
|
|
return find_userfault_in(&ctx->event_wqh);
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
static unsigned int userfaultfd_poll(struct file *file, poll_table *wait)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = file->private_data;
|
|
|
|
unsigned int ret;
|
|
|
|
|
|
|
|
poll_wait(file, &ctx->fd_wqh, wait);
|
|
|
|
|
|
|
|
switch (ctx->state) {
|
|
|
|
case UFFD_STATE_WAIT_API:
|
|
|
|
return POLLERR;
|
|
|
|
case UFFD_STATE_RUNNING:
|
2015-09-04 22:46:41 +00:00
|
|
|
/*
|
|
|
|
* poll() never guarantees that read won't block.
|
|
|
|
* userfaults can be waken before they're read().
|
|
|
|
*/
|
|
|
|
if (unlikely(!(file->f_flags & O_NONBLOCK)))
|
|
|
|
return POLLERR;
|
2015-09-04 22:46:44 +00:00
|
|
|
/*
|
|
|
|
* lockless access to see if there are pending faults
|
|
|
|
* __pollwait last action is the add_wait_queue but
|
|
|
|
* the spin_unlock would allow the waitqueue_active to
|
|
|
|
* pass above the actual list_add inside
|
|
|
|
* add_wait_queue critical section. So use a full
|
|
|
|
* memory barrier to serialize the list_add write of
|
|
|
|
* add_wait_queue() with the waitqueue_active read
|
|
|
|
* below.
|
|
|
|
*/
|
|
|
|
ret = 0;
|
|
|
|
smp_mb();
|
|
|
|
if (waitqueue_active(&ctx->fault_pending_wqh))
|
|
|
|
ret = POLLIN;
|
2017-02-22 23:42:21 +00:00
|
|
|
else if (waitqueue_active(&ctx->event_wqh))
|
|
|
|
ret = POLLIN;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
return ret;
|
|
|
|
default:
|
2017-02-22 23:42:12 +00:00
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return POLLERR;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
static const struct file_operations userfaultfd_fops;
|
|
|
|
|
|
|
|
static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
|
|
|
|
struct userfaultfd_ctx *new,
|
|
|
|
struct uffd_msg *msg)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct file *file;
|
|
|
|
unsigned int flags = new->flags & UFFD_SHARED_FCNTL_FLAGS;
|
|
|
|
|
|
|
|
fd = get_unused_fd_flags(flags);
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, new,
|
|
|
|
O_RDWR | flags);
|
|
|
|
if (IS_ERR(file)) {
|
|
|
|
put_unused_fd(fd);
|
|
|
|
return PTR_ERR(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
fd_install(fd, file);
|
|
|
|
msg->arg.reserved.reserved1 = 0;
|
|
|
|
msg->arg.fork.ufd = fd;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
|
2015-09-04 22:46:37 +00:00
|
|
|
struct uffd_msg *msg)
|
2015-09-04 22:46:31 +00:00
|
|
|
{
|
|
|
|
ssize_t ret;
|
|
|
|
DECLARE_WAITQUEUE(wait, current);
|
2015-09-04 22:46:44 +00:00
|
|
|
struct userfaultfd_wait_queue *uwq;
|
2017-02-22 23:42:27 +00:00
|
|
|
/*
|
|
|
|
* Handling fork event requires sleeping operations, so
|
|
|
|
* we drop the event_wqh lock, then do these ops, then
|
|
|
|
* lock it back and wake up the waiter. While the lock is
|
|
|
|
* dropped the ewq may go away so we keep track of it
|
|
|
|
* carefully.
|
|
|
|
*/
|
|
|
|
LIST_HEAD(fork_event);
|
|
|
|
struct userfaultfd_ctx *fork_nctx = NULL;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
/* always take the fd_wqh lock before the fault_pending_wqh lock */
|
2015-09-04 22:46:31 +00:00
|
|
|
spin_lock(&ctx->fd_wqh.lock);
|
|
|
|
__add_wait_queue(&ctx->fd_wqh, &wait);
|
|
|
|
for (;;) {
|
|
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
|
|
|
uwq = find_userfault(ctx);
|
|
|
|
if (uwq) {
|
2015-09-04 22:47:23 +00:00
|
|
|
/*
|
|
|
|
* Use a seqcount to repeat the lockless check
|
|
|
|
* in wake_userfault() to avoid missing
|
|
|
|
* wakeups because during the refile both
|
|
|
|
* waitqueue could become empty if this is the
|
|
|
|
* only userfault.
|
|
|
|
*/
|
|
|
|
write_seqcount_begin(&ctx->refile_seq);
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
2015-09-04 22:46:44 +00:00
|
|
|
* The fault_pending_wqh.lock prevents the uwq
|
|
|
|
* to disappear from under us.
|
|
|
|
*
|
|
|
|
* Refile this userfault from
|
|
|
|
* fault_pending_wqh to fault_wqh, it's not
|
|
|
|
* pending anymore after we read it.
|
|
|
|
*
|
|
|
|
* Use list_del() by hand (as
|
|
|
|
* userfaultfd_wake_function also uses
|
|
|
|
* list_del_init() by hand) to be sure nobody
|
|
|
|
* changes __remove_wait_queue() to use
|
|
|
|
* list_del_init() in turn breaking the
|
|
|
|
* !list_empty_careful() check in
|
|
|
|
* handle_userfault(). The uwq->wq.task_list
|
|
|
|
* must never be empty at any time during the
|
|
|
|
* refile, or the waitqueue could disappear
|
|
|
|
* from under us. The "wait_queue_head_t"
|
|
|
|
* parameter of __remove_wait_queue() is unused
|
|
|
|
* anyway.
|
2015-09-04 22:46:31 +00:00
|
|
|
*/
|
2015-09-04 22:46:44 +00:00
|
|
|
list_del(&uwq->wq.task_list);
|
|
|
|
__add_wait_queue(&ctx->fault_wqh, &uwq->wq);
|
|
|
|
|
2015-09-04 22:47:23 +00:00
|
|
|
write_seqcount_end(&ctx->refile_seq);
|
|
|
|
|
2015-09-04 22:46:37 +00:00
|
|
|
/* careful to always initialize msg if ret == 0 */
|
|
|
|
*msg = uwq->msg;
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2017-02-22 23:42:21 +00:00
|
|
|
|
|
|
|
spin_lock(&ctx->event_wqh.lock);
|
|
|
|
uwq = find_userfault_evt(ctx);
|
|
|
|
if (uwq) {
|
|
|
|
*msg = uwq->msg;
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
if (uwq->msg.event == UFFD_EVENT_FORK) {
|
|
|
|
fork_nctx = (struct userfaultfd_ctx *)
|
|
|
|
(unsigned long)
|
|
|
|
uwq->msg.arg.reserved.reserved1;
|
|
|
|
list_move(&uwq->wq.task_list, &fork_event);
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:21 +00:00
|
|
|
userfaultfd_event_complete(ctx, uwq);
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
if (signal_pending(current)) {
|
|
|
|
ret = -ERESTARTSYS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (no_wait) {
|
|
|
|
ret = -EAGAIN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
spin_unlock(&ctx->fd_wqh.lock);
|
|
|
|
schedule();
|
|
|
|
spin_lock(&ctx->fd_wqh.lock);
|
|
|
|
}
|
|
|
|
__remove_wait_queue(&ctx->fd_wqh, &wait);
|
|
|
|
__set_current_state(TASK_RUNNING);
|
|
|
|
spin_unlock(&ctx->fd_wqh.lock);
|
|
|
|
|
2017-02-22 23:42:27 +00:00
|
|
|
if (!ret && msg->event == UFFD_EVENT_FORK) {
|
|
|
|
ret = resolve_userfault_fork(ctx, fork_nctx, msg);
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
spin_lock(&ctx->event_wqh.lock);
|
|
|
|
if (!list_empty(&fork_event)) {
|
|
|
|
uwq = list_first_entry(&fork_event,
|
|
|
|
typeof(*uwq),
|
|
|
|
wq.task_list);
|
|
|
|
list_del(&uwq->wq.task_list);
|
|
|
|
__add_wait_queue(&ctx->event_wqh, &uwq->wq);
|
|
|
|
userfaultfd_event_complete(ctx, uwq);
|
|
|
|
}
|
|
|
|
spin_unlock(&ctx->event_wqh.lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t userfaultfd_read(struct file *file, char __user *buf,
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = file->private_data;
|
|
|
|
ssize_t _ret, ret = 0;
|
2015-09-04 22:46:37 +00:00
|
|
|
struct uffd_msg msg;
|
2015-09-04 22:46:31 +00:00
|
|
|
int no_wait = file->f_flags & O_NONBLOCK;
|
|
|
|
|
|
|
|
if (ctx->state == UFFD_STATE_WAIT_API)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
for (;;) {
|
2015-09-04 22:46:37 +00:00
|
|
|
if (count < sizeof(msg))
|
2015-09-04 22:46:31 +00:00
|
|
|
return ret ? ret : -EINVAL;
|
2015-09-04 22:46:37 +00:00
|
|
|
_ret = userfaultfd_ctx_read(ctx, no_wait, &msg);
|
2015-09-04 22:46:31 +00:00
|
|
|
if (_ret < 0)
|
|
|
|
return ret ? ret : _ret;
|
2015-09-04 22:46:37 +00:00
|
|
|
if (copy_to_user((__u64 __user *) buf, &msg, sizeof(msg)))
|
2015-09-04 22:46:31 +00:00
|
|
|
return ret ? ret : -EFAULT;
|
2015-09-04 22:46:37 +00:00
|
|
|
ret += sizeof(msg);
|
|
|
|
buf += sizeof(msg);
|
|
|
|
count -= sizeof(msg);
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Allow to read more than one fault at time but only
|
|
|
|
* block if waiting for the very first one.
|
|
|
|
*/
|
|
|
|
no_wait = O_NONBLOCK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __wake_userfault(struct userfaultfd_ctx *ctx,
|
|
|
|
struct userfaultfd_wake_range *range)
|
|
|
|
{
|
|
|
|
unsigned long start, end;
|
|
|
|
|
|
|
|
start = range->start;
|
|
|
|
end = range->start + range->len;
|
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
/* wake all in the range and autoremove */
|
2015-09-04 22:46:44 +00:00
|
|
|
if (waitqueue_active(&ctx->fault_pending_wqh))
|
2015-09-22 21:58:49 +00:00
|
|
|
__wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL,
|
2015-09-04 22:46:44 +00:00
|
|
|
range);
|
|
|
|
if (waitqueue_active(&ctx->fault_wqh))
|
2015-09-22 21:58:49 +00:00
|
|
|
__wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, range);
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
|
|
|
|
struct userfaultfd_wake_range *range)
|
|
|
|
{
|
2015-09-04 22:47:23 +00:00
|
|
|
unsigned seq;
|
|
|
|
bool need_wakeup;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* To be sure waitqueue_active() is not reordered by the CPU
|
|
|
|
* before the pagetable update, use an explicit SMP memory
|
|
|
|
* barrier here. PT lock release or up_read(mmap_sem) still
|
|
|
|
* have release semantics that can allow the
|
|
|
|
* waitqueue_active() to be reordered before the pte update.
|
|
|
|
*/
|
|
|
|
smp_mb();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use waitqueue_active because it's very frequent to
|
|
|
|
* change the address space atomically even if there are no
|
|
|
|
* userfaults yet. So we take the spinlock only when we're
|
|
|
|
* sure we've userfaults to wake.
|
|
|
|
*/
|
2015-09-04 22:47:23 +00:00
|
|
|
do {
|
|
|
|
seq = read_seqcount_begin(&ctx->refile_seq);
|
|
|
|
need_wakeup = waitqueue_active(&ctx->fault_pending_wqh) ||
|
|
|
|
waitqueue_active(&ctx->fault_wqh);
|
|
|
|
cond_resched();
|
|
|
|
} while (read_seqcount_retry(&ctx->refile_seq, seq));
|
|
|
|
if (need_wakeup)
|
2015-09-04 22:46:31 +00:00
|
|
|
__wake_userfault(ctx, range);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline int validate_range(struct mm_struct *mm,
|
|
|
|
__u64 start, __u64 len)
|
|
|
|
{
|
|
|
|
__u64 task_size = mm->task_size;
|
|
|
|
|
|
|
|
if (start & ~PAGE_MASK)
|
|
|
|
return -EINVAL;
|
|
|
|
if (len & ~PAGE_MASK)
|
|
|
|
return -EINVAL;
|
|
|
|
if (!len)
|
|
|
|
return -EINVAL;
|
|
|
|
if (start < mmap_min_addr)
|
|
|
|
return -EINVAL;
|
|
|
|
if (start >= task_size)
|
|
|
|
return -EINVAL;
|
|
|
|
if (len > task_size - start)
|
|
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:43:22 +00:00
|
|
|
static inline bool vma_can_userfault(struct vm_area_struct *vma)
|
|
|
|
{
|
2017-02-22 23:43:40 +00:00
|
|
|
return vma_is_anonymous(vma) || is_vm_hugetlb_page(vma) ||
|
|
|
|
vma_is_shmem(vma);
|
2017-02-22 23:43:22 +00:00
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
struct mm_struct *mm = ctx->mm;
|
|
|
|
struct vm_area_struct *vma, *prev, *cur;
|
|
|
|
int ret;
|
|
|
|
struct uffdio_register uffdio_register;
|
|
|
|
struct uffdio_register __user *user_uffdio_register;
|
|
|
|
unsigned long vm_flags, new_flags;
|
|
|
|
bool found;
|
2017-02-22 23:43:40 +00:00
|
|
|
bool non_anon_pages;
|
2015-09-04 22:46:31 +00:00
|
|
|
unsigned long start, end, vma_end;
|
|
|
|
|
|
|
|
user_uffdio_register = (struct uffdio_register __user *) arg;
|
|
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_from_user(&uffdio_register, user_uffdio_register,
|
|
|
|
sizeof(uffdio_register)-sizeof(__u64)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (!uffdio_register.mode)
|
|
|
|
goto out;
|
|
|
|
if (uffdio_register.mode & ~(UFFDIO_REGISTER_MODE_MISSING|
|
|
|
|
UFFDIO_REGISTER_MODE_WP))
|
|
|
|
goto out;
|
|
|
|
vm_flags = 0;
|
|
|
|
if (uffdio_register.mode & UFFDIO_REGISTER_MODE_MISSING)
|
|
|
|
vm_flags |= VM_UFFD_MISSING;
|
|
|
|
if (uffdio_register.mode & UFFDIO_REGISTER_MODE_WP) {
|
|
|
|
vm_flags |= VM_UFFD_WP;
|
|
|
|
/*
|
|
|
|
* FIXME: remove the below error constraint by
|
|
|
|
* implementing the wprotect tracking mode.
|
|
|
|
*/
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = validate_range(mm, uffdio_register.range.start,
|
|
|
|
uffdio_register.range.len);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
start = uffdio_register.range.start;
|
|
|
|
end = start + uffdio_register.range.len;
|
|
|
|
|
2016-05-20 23:58:36 +00:00
|
|
|
ret = -ENOMEM;
|
|
|
|
if (!mmget_not_zero(mm))
|
|
|
|
goto out;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
down_write(&mm->mmap_sem);
|
|
|
|
vma = find_vma_prev(mm, start, &prev);
|
|
|
|
if (!vma)
|
|
|
|
goto out_unlock;
|
|
|
|
|
|
|
|
/* check that there's at least one vma in the range */
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (vma->vm_start >= end)
|
|
|
|
goto out_unlock;
|
|
|
|
|
2017-02-22 23:43:04 +00:00
|
|
|
/*
|
|
|
|
* If the first vma contains huge pages, make sure start address
|
|
|
|
* is aligned to huge page size.
|
|
|
|
*/
|
|
|
|
if (is_vm_hugetlb_page(vma)) {
|
|
|
|
unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
|
|
|
|
|
|
|
|
if (start & (vma_hpagesize - 1))
|
|
|
|
goto out_unlock;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Search for not compatible vmas.
|
|
|
|
*/
|
|
|
|
found = false;
|
2017-02-22 23:43:40 +00:00
|
|
|
non_anon_pages = false;
|
2015-09-04 22:46:31 +00:00
|
|
|
for (cur = vma; cur && cur->vm_start < end; cur = cur->vm_next) {
|
|
|
|
cond_resched();
|
|
|
|
|
|
|
|
BUG_ON(!!cur->vm_userfaultfd_ctx.ctx ^
|
|
|
|
!!(cur->vm_flags & (VM_UFFD_MISSING | VM_UFFD_WP)));
|
|
|
|
|
|
|
|
/* check not compatible vmas */
|
|
|
|
ret = -EINVAL;
|
2017-02-22 23:43:22 +00:00
|
|
|
if (!vma_can_userfault(cur))
|
2015-09-04 22:46:31 +00:00
|
|
|
goto out_unlock;
|
2017-02-22 23:43:04 +00:00
|
|
|
/*
|
|
|
|
* If this vma contains ending address, and huge pages
|
|
|
|
* check alignment.
|
|
|
|
*/
|
|
|
|
if (is_vm_hugetlb_page(cur) && end <= cur->vm_end &&
|
|
|
|
end > cur->vm_start) {
|
|
|
|
unsigned long vma_hpagesize = vma_kernel_pagesize(cur);
|
|
|
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
|
|
|
if (end & (vma_hpagesize - 1))
|
|
|
|
goto out_unlock;
|
|
|
|
}
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that this vma isn't already owned by a
|
|
|
|
* different userfaultfd. We can't allow more than one
|
|
|
|
* userfaultfd to own a single vma simultaneously or we
|
|
|
|
* wouldn't know which one to deliver the userfaults to.
|
|
|
|
*/
|
|
|
|
ret = -EBUSY;
|
|
|
|
if (cur->vm_userfaultfd_ctx.ctx &&
|
|
|
|
cur->vm_userfaultfd_ctx.ctx != ctx)
|
|
|
|
goto out_unlock;
|
|
|
|
|
2017-02-22 23:43:04 +00:00
|
|
|
/*
|
|
|
|
* Note vmas containing huge pages
|
|
|
|
*/
|
2017-02-22 23:43:40 +00:00
|
|
|
if (is_vm_hugetlb_page(cur) || vma_is_shmem(cur))
|
|
|
|
non_anon_pages = true;
|
2017-02-22 23:43:04 +00:00
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
BUG_ON(!found);
|
|
|
|
|
|
|
|
if (vma->vm_start < start)
|
|
|
|
prev = vma;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
do {
|
|
|
|
cond_resched();
|
|
|
|
|
2017-02-22 23:43:22 +00:00
|
|
|
BUG_ON(!vma_can_userfault(vma));
|
2015-09-04 22:46:31 +00:00
|
|
|
BUG_ON(vma->vm_userfaultfd_ctx.ctx &&
|
|
|
|
vma->vm_userfaultfd_ctx.ctx != ctx);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Nothing to do: this vma is already registered into this
|
|
|
|
* userfaultfd and with the right tracking mode too.
|
|
|
|
*/
|
|
|
|
if (vma->vm_userfaultfd_ctx.ctx == ctx &&
|
|
|
|
(vma->vm_flags & vm_flags) == vm_flags)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
if (vma->vm_start > start)
|
|
|
|
start = vma->vm_start;
|
|
|
|
vma_end = min(end, vma->vm_end);
|
|
|
|
|
|
|
|
new_flags = (vma->vm_flags & ~vm_flags) | vm_flags;
|
|
|
|
prev = vma_merge(mm, prev, start, vma_end, new_flags,
|
|
|
|
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
|
|
|
vma_policy(vma),
|
|
|
|
((struct vm_userfaultfd_ctx){ ctx }));
|
|
|
|
if (prev) {
|
|
|
|
vma = prev;
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
if (vma->vm_start < start) {
|
|
|
|
ret = split_vma(mm, vma, start, 1);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (vma->vm_end > end) {
|
|
|
|
ret = split_vma(mm, vma, end, 0);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
next:
|
|
|
|
/*
|
|
|
|
* In the vma_merge() successful mprotect-like case 8:
|
|
|
|
* the next vma was merged into the current one and
|
|
|
|
* the current one has not been updated yet.
|
|
|
|
*/
|
|
|
|
vma->vm_flags = new_flags;
|
|
|
|
vma->vm_userfaultfd_ctx.ctx = ctx;
|
|
|
|
|
|
|
|
skip:
|
|
|
|
prev = vma;
|
|
|
|
start = vma->vm_end;
|
|
|
|
vma = vma->vm_next;
|
|
|
|
} while (vma && vma->vm_start < end);
|
|
|
|
out_unlock:
|
|
|
|
up_write(&mm->mmap_sem);
|
2016-05-20 23:58:36 +00:00
|
|
|
mmput(mm);
|
2015-09-04 22:46:31 +00:00
|
|
|
if (!ret) {
|
|
|
|
/*
|
|
|
|
* Now that we scanned all vmas we can already tell
|
|
|
|
* userland which ioctls methods are guaranteed to
|
|
|
|
* succeed on this range.
|
|
|
|
*/
|
2017-02-22 23:43:40 +00:00
|
|
|
if (put_user(non_anon_pages ? UFFD_API_RANGE_IOCTLS_BASIC :
|
2017-02-22 23:43:04 +00:00
|
|
|
UFFD_API_RANGE_IOCTLS,
|
2015-09-04 22:46:31 +00:00
|
|
|
&user_uffdio_register->ioctls))
|
|
|
|
ret = -EFAULT;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
struct mm_struct *mm = ctx->mm;
|
|
|
|
struct vm_area_struct *vma, *prev, *cur;
|
|
|
|
int ret;
|
|
|
|
struct uffdio_range uffdio_unregister;
|
|
|
|
unsigned long new_flags;
|
|
|
|
bool found;
|
|
|
|
unsigned long start, end, vma_end;
|
|
|
|
const void __user *buf = (void __user *)arg;
|
|
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = validate_range(mm, uffdio_unregister.start,
|
|
|
|
uffdio_unregister.len);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
start = uffdio_unregister.start;
|
|
|
|
end = start + uffdio_unregister.len;
|
|
|
|
|
2016-05-20 23:58:36 +00:00
|
|
|
ret = -ENOMEM;
|
|
|
|
if (!mmget_not_zero(mm))
|
|
|
|
goto out;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
down_write(&mm->mmap_sem);
|
|
|
|
vma = find_vma_prev(mm, start, &prev);
|
|
|
|
if (!vma)
|
|
|
|
goto out_unlock;
|
|
|
|
|
|
|
|
/* check that there's at least one vma in the range */
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (vma->vm_start >= end)
|
|
|
|
goto out_unlock;
|
|
|
|
|
2017-02-22 23:43:04 +00:00
|
|
|
/*
|
|
|
|
* If the first vma contains huge pages, make sure start address
|
|
|
|
* is aligned to huge page size.
|
|
|
|
*/
|
|
|
|
if (is_vm_hugetlb_page(vma)) {
|
|
|
|
unsigned long vma_hpagesize = vma_kernel_pagesize(vma);
|
|
|
|
|
|
|
|
if (start & (vma_hpagesize - 1))
|
|
|
|
goto out_unlock;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* Search for not compatible vmas.
|
|
|
|
*/
|
|
|
|
found = false;
|
|
|
|
ret = -EINVAL;
|
|
|
|
for (cur = vma; cur && cur->vm_start < end; cur = cur->vm_next) {
|
|
|
|
cond_resched();
|
|
|
|
|
|
|
|
BUG_ON(!!cur->vm_userfaultfd_ctx.ctx ^
|
|
|
|
!!(cur->vm_flags & (VM_UFFD_MISSING | VM_UFFD_WP)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check not compatible vmas, not strictly required
|
|
|
|
* here as not compatible vmas cannot have an
|
|
|
|
* userfaultfd_ctx registered on them, but this
|
|
|
|
* provides for more strict behavior to notice
|
|
|
|
* unregistration errors.
|
|
|
|
*/
|
2017-02-22 23:43:22 +00:00
|
|
|
if (!vma_can_userfault(cur))
|
2015-09-04 22:46:31 +00:00
|
|
|
goto out_unlock;
|
|
|
|
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
BUG_ON(!found);
|
|
|
|
|
|
|
|
if (vma->vm_start < start)
|
|
|
|
prev = vma;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
do {
|
|
|
|
cond_resched();
|
|
|
|
|
2017-02-22 23:43:22 +00:00
|
|
|
BUG_ON(!vma_can_userfault(vma));
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Nothing to do: this vma is already registered into this
|
|
|
|
* userfaultfd and with the right tracking mode too.
|
|
|
|
*/
|
|
|
|
if (!vma->vm_userfaultfd_ctx.ctx)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
if (vma->vm_start > start)
|
|
|
|
start = vma->vm_start;
|
|
|
|
vma_end = min(end, vma->vm_end);
|
|
|
|
|
2017-02-22 23:42:46 +00:00
|
|
|
if (userfaultfd_missing(vma)) {
|
|
|
|
/*
|
|
|
|
* Wake any concurrent pending userfault while
|
|
|
|
* we unregister, so they will not hang
|
|
|
|
* permanently and it avoids userland to call
|
|
|
|
* UFFDIO_WAKE explicitly.
|
|
|
|
*/
|
|
|
|
struct userfaultfd_wake_range range;
|
|
|
|
range.start = start;
|
|
|
|
range.len = vma_end - start;
|
|
|
|
wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range);
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
new_flags = vma->vm_flags & ~(VM_UFFD_MISSING | VM_UFFD_WP);
|
|
|
|
prev = vma_merge(mm, prev, start, vma_end, new_flags,
|
|
|
|
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
|
|
|
vma_policy(vma),
|
|
|
|
NULL_VM_UFFD_CTX);
|
|
|
|
if (prev) {
|
|
|
|
vma = prev;
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
if (vma->vm_start < start) {
|
|
|
|
ret = split_vma(mm, vma, start, 1);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (vma->vm_end > end) {
|
|
|
|
ret = split_vma(mm, vma, end, 0);
|
|
|
|
if (ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
next:
|
|
|
|
/*
|
|
|
|
* In the vma_merge() successful mprotect-like case 8:
|
|
|
|
* the next vma was merged into the current one and
|
|
|
|
* the current one has not been updated yet.
|
|
|
|
*/
|
|
|
|
vma->vm_flags = new_flags;
|
|
|
|
vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
|
|
|
|
|
|
|
|
skip:
|
|
|
|
prev = vma;
|
|
|
|
start = vma->vm_end;
|
|
|
|
vma = vma->vm_next;
|
|
|
|
} while (vma && vma->vm_start < end);
|
|
|
|
out_unlock:
|
|
|
|
up_write(&mm->mmap_sem);
|
2016-05-20 23:58:36 +00:00
|
|
|
mmput(mm);
|
2015-09-04 22:46:31 +00:00
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-09-04 22:46:41 +00:00
|
|
|
* userfaultfd_wake may be used in combination with the
|
|
|
|
* UFFDIO_*_MODE_DONTWAKE to wakeup userfaults in batches.
|
2015-09-04 22:46:31 +00:00
|
|
|
*/
|
|
|
|
static int userfaultfd_wake(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct uffdio_range uffdio_wake;
|
|
|
|
struct userfaultfd_wake_range range;
|
|
|
|
const void __user *buf = (void __user *)arg;
|
|
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = validate_range(ctx->mm, uffdio_wake.start, uffdio_wake.len);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
range.start = uffdio_wake.start;
|
|
|
|
range.len = uffdio_wake.len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* len == 0 means wake all and we don't want to wake all here,
|
|
|
|
* so check it again to be sure.
|
|
|
|
*/
|
|
|
|
VM_BUG_ON(!range.len);
|
|
|
|
|
|
|
|
wake_userfault(ctx, &range);
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:47:11 +00:00
|
|
|
static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
__s64 ret;
|
|
|
|
struct uffdio_copy uffdio_copy;
|
|
|
|
struct uffdio_copy __user *user_uffdio_copy;
|
|
|
|
struct userfaultfd_wake_range range;
|
|
|
|
|
|
|
|
user_uffdio_copy = (struct uffdio_copy __user *) arg;
|
|
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_from_user(&uffdio_copy, user_uffdio_copy,
|
|
|
|
/* don't copy "copy" last field */
|
|
|
|
sizeof(uffdio_copy)-sizeof(__s64)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
/*
|
|
|
|
* double check for wraparound just in case. copy_from_user()
|
|
|
|
* will later check uffdio_copy.src + uffdio_copy.len to fit
|
|
|
|
* in the userland range.
|
|
|
|
*/
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (uffdio_copy.src + uffdio_copy.len <= uffdio_copy.src)
|
|
|
|
goto out;
|
|
|
|
if (uffdio_copy.mode & ~UFFDIO_COPY_MODE_DONTWAKE)
|
|
|
|
goto out;
|
2016-05-20 23:58:36 +00:00
|
|
|
if (mmget_not_zero(ctx->mm)) {
|
|
|
|
ret = mcopy_atomic(ctx->mm, uffdio_copy.dst, uffdio_copy.src,
|
|
|
|
uffdio_copy.len);
|
|
|
|
mmput(ctx->mm);
|
2017-02-24 22:58:31 +00:00
|
|
|
} else {
|
|
|
|
return -ENOSPC;
|
2016-05-20 23:58:36 +00:00
|
|
|
}
|
2015-09-04 22:47:11 +00:00
|
|
|
if (unlikely(put_user(ret, &user_uffdio_copy->copy)))
|
|
|
|
return -EFAULT;
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
BUG_ON(!ret);
|
|
|
|
/* len == 0 would wake all */
|
|
|
|
range.len = ret;
|
|
|
|
if (!(uffdio_copy.mode & UFFDIO_COPY_MODE_DONTWAKE)) {
|
|
|
|
range.start = uffdio_copy.dst;
|
|
|
|
wake_userfault(ctx, &range);
|
|
|
|
}
|
|
|
|
ret = range.len == uffdio_copy.len ? 0 : -EAGAIN;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
__s64 ret;
|
|
|
|
struct uffdio_zeropage uffdio_zeropage;
|
|
|
|
struct uffdio_zeropage __user *user_uffdio_zeropage;
|
|
|
|
struct userfaultfd_wake_range range;
|
|
|
|
|
|
|
|
user_uffdio_zeropage = (struct uffdio_zeropage __user *) arg;
|
|
|
|
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_from_user(&uffdio_zeropage, user_uffdio_zeropage,
|
|
|
|
/* don't copy "zeropage" last field */
|
|
|
|
sizeof(uffdio_zeropage)-sizeof(__s64)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = validate_range(ctx->mm, uffdio_zeropage.range.start,
|
|
|
|
uffdio_zeropage.range.len);
|
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (uffdio_zeropage.mode & ~UFFDIO_ZEROPAGE_MODE_DONTWAKE)
|
|
|
|
goto out;
|
|
|
|
|
2016-05-20 23:58:36 +00:00
|
|
|
if (mmget_not_zero(ctx->mm)) {
|
|
|
|
ret = mfill_zeropage(ctx->mm, uffdio_zeropage.range.start,
|
|
|
|
uffdio_zeropage.range.len);
|
|
|
|
mmput(ctx->mm);
|
|
|
|
}
|
2015-09-04 22:47:11 +00:00
|
|
|
if (unlikely(put_user(ret, &user_uffdio_zeropage->zeropage)))
|
|
|
|
return -EFAULT;
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
/* len == 0 would wake all */
|
|
|
|
BUG_ON(!ret);
|
|
|
|
range.len = ret;
|
|
|
|
if (!(uffdio_zeropage.mode & UFFDIO_ZEROPAGE_MODE_DONTWAKE)) {
|
|
|
|
range.start = uffdio_zeropage.range.start;
|
|
|
|
wake_userfault(ctx, &range);
|
|
|
|
}
|
|
|
|
ret = range.len == uffdio_zeropage.range.len ? 0 : -EAGAIN;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-02-22 23:42:21 +00:00
|
|
|
static inline unsigned int uffd_ctx_features(__u64 user_features)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* For the current set of features the bits just coincide
|
|
|
|
*/
|
|
|
|
return (unsigned int)user_features;
|
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/*
|
|
|
|
* userland asks for a certain API version and we return which bits
|
|
|
|
* and ioctl commands are implemented in this kernel for such API
|
|
|
|
* version or -EINVAL if unknown.
|
|
|
|
*/
|
|
|
|
static int userfaultfd_api(struct userfaultfd_ctx *ctx,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
struct uffdio_api uffdio_api;
|
|
|
|
void __user *buf = (void __user *)arg;
|
|
|
|
int ret;
|
2017-02-22 23:42:24 +00:00
|
|
|
__u64 features;
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
if (ctx->state != UFFD_STATE_WAIT_API)
|
|
|
|
goto out;
|
|
|
|
ret = -EFAULT;
|
2015-09-04 22:46:37 +00:00
|
|
|
if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
|
2015-09-04 22:46:31 +00:00
|
|
|
goto out;
|
2017-02-22 23:42:24 +00:00
|
|
|
features = uffdio_api.features;
|
|
|
|
if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) {
|
2015-09-04 22:46:31 +00:00
|
|
|
memset(&uffdio_api, 0, sizeof(uffdio_api));
|
|
|
|
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
|
|
|
|
goto out;
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2017-02-22 23:42:24 +00:00
|
|
|
/* report all available features and ioctls to userland */
|
|
|
|
uffdio_api.features = UFFD_API_FEATURES;
|
2015-09-04 22:46:31 +00:00
|
|
|
uffdio_api.ioctls = UFFD_API_IOCTLS;
|
|
|
|
ret = -EFAULT;
|
|
|
|
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
|
|
|
|
goto out;
|
|
|
|
ctx->state = UFFD_STATE_RUNNING;
|
2017-02-22 23:42:24 +00:00
|
|
|
/* only enable the requested features for this uffd context */
|
|
|
|
ctx->features = uffd_ctx_features(features);
|
2015-09-04 22:46:31 +00:00
|
|
|
ret = 0;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static long userfaultfd_ioctl(struct file *file, unsigned cmd,
|
|
|
|
unsigned long arg)
|
|
|
|
{
|
|
|
|
int ret = -EINVAL;
|
|
|
|
struct userfaultfd_ctx *ctx = file->private_data;
|
|
|
|
|
2015-09-04 22:47:15 +00:00
|
|
|
if (cmd != UFFDIO_API && ctx->state == UFFD_STATE_WAIT_API)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
switch(cmd) {
|
|
|
|
case UFFDIO_API:
|
|
|
|
ret = userfaultfd_api(ctx, arg);
|
|
|
|
break;
|
|
|
|
case UFFDIO_REGISTER:
|
|
|
|
ret = userfaultfd_register(ctx, arg);
|
|
|
|
break;
|
|
|
|
case UFFDIO_UNREGISTER:
|
|
|
|
ret = userfaultfd_unregister(ctx, arg);
|
|
|
|
break;
|
|
|
|
case UFFDIO_WAKE:
|
|
|
|
ret = userfaultfd_wake(ctx, arg);
|
|
|
|
break;
|
2015-09-04 22:47:11 +00:00
|
|
|
case UFFDIO_COPY:
|
|
|
|
ret = userfaultfd_copy(ctx, arg);
|
|
|
|
break;
|
|
|
|
case UFFDIO_ZEROPAGE:
|
|
|
|
ret = userfaultfd_zeropage(ctx, arg);
|
|
|
|
break;
|
2015-09-04 22:46:31 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
static void userfaultfd_show_fdinfo(struct seq_file *m, struct file *f)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = f->private_data;
|
|
|
|
wait_queue_t *wq;
|
|
|
|
struct userfaultfd_wait_queue *uwq;
|
|
|
|
unsigned long pending = 0, total = 0;
|
|
|
|
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_lock(&ctx->fault_pending_wqh.lock);
|
|
|
|
list_for_each_entry(wq, &ctx->fault_pending_wqh.task_list, task_list) {
|
|
|
|
uwq = container_of(wq, struct userfaultfd_wait_queue, wq);
|
|
|
|
pending++;
|
|
|
|
total++;
|
|
|
|
}
|
2015-09-04 22:46:31 +00:00
|
|
|
list_for_each_entry(wq, &ctx->fault_wqh.task_list, task_list) {
|
|
|
|
uwq = container_of(wq, struct userfaultfd_wait_queue, wq);
|
|
|
|
total++;
|
|
|
|
}
|
2015-09-04 22:46:44 +00:00
|
|
|
spin_unlock(&ctx->fault_pending_wqh.lock);
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If more protocols will be added, there will be all shown
|
|
|
|
* separated by a space. Like this:
|
|
|
|
* protocols: aa:... bb:...
|
|
|
|
*/
|
|
|
|
seq_printf(m, "pending:\t%lu\ntotal:\t%lu\nAPI:\t%Lx:%x:%Lx\n",
|
2015-09-04 22:46:34 +00:00
|
|
|
pending, total, UFFD_API, UFFD_API_FEATURES,
|
2015-09-04 22:46:31 +00:00
|
|
|
UFFD_API_IOCTLS|UFFD_API_RANGE_IOCTLS);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static const struct file_operations userfaultfd_fops = {
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
.show_fdinfo = userfaultfd_show_fdinfo,
|
|
|
|
#endif
|
|
|
|
.release = userfaultfd_release,
|
|
|
|
.poll = userfaultfd_poll,
|
|
|
|
.read = userfaultfd_read,
|
|
|
|
.unlocked_ioctl = userfaultfd_ioctl,
|
|
|
|
.compat_ioctl = userfaultfd_ioctl,
|
|
|
|
.llseek = noop_llseek,
|
|
|
|
};
|
|
|
|
|
2015-09-04 22:46:48 +00:00
|
|
|
static void init_once_userfaultfd_ctx(void *mem)
|
|
|
|
{
|
|
|
|
struct userfaultfd_ctx *ctx = (struct userfaultfd_ctx *) mem;
|
|
|
|
|
|
|
|
init_waitqueue_head(&ctx->fault_pending_wqh);
|
|
|
|
init_waitqueue_head(&ctx->fault_wqh);
|
2017-02-22 23:42:21 +00:00
|
|
|
init_waitqueue_head(&ctx->event_wqh);
|
2015-09-04 22:46:48 +00:00
|
|
|
init_waitqueue_head(&ctx->fd_wqh);
|
2015-09-04 22:47:23 +00:00
|
|
|
seqcount_init(&ctx->refile_seq);
|
2015-09-04 22:46:48 +00:00
|
|
|
}
|
|
|
|
|
2015-09-04 22:46:31 +00:00
|
|
|
/**
|
2017-02-27 22:28:47 +00:00
|
|
|
* userfaultfd_file_create - Creates a userfaultfd file pointer.
|
2015-09-04 22:46:31 +00:00
|
|
|
* @flags: Flags for the userfaultfd file.
|
|
|
|
*
|
2017-02-27 22:28:47 +00:00
|
|
|
* This function creates a userfaultfd file pointer, w/out installing
|
2015-09-04 22:46:31 +00:00
|
|
|
* it into the fd table. This is useful when the userfaultfd file is
|
|
|
|
* used during the initialization of data structures that require
|
|
|
|
* extra setup after the userfaultfd creation. So the userfaultfd
|
|
|
|
* creation is split into the file pointer creation phase, and the
|
|
|
|
* file descriptor installation phase. In this way races with
|
|
|
|
* userspace closing the newly installed file descriptor can be
|
2017-02-27 22:28:47 +00:00
|
|
|
* avoided. Returns a userfaultfd file pointer, or a proper error
|
2015-09-04 22:46:31 +00:00
|
|
|
* pointer.
|
|
|
|
*/
|
|
|
|
static struct file *userfaultfd_file_create(int flags)
|
|
|
|
{
|
|
|
|
struct file *file;
|
|
|
|
struct userfaultfd_ctx *ctx;
|
|
|
|
|
|
|
|
BUG_ON(!current->mm);
|
|
|
|
|
|
|
|
/* Check the UFFD_* constants for consistency. */
|
|
|
|
BUILD_BUG_ON(UFFD_CLOEXEC != O_CLOEXEC);
|
|
|
|
BUILD_BUG_ON(UFFD_NONBLOCK != O_NONBLOCK);
|
|
|
|
|
|
|
|
file = ERR_PTR(-EINVAL);
|
|
|
|
if (flags & ~UFFD_SHARED_FCNTL_FLAGS)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
file = ERR_PTR(-ENOMEM);
|
2015-09-04 22:46:48 +00:00
|
|
|
ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL);
|
2015-09-04 22:46:31 +00:00
|
|
|
if (!ctx)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
atomic_set(&ctx->refcount, 1);
|
|
|
|
ctx->flags = flags;
|
2017-02-22 23:42:21 +00:00
|
|
|
ctx->features = 0;
|
2015-09-04 22:46:31 +00:00
|
|
|
ctx->state = UFFD_STATE_WAIT_API;
|
|
|
|
ctx->released = false;
|
|
|
|
ctx->mm = current->mm;
|
|
|
|
/* prevent the mm struct to be freed */
|
2017-02-27 22:30:07 +00:00
|
|
|
mmgrab(ctx->mm);
|
2015-09-04 22:46:31 +00:00
|
|
|
|
|
|
|
file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
|
|
|
|
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
|
2015-09-17 23:01:54 +00:00
|
|
|
if (IS_ERR(file)) {
|
2016-05-20 23:58:36 +00:00
|
|
|
mmdrop(ctx->mm);
|
2015-09-04 22:46:48 +00:00
|
|
|
kmem_cache_free(userfaultfd_ctx_cachep, ctx);
|
2015-09-17 23:01:54 +00:00
|
|
|
}
|
2015-09-04 22:46:31 +00:00
|
|
|
out:
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
SYSCALL_DEFINE1(userfaultfd, int, flags)
|
|
|
|
{
|
|
|
|
int fd, error;
|
|
|
|
struct file *file;
|
|
|
|
|
|
|
|
error = get_unused_fd_flags(flags & UFFD_SHARED_FCNTL_FLAGS);
|
|
|
|
if (error < 0)
|
|
|
|
return error;
|
|
|
|
fd = error;
|
|
|
|
|
|
|
|
file = userfaultfd_file_create(flags);
|
|
|
|
if (IS_ERR(file)) {
|
|
|
|
error = PTR_ERR(file);
|
|
|
|
goto err_put_unused_fd;
|
|
|
|
}
|
|
|
|
fd_install(fd, file);
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
err_put_unused_fd:
|
|
|
|
put_unused_fd(fd);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
2015-09-04 22:46:48 +00:00
|
|
|
|
|
|
|
static int __init userfaultfd_init(void)
|
|
|
|
{
|
|
|
|
userfaultfd_ctx_cachep = kmem_cache_create("userfaultfd_ctx_cache",
|
|
|
|
sizeof(struct userfaultfd_ctx),
|
|
|
|
0,
|
|
|
|
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
|
|
|
|
init_once_userfaultfd_ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
__initcall(userfaultfd_init);
|