summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2017-09-18 19:38:36 -0400
committerDavid S. Miller <davem@davemloft.net>2017-09-20 17:10:29 -0400
commitec9dd352d591f0c90402ec67a317c1ed4fb2e638 (patch)
tree6c44d1a7f5fd0fa102dac35a26586a7c4b22c8dd /kernel
parent008ba2a13f2d04c947adc536d19debb8fe66f110 (diff)
bpf: one perf event close won't free bpf program attached by another perf event
This patch fixes a bug exhibited by the following scenario: 1. fd1 = perf_event_open with attr.config = ID1 2. attach bpf program prog1 to fd1 3. fd2 = perf_event_open with attr.config = ID1 <this will be successful> 4. user program closes fd2 and prog1 is detached from the tracepoint. 5. user program with fd1 does not work properly as tracepoint no output any more. The issue happens at step 4. Multiple perf_event_open can be called successfully, but only one bpf prog pointer in the tp_event. In the current logic, any fd release for the same tp_event will free the tp_event->prog. The fix is to free tp_event->prog only when the closing fd corresponds to the one which registered the program. Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3e691b75b2db..6bc21e202ae4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8171,6 +8171,7 @@ static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd)
8171 } 8171 }
8172 } 8172 }
8173 event->tp_event->prog = prog; 8173 event->tp_event->prog = prog;
8174 event->tp_event->bpf_prog_owner = event;
8174 8175
8175 return 0; 8176 return 0;
8176} 8177}
@@ -8185,7 +8186,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event)
8185 return; 8186 return;
8186 8187
8187 prog = event->tp_event->prog; 8188 prog = event->tp_event->prog;
8188 if (prog) { 8189 if (prog && event->tp_event->bpf_prog_owner == event) {
8189 event->tp_event->prog = NULL; 8190 event->tp_event->prog = NULL;
8190 bpf_prog_put(prog); 8191 bpf_prog_put(prog);
8191 } 8192 }