diff options
author | Eric Biggers <ebiggers@google.com> | 2018-12-28 03:34:43 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-12-28 15:11:47 -0500 |
commit | ca880420665dbc8beec3693bee9f5eccb89de4a6 (patch) | |
tree | 7255c489175110780706a7eaf04fe8f0f34611b5 | |
parent | 66f71da9dd38af17dc17209cdde7987d4679a699 (diff) |
userfaultfd: convert userfaultfd_ctx::refcount to refcount_t
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.
Link: http://lkml.kernel.org/r/20181115003916.63381-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/userfaultfd.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 59dc28047030..e211b99d33c4 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c | |||
@@ -53,7 +53,7 @@ struct userfaultfd_ctx { | |||
53 | /* a refile sequence protected by fault_pending_wqh lock */ | 53 | /* a refile sequence protected by fault_pending_wqh lock */ |
54 | struct seqcount refile_seq; | 54 | struct seqcount refile_seq; |
55 | /* pseudo fd refcounting */ | 55 | /* pseudo fd refcounting */ |
56 | atomic_t refcount; | 56 | refcount_t refcount; |
57 | /* userfaultfd syscall flags */ | 57 | /* userfaultfd syscall flags */ |
58 | unsigned int flags; | 58 | unsigned int flags; |
59 | /* features requested from the userspace */ | 59 | /* features requested from the userspace */ |
@@ -140,8 +140,7 @@ out: | |||
140 | */ | 140 | */ |
141 | static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx) | 141 | static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx) |
142 | { | 142 | { |
143 | if (!atomic_inc_not_zero(&ctx->refcount)) | 143 | refcount_inc(&ctx->refcount); |
144 | BUG(); | ||
145 | } | 144 | } |
146 | 145 | ||
147 | /** | 146 | /** |
@@ -154,7 +153,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx) | |||
154 | */ | 153 | */ |
155 | static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx) | 154 | static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx) |
156 | { | 155 | { |
157 | if (atomic_dec_and_test(&ctx->refcount)) { | 156 | if (refcount_dec_and_test(&ctx->refcount)) { |
158 | VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock)); | 157 | VM_BUG_ON(spin_is_locked(&ctx->fault_pending_wqh.lock)); |
159 | VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh)); | 158 | VM_BUG_ON(waitqueue_active(&ctx->fault_pending_wqh)); |
160 | VM_BUG_ON(spin_is_locked(&ctx->fault_wqh.lock)); | 159 | 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) | |||
686 | return -ENOMEM; | 685 | return -ENOMEM; |
687 | } | 686 | } |
688 | 687 | ||
689 | atomic_set(&ctx->refcount, 1); | 688 | refcount_set(&ctx->refcount, 1); |
690 | ctx->flags = octx->flags; | 689 | ctx->flags = octx->flags; |
691 | ctx->state = UFFD_STATE_RUNNING; | 690 | ctx->state = UFFD_STATE_RUNNING; |
692 | ctx->features = octx->features; | 691 | ctx->features = octx->features; |
@@ -1927,7 +1926,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) | |||
1927 | if (!ctx) | 1926 | if (!ctx) |
1928 | return -ENOMEM; | 1927 | return -ENOMEM; |
1929 | 1928 | ||
1930 | atomic_set(&ctx->refcount, 1); | 1929 | refcount_set(&ctx->refcount, 1); |
1931 | ctx->flags = flags; | 1930 | ctx->flags = flags; |
1932 | ctx->features = 0; | 1931 | ctx->features = 0; |
1933 | ctx->state = UFFD_STATE_WAIT_API; | 1932 | ctx->state = UFFD_STATE_WAIT_API; |