]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
54b550cfa64c4a68d8eebefcb6599ea3a6ba20c1
[thirdparty/kernel/stable-queue.git] /
1 From ef01f4e25c1760920e2c94f1c232350277ace69b Mon Sep 17 00:00:00 2001
2 From: Paul Moore <paul@paul-moore.com>
3 Date: Fri, 6 Jan 2023 10:43:59 -0500
4 Subject: bpf: restore the ebpf program ID for BPF_AUDIT_UNLOAD and PERF_BPF_EVENT_PROG_UNLOAD
5
6 From: Paul Moore <paul@paul-moore.com>
7
8 commit ef01f4e25c1760920e2c94f1c232350277ace69b upstream.
9
10 When changing the ebpf program put() routines to support being called
11 from within IRQ context the program ID was reset to zero prior to
12 calling the perf event and audit UNLOAD record generators, which
13 resulted in problems as the ebpf program ID was bogus (always zero).
14 This patch addresses this problem by removing an unnecessary call to
15 bpf_prog_free_id() in __bpf_prog_offload_destroy() and adjusting
16 __bpf_prog_put() to only call bpf_prog_free_id() after audit and perf
17 have finished their bpf program unload tasks in
18 bpf_prog_put_deferred(). For the record, no one can determine, or
19 remember, why it was necessary to free the program ID, and remove it
20 from the IDR, prior to executing bpf_prog_put_deferred();
21 regardless, both Stanislav and Alexei agree that the approach in this
22 patch should be safe.
23
24 It is worth noting that when moving the bpf_prog_free_id() call, the
25 do_idr_lock parameter was forced to true as the ebpf devs determined
26 this was the correct as the do_idr_lock should always be true. The
27 do_idr_lock parameter will be removed in a follow-up patch, but it
28 was kept here to keep the patch small in an effort to ease any stable
29 backports.
30
31 I also modified the bpf_audit_prog() logic used to associate the
32 AUDIT_BPF record with other associated records, e.g. @ctx != NULL.
33 Instead of keying off the operation, it now keys off the execution
34 context, e.g. '!in_irg && !irqs_disabled()', which is much more
35 appropriate and should help better connect the UNLOAD operations with
36 the associated audit state (other audit records).
37
38 Cc: stable@vger.kernel.org
39 Fixes: d809e134be7a ("bpf: Prepare bpf_prog_put() to be called from irq context.")
40 Reported-by: Burn Alting <burn.alting@iinet.net.au>
41 Reported-by: Jiri Olsa <olsajiri@gmail.com>
42 Suggested-by: Stanislav Fomichev <sdf@google.com>
43 Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
44 Signed-off-by: Paul Moore <paul@paul-moore.com>
45 Acked-by: Stanislav Fomichev <sdf@google.com>
46 Link: https://lore.kernel.org/r/20230106154400.74211-1-paul@paul-moore.com
47 Signed-off-by: Alexei Starovoitov <ast@kernel.org>
48 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
49 ---
50 kernel/bpf/offload.c | 3 ---
51 kernel/bpf/syscall.c | 6 ++----
52 2 files changed, 2 insertions(+), 7 deletions(-)
53
54 --- a/kernel/bpf/offload.c
55 +++ b/kernel/bpf/offload.c
56 @@ -216,9 +216,6 @@ static void __bpf_prog_offload_destroy(s
57 if (offload->dev_state)
58 offload->offdev->ops->destroy(prog);
59
60 - /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
61 - bpf_prog_free_id(prog, true);
62 -
63 list_del_init(&offload->offloads);
64 kfree(offload);
65 prog->aux->offload = NULL;
66 --- a/kernel/bpf/syscall.c
67 +++ b/kernel/bpf/syscall.c
68 @@ -1695,7 +1695,7 @@ static void bpf_audit_prog(const struct
69 return;
70 if (audit_enabled == AUDIT_OFF)
71 return;
72 - if (op == BPF_AUDIT_LOAD)
73 + if (!in_irq() && !irqs_disabled())
74 ctx = audit_context();
75 ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_BPF);
76 if (unlikely(!ab))
77 @@ -1790,6 +1790,7 @@ static void bpf_prog_put_deferred(struct
78 prog = aux->prog;
79 perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
80 bpf_audit_prog(prog, BPF_AUDIT_UNLOAD);
81 + bpf_prog_free_id(prog, true);
82 __bpf_prog_put_noref(prog, true);
83 }
84
85 @@ -1798,9 +1799,6 @@ static void __bpf_prog_put(struct bpf_pr
86 struct bpf_prog_aux *aux = prog->aux;
87
88 if (atomic64_dec_and_test(&aux->refcnt)) {
89 - /* bpf_prog_free_id() must be called first */
90 - bpf_prog_free_id(prog, do_idr_lock);
91 -
92 if (in_irq() || irqs_disabled()) {
93 INIT_WORK(&aux->work, bpf_prog_put_deferred);
94 schedule_work(&aux->work);