refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 kernel/events/core.c        | 2 +-
 kernel/events/internal.h    | 2 +-
 kernel/events/ring_buffer.c | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9147397..072327e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5124,7 +5124,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
                /* this has to be the last one */
                rb_free_aux(rb);
-               WARN_ON_ONCE(atomic_read(&rb->aux_refcount));
+               WARN_ON_ONCE(refcount_read(&rb->aux_refcount));
 
                mutex_unlock(&event->mmap_mutex);
        }
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index b8e6fdf..fb55716 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -48,7 +48,7 @@ struct ring_buffer {
        atomic_t                        aux_mmap_count;
        unsigned long                   aux_mmap_locked;
        void                            (*free_aux)(void *);
-       atomic_t                        aux_refcount;
+       refcount_t                      aux_refcount;
        void                            **aux_pages;
        void                            *aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 3353572..ba12fd2 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -357,7 +357,7 @@ void *perf_aux_output_begin(struct perf_output_handle 
*handle,
        if (!atomic_read(&rb->aux_mmap_count))
                goto err;
 
-       if (!atomic_inc_not_zero(&rb->aux_refcount))
+       if (!refcount_inc_not_zero(&rb->aux_refcount))
                goto err;
 
        /*
@@ -648,7 +648,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
         * we keep a refcount here to make sure either of the two can
         * reference them safely.
         */
-       atomic_set(&rb->aux_refcount, 1);
+       refcount_set(&rb->aux_refcount, 1);
 
        rb->aux_overwrite = overwrite;
        rb->aux_watermark = watermark;
@@ -667,7 +667,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-       if (atomic_dec_and_test(&rb->aux_refcount))
+       if (refcount_dec_and_test(&rb->aux_refcount))
                __rb_free_aux(rb);
 }
 
-- 
2.7.4

Reply via email to