Commit 8991e2d5 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Kamal Mostafa

bpf, perf: delay release of BPF prog after grace period

BugLink: http://bugs.launchpad.net/bugs/1601952

[ Upstream commit ceb56070 ]

Commit dead9f29 ("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: dead9f29 ("perf: Fix race in BPF program unregister")
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Cc: Jann Horn <jann@thejh.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent ff0c8e60
...@@ -198,6 +198,10 @@ static inline struct bpf_prog *bpf_prog_get(u32 ufd) ...@@ -198,6 +198,10 @@ static inline struct bpf_prog *bpf_prog_get(u32 ufd)
static inline void bpf_prog_put(struct bpf_prog *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 */ #endif /* CONFIG_BPF_SYSCALL */
/* verifier prototypes for helper functions called from eBPF programs */ /* verifier prototypes for helper functions called from eBPF programs */
......
...@@ -7101,7 +7101,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event) ...@@ -7101,7 +7101,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event)
prog = event->tp_event->prog; prog = event->tp_event->prog;
if (prog) { if (prog) {
event->tp_event->prog = NULL; event->tp_event->prog = NULL;
bpf_prog_put(prog); bpf_prog_put_rcu(prog);
} }
} }
......
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