Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf: Convert mmap() refcounts to refcount_t

The recently fixed reference count leaks could have been detected by using
refcount_t and refcount_t would have mitigated the potential overflow at
least.

Now that the code is properly structured, convert the mmap() related
mmap_count variants over to refcount_t.

No functional change intended.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Link: https://lore.kernel.org/r/20250812104020.071507932@infradead.org

authored by

Thomas Gleixner and committed by
Peter Zijlstra
448f97fb 59741451

+24 -24
+1 -1
include/linux/perf_event.h
··· 859 859 860 860 /* mmap bits */ 861 861 struct mutex mmap_mutex; 862 - atomic_t mmap_count; 862 + refcount_t mmap_count; 863 863 864 864 struct perf_buffer *rb; 865 865 struct list_head rb_entry;
+20 -20
kernel/events/core.c
··· 3968 3968 */ 3969 3969 static inline bool event_update_userpage(struct perf_event *event) 3970 3970 { 3971 - if (likely(!atomic_read(&event->mmap_count))) 3971 + if (likely(!refcount_read(&event->mmap_count))) 3972 3972 return false; 3973 3973 3974 3974 perf_event_update_time(event); ··· 6704 6704 struct perf_event *event = vma->vm_file->private_data; 6705 6705 mapped_f mapped = get_mapped(event, event_mapped); 6706 6706 6707 - atomic_inc(&event->mmap_count); 6708 - atomic_inc(&event->rb->mmap_count); 6707 + refcount_inc(&event->mmap_count); 6708 + refcount_inc(&event->rb->mmap_count); 6709 6709 6710 6710 if (vma->vm_pgoff) 6711 - atomic_inc(&event->rb->aux_mmap_count); 6711 + refcount_inc(&event->rb->aux_mmap_count); 6712 6712 6713 6713 if (mapped) 6714 6714 mapped(event, vma->vm_mm); ··· 6743 6743 * to avoid complications. 6744 6744 */ 6745 6745 if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff && 6746 - atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &rb->aux_mutex)) { 6746 + refcount_dec_and_mutex_lock(&rb->aux_mmap_count, &rb->aux_mutex)) { 6747 6747 /* 6748 6748 * Stop all AUX events that are writing to this buffer, 6749 6749 * so that we can free its AUX pages and corresponding PMU ··· 6763 6763 mutex_unlock(&rb->aux_mutex); 6764 6764 } 6765 6765 6766 - if (atomic_dec_and_test(&rb->mmap_count)) 6766 + if (refcount_dec_and_test(&rb->mmap_count)) 6767 6767 detach_rest = true; 6768 6768 6769 - if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) 6769 + if (!refcount_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) 6770 6770 goto out_put; 6771 6771 6772 6772 ring_buffer_attach(event, NULL); ··· 6992 6992 if (data_page_nr(event->rb) != nr_pages) 6993 6993 return -EINVAL; 6994 6994 6995 - if (atomic_inc_not_zero(&event->rb->mmap_count)) { 6995 + if (refcount_inc_not_zero(&event->rb->mmap_count)) { 6996 6996 /* 6997 6997 * Success -- managed to mmap() the same buffer 6998 6998 * multiple times. 6999 6999 */ 7000 7000 perf_mmap_account(vma, user_extra, extra); 7001 - atomic_inc(&event->mmap_count); 7001 + refcount_inc(&event->mmap_count); 7002 7002 return 0; 7003 7003 } 7004 7004 7005 7005 /* 7006 7006 * Raced against perf_mmap_close()'s 7007 - * atomic_dec_and_mutex_lock() remove the 7007 + * refcount_dec_and_mutex_lock() remove the 7008 7008 * event and continue as if !event->rb 7009 7009 */ 7010 7010 ring_buffer_attach(event, NULL); ··· 7023 7023 if (!rb) 7024 7024 return -ENOMEM; 7025 7025 7026 - atomic_set(&rb->mmap_count, 1); 7026 + refcount_set(&rb->mmap_count, 1); 7027 7027 rb->mmap_user = get_current_user(); 7028 7028 rb->mmap_locked = extra; 7029 7029 ··· 7034 7034 perf_event_update_userpage(event); 7035 7035 7036 7036 perf_mmap_account(vma, user_extra, extra); 7037 - atomic_set(&event->mmap_count, 1); 7037 + refcount_set(&event->mmap_count, 1); 7038 7038 7039 7039 return 0; 7040 7040 } ··· 7081 7081 if (!is_power_of_2(nr_pages)) 7082 7082 return -EINVAL; 7083 7083 7084 - if (!atomic_inc_not_zero(&rb->mmap_count)) 7084 + if (!refcount_inc_not_zero(&rb->mmap_count)) 7085 7085 return -EINVAL; 7086 7086 7087 7087 if (rb_has_aux(rb)) { 7088 - atomic_inc(&rb->aux_mmap_count); 7088 + refcount_inc(&rb->aux_mmap_count); 7089 7089 7090 7090 } else { 7091 7091 if (!perf_mmap_calc_limits(vma, &user_extra, &extra)) { 7092 - atomic_dec(&rb->mmap_count); 7092 + refcount_dec(&rb->mmap_count); 7093 7093 return -EPERM; 7094 7094 } 7095 7095 ··· 7101 7101 ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages, 7102 7102 event->attr.aux_watermark, rb_flags); 7103 7103 if (ret) { 7104 - atomic_dec(&rb->mmap_count); 7104 + refcount_dec(&rb->mmap_count); 7105 7105 return ret; 7106 7106 } 7107 7107 7108 - atomic_set(&rb->aux_mmap_count, 1); 7108 + refcount_set(&rb->aux_mmap_count, 1); 7109 7109 rb->aux_mmap_locked = extra; 7110 7110 } 7111 7111 7112 7112 perf_mmap_account(vma, user_extra, extra); 7113 - atomic_inc(&event->mmap_count); 7113 + refcount_inc(&event->mmap_count); 7114 7114 7115 7115 return 0; 7116 7116 } ··· 13254 13254 mutex_lock_double(&event->mmap_mutex, &output_event->mmap_mutex); 13255 13255 set: 13256 13256 /* Can't redirect output if we've got an active mmap() */ 13257 - if (atomic_read(&event->mmap_count)) 13257 + if (refcount_read(&event->mmap_count)) 13258 13258 goto unlock; 13259 13259 13260 13260 if (output_event) { ··· 13267 13267 goto unlock; 13268 13268 13269 13269 /* did we race against perf_mmap_close() */ 13270 - if (!atomic_read(&rb->mmap_count)) { 13270 + if (!refcount_read(&rb->mmap_count)) { 13271 13271 ring_buffer_put(rb); 13272 13272 goto unlock; 13273 13273 }
+2 -2
kernel/events/internal.h
··· 35 35 spinlock_t event_lock; 36 36 struct list_head event_list; 37 37 38 - atomic_t mmap_count; 38 + refcount_t mmap_count; 39 39 unsigned long mmap_locked; 40 40 struct user_struct *mmap_user; 41 41 ··· 47 47 unsigned long aux_pgoff; 48 48 int aux_nr_pages; 49 49 int aux_overwrite; 50 - atomic_t aux_mmap_count; 50 + refcount_t aux_mmap_count; 51 51 unsigned long aux_mmap_locked; 52 52 void (*free_aux)(void *); 53 53 refcount_t aux_refcount;
+1 -1
kernel/events/ring_buffer.c
··· 400 400 * the same order, see perf_mmap_close. Otherwise we end up freeing 401 401 * aux pages in this path, which is a bug, because in_atomic(). 402 402 */ 403 - if (!atomic_read(&rb->aux_mmap_count)) 403 + if (!refcount_read(&rb->aux_mmap_count)) 404 404 goto err; 405 405 406 406 if (!refcount_inc_not_zero(&rb->aux_refcount))