summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLee Jia Jie <mkofdwu@gmail.com>2026-10-22 20:58:48 +0800
committerPeter Zijlstra <peterz@infradead.org>2026-10-23 19:09:52 +0200
commit64ea0e8226ed98d14e0231af1beae10c3d5c043a (patch)
tree30b9ff888eba4d6c32748f0dc54374f4ae198543 /kernel
parent2b774b5bbffabae7ac6be98a98e9641fb3c0bbb4 (diff)
perf: Fix UAF in attach_task_ctx_data()
struct perf_ctx_data is RCU protected. In attach_task_ctx_data(), the cmpxchg retry loop runs without holding rcu_read_lock(). If task->perf_ctx_data already holds a pointer (call it `cd1`), then try_cmpxchg(&task->perf_ctx_data, &old, cd) fails and loads old = cd1. A concurrent thread running detach_task_ctx_data() could free cd1 leading to UAF and further memory corruption when cd1 is reclaimed by another thread. CPU 0: attach_task_ctx_data() CPU 1: detach_task_ctx_data() ----------------------------- ----------------------------- try_cmpxchg(&task->perf_ctx_data, &old, cd2) -> fails; loads old = cd1 refcount_dec_and_test(&cd1->refcount) try_cmpxchg(&task->perf_ctx_data, &cd1, NULL) perf_free_ctx_data_rcu(cd1) [ RCU grace period -> kfree(cd1) ] refcount_inc_not_zero(&old->refcount) -> UAF on freed cd1 Fix this by taking rcu_read_lock across the race window. Fixes: 506e64e710ff ("perf: attach/detach PMU specific data") Signed-off-by: Lee Jia Jie <mkofdwu@gmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a9ee91151b2d..e248f34f7b66 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5434,6 +5434,9 @@ attach_task_ctx_data(struct task_struct *task, struct kmem_cache *ctx_cache,
return -ENOMEM;
for (;;) {
+ /* Protect @old until inc_not_zero(&old->refcount) */
+ guard(rcu)();
+
if (try_cmpxchg(&task->perf_ctx_data, &old, cd)) {
if (old)
perf_free_ctx_data_rcu(old);