Commit 07c41a29 authored by Yonghong Song's avatar Yonghong Song Committed by David S. Miller

bpf: avoid rcu_dereference inside bpf_event_mutex lock region

During perf event attaching/detaching bpf programs,
the tp_event->prog_array change is protected by the
bpf_event_mutex lock in both attaching and deteching
functions. Although tp_event->prog_array is a rcu
pointer, rcu_derefrence is not needed to access it
since mutex lock will guarantee ordering.

Verified through "make C=2" that sparse
locking check still happy with the new change.

Also change the label name in perf_event_{attach,detach}_bpf_prog
from "out" to "unlock" to reflect the code action after the label.
Signed-off-by: default avatarYonghong Song <yhs@fb.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3051fbec
...@@ -769,20 +769,19 @@ int perf_event_attach_bpf_prog(struct perf_event *event, ...@@ -769,20 +769,19 @@ int perf_event_attach_bpf_prog(struct perf_event *event,
mutex_lock(&bpf_event_mutex); mutex_lock(&bpf_event_mutex);
if (event->prog) if (event->prog)
goto out; goto unlock;
old_array = rcu_dereference_protected(event->tp_event->prog_array, old_array = event->tp_event->prog_array;
lockdep_is_held(&bpf_event_mutex));
ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array); ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array);
if (ret < 0) if (ret < 0)
goto out; goto unlock;
/* set the new array to event->tp_event and set event->prog */ /* set the new array to event->tp_event and set event->prog */
event->prog = prog; event->prog = prog;
rcu_assign_pointer(event->tp_event->prog_array, new_array); rcu_assign_pointer(event->tp_event->prog_array, new_array);
bpf_prog_array_free(old_array); bpf_prog_array_free(old_array);
out: unlock:
mutex_unlock(&bpf_event_mutex); mutex_unlock(&bpf_event_mutex);
return ret; return ret;
} }
...@@ -796,11 +795,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event) ...@@ -796,11 +795,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
mutex_lock(&bpf_event_mutex); mutex_lock(&bpf_event_mutex);
if (!event->prog) if (!event->prog)
goto out; goto unlock;
old_array = rcu_dereference_protected(event->tp_event->prog_array,
lockdep_is_held(&bpf_event_mutex));
old_array = event->tp_event->prog_array;
ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array); ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array);
if (ret < 0) { if (ret < 0) {
bpf_prog_array_delete_safe(old_array, event->prog); bpf_prog_array_delete_safe(old_array, event->prog);
...@@ -812,6 +809,6 @@ void perf_event_detach_bpf_prog(struct perf_event *event) ...@@ -812,6 +809,6 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
bpf_prog_put(event->prog); bpf_prog_put(event->prog);
event->prog = NULL; event->prog = NULL;
out: unlock:
mutex_unlock(&bpf_event_mutex); mutex_unlock(&bpf_event_mutex);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment