| From foo@baz Wed Jul 6 16:50:56 PDT 2016 |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| Date: Mon, 27 Jun 2016 21:38:11 +0200 |
| Subject: bpf, perf: delay release of BPF prog after grace period |
| |
| From: Daniel Borkmann <daniel@iogearbox.net> |
| |
| [ Upstream commit ceb56070359b7329b5678b5d95a376fcb24767be ] |
| |
| Commit dead9f29ddcc ("perf: Fix race in BPF program unregister") moved |
| destruction of BPF program from free_event_rcu() callback to __free_event(), |
| which is problematic if used with tail calls: if prog A is attached as |
| trace event directly, but at the same time present in a tail call map used |
| by another trace event program elsewhere, then we need to delay destruction |
| via RCU grace period since it can still be in use by the program doing the |
| tail call (the prog first needs to be dropped from the tail call map, then |
| trace event with prog A attached destroyed, so we get immediate destruction). |
| |
| Fixes: dead9f29ddcc ("perf: Fix race in BPF program unregister") |
| Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> |
| Acked-by: Alexei Starovoitov <ast@kernel.org> |
| Cc: Jann Horn <jann@thejh.net> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/bpf.h | 4 ++++ |
| kernel/events/core.c | 2 +- |
| 2 files changed, 5 insertions(+), 1 deletion(-) |
| |
| --- a/include/linux/bpf.h |
| +++ b/include/linux/bpf.h |
| @@ -229,6 +229,10 @@ static inline struct bpf_prog *bpf_prog_ |
| static inline void bpf_prog_put(struct bpf_prog *prog) |
| { |
| } |
| + |
| +static inline void bpf_prog_put_rcu(struct bpf_prog *prog) |
| +{ |
| +} |
| #endif /* CONFIG_BPF_SYSCALL */ |
| |
| /* verifier prototypes for helper functions called from eBPF programs */ |
| --- a/kernel/events/core.c |
| +++ b/kernel/events/core.c |
| @@ -7143,7 +7143,7 @@ static void perf_event_free_bpf_prog(str |
| prog = event->tp_event->prog; |
| if (prog) { |
| event->tp_event->prog = NULL; |
| - bpf_prog_put(prog); |
| + bpf_prog_put_rcu(prog); |
| } |
| } |
| |