From 0e6de25f0b1caa3565b02656ec6a00c1377e1ff8 Mon Sep 17 00:00:00 2001 From: Pu Lehui Date: Tue, 31 Dec 2024 03:35:09 +0000 Subject: [PATCH] bpf: Move out synchronize_rcu_tasks_trace from mutex CS Commit ef1b808e3b7c ("bpf: Fix UAF via mismatching bpf_prog/attachment RCU flavors") resolved a possible UAF issue in uprobes that attach non-sleepable bpf prog by explicitly waiting for a tasks-trace-RCU grace period. But, in the current implementation, synchronize_rcu_tasks_trace is included within the mutex critical section, which increases the length of the critical section and may affect performance. So let's move out synchronize_rcu_tasks_trace from mutex CS. Signed-off-by: Pu Lehui --- kernel/trace/bpf_trace.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 48db147c6c7d7..30ef8a6f5ca2b 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2245,12 +2245,15 @@ void perf_event_detach_bpf_prog(struct perf_event *event) { struct bpf_prog_array *old_array; struct bpf_prog_array *new_array; + struct bpf_prog *prog; int ret; mutex_lock(&bpf_event_mutex); - if (!event->prog) - goto unlock; + if (!event->prog) { + mutex_unlock(&bpf_event_mutex); + return; + } old_array = bpf_event_rcu_dereference(event->tp_event->prog_array); if (!old_array) @@ -2265,6 +2268,11 @@ void perf_event_detach_bpf_prog(struct perf_event *event) } put: + prog = event->prog; + event->prog = NULL; + + mutex_unlock(&bpf_event_mutex); + /* * It could be that the bpf_prog is not sleepable (and will be freed * via normal RCU), but is called from a point that supports sleepable @@ -2272,11 +2280,7 @@ void perf_event_detach_bpf_prog(struct perf_event *event) */ synchronize_rcu_tasks_trace(); - bpf_prog_put(event->prog); - event->prog = NULL; - -unlock: - mutex_unlock(&bpf_event_mutex); + bpf_prog_put(prog); } int perf_event_query_prog_array(struct perf_event *event, void __user *info)