On Wed, Nov 14, 2018 at 04:39:16PM -0800, Eric Biggers wrote: > From: Eric Biggers <ebiggers@xxxxxxxxxx> > > Reference counters should use refcount_t rather than atomic_t, since the > refcount_t implementation can prevent overflows, reducing the > exploitability of reference leak bugs. userfaultfd_ctx::refcount is a > reference counter with the usual semantics, so convert it to refcount_t. > > Note: I replaced the BUG() on incrementing a 0 refcount with just > refcount_inc(), since part of the semantics of refcount_t is that that > incrementing a 0 refcount is not allowed; with CONFIG_REFCOUNT_FULL, > refcount_inc() already checks for it and warns. > > Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx> Reviewed-by: Mike Rapoport <rppt@xxxxxxxxxxxxx> > --- > fs/userfaultfd.c | 11 +++++------ > 1 file changed, 5 insertions(+), 6 deletions(-) > > diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c > index 356d2b8568c14..8375faac2790d 100644 > --- a/fs/userfaultfd.c > +++ b/fs/userfaultfd.c > @@ -53,7 +53,7 @@ struct userfaultfd_ctx { > /* a refile sequence protected by fault_pending_wqh lock */ > struct seqcount refile_seq; > /* pseudo fd refcounting */ > - atomic_t refcount; > + refcount_t refcount; > /* userfaultfd syscall flags */ > unsigned int flags; > /* features requested from the userspace */ > @@ -140,8 +140,7 @@ static int userfaultfd_wake_function(wait_queue_entry_t *wq, unsigned mode, > */ > static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx) > { > - if (!atomic_inc_not_zero(&ctx->refcount)) > - BUG(); > + refcount_inc(&ctx->refcount); > } > > /** > @@ -154,7 +153,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx) > */ > static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx) > { > - if (atomic_dec_and_test(&ctx->refcount)) { > + if (refcount_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)); > @@ -686,7 +685,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct list_head *fcs) > return -ENOMEM; > } > > - atomic_set(&ctx->refcount, 1); > + refcount_set(&ctx->refcount, 1); > ctx->flags = octx->flags; > ctx->state = UFFD_STATE_RUNNING; > ctx->features = octx->features; > @@ -1911,7 +1910,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) > if (!ctx) > return -ENOMEM; > > - atomic_set(&ctx->refcount, 1); > + refcount_set(&ctx->refcount, 1); > ctx->flags = flags; > ctx->features = 0; > ctx->state = UFFD_STATE_WAIT_API; > -- > 2.19.1.930.g4563a0d9d0-goog > -- Sincerely yours, Mike.