]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Move out synchronize_rcu_tasks_trace from mutex CS
authorPu Lehui <pulehui@huawei.com>
Sat, 4 Jan 2025 01:39:46 +0000 (01:39 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 8 Jan 2025 17:38:41 +0000 (09:38 -0800)
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 <pulehui@huawei.com>
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20250104013946.1111785-1-pulehui@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/trace/bpf_trace.c

index 48db147c6c7d7e3c7fa666f1fd09c89a4530ccce..a90880f475af8375af378b13decfdb8729b1c7d2 100644 (file)
@@ -2245,6 +2245,7 @@ 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 = NULL;
        int ret;
 
        mutex_lock(&bpf_event_mutex);
@@ -2265,18 +2266,22 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
        }
 
 put:
-       /*
-        * 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
-        * programs and uses tasks-trace-RCU.
-        */
-       synchronize_rcu_tasks_trace();
-
-       bpf_prog_put(event->prog);
+       prog = event->prog;
        event->prog = NULL;
 
 unlock:
        mutex_unlock(&bpf_event_mutex);
+
+       if (prog) {
+               /*
+                * 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
+                * programs and uses tasks-trace-RCU.
+                */
+               synchronize_rcu_tasks_trace();
+
+               bpf_prog_put(prog);
+       }
 }
 
 int perf_event_query_prog_array(struct perf_event *event, void __user *info)