diff options
author | Andrea Arcangeli <aarcange@redhat.com> | 2017-03-09 16:16:54 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-09 17:01:09 -0800 |
commit | 8c9e7bb7a41f2bbd54b2caefb274fb3de239819f (patch) | |
tree | e7ebed49b9c69b07a09654c8298747eedb97781c /fs | |
parent | 9a69a829f9b656c2a220d65a94ecf7b5887c5da1 (diff) | |
download | linux-8c9e7bb7a41f2bbd54b2caefb274fb3de239819f.tar.gz linux-8c9e7bb7a41f2bbd54b2caefb274fb3de239819f.tar.bz2 linux-8c9e7bb7a41f2bbd54b2caefb274fb3de239819f.zip |
userfaultfd: non-cooperative: release all ctx in dup_userfaultfd_complete
Don't stop running dup_fctx() even if userfaultfd_event_wait_completion
fails as it has to run userfaultfd_ctx_put on all ctx to pair against
the userfaultfd_ctx_get that was run on all fctx->orig in
dup_userfaultfd.
Link: http://lkml.kernel.org/r/20170224181957.19736-4-aarcange@redhat.com
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Mike Kravetz <mike.kravetz@oracle.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Hillf Danton <hillf.zj@alibaba-inc.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/userfaultfd.c | 18 |
1 files changed, 5 insertions, 13 deletions
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 668bbbd2e04d..dd48052e086f 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -527,16 +527,12 @@ out: return ret; } -static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, - struct userfaultfd_wait_queue *ewq) +static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, + struct userfaultfd_wait_queue *ewq) { - int ret; - - ret = -1; if (WARN_ON_ONCE(current->flags & PF_EXITING)) goto out; - ret = 0; ewq->ctx = ctx; init_waitqueue_entry(&ewq->wq, current); @@ -552,7 +548,6 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, break; if (ACCESS_ONCE(ctx->released) || fatal_signal_pending(current)) { - ret = -1; __remove_wait_queue(&ctx->event_wqh, &ewq->wq); break; } @@ -573,7 +568,6 @@ static int userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx, */ out: userfaultfd_ctx_put(ctx); - return ret; } static void userfaultfd_event_complete(struct userfaultfd_ctx *ctx, @@ -631,7 +625,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs) return 0; } -static int dup_fctx(struct userfaultfd_fork_ctx *fctx) +static void dup_fctx(struct userfaultfd_fork_ctx *fctx) { struct userfaultfd_ctx *ctx = fctx->orig; struct userfaultfd_wait_queue ewq; @@ -641,17 +635,15 @@ static int dup_fctx(struct userfaultfd_fork_ctx *fctx) ewq.msg.event = UFFD_EVENT_FORK; ewq.msg.arg.reserved.reserved1 = (unsigned long)fctx->new; - return userfaultfd_event_wait_completion(ctx, &ewq); + 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); + dup_fctx(fctx); list_del(&fctx->list); kfree(fctx); } |