From: Greg Kroah-Hartman Date: Tue, 23 Aug 2022 07:26:10 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v4.9.326~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d82b1afcb4943ce3830347f53137e48328e1b430;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bpf-fix-kasan-use-after-free-read-in-compute_effective_progs.patch --- diff --git a/queue-5.10/bpf-fix-kasan-use-after-free-read-in-compute_effective_progs.patch b/queue-5.10/bpf-fix-kasan-use-after-free-read-in-compute_effective_progs.patch new file mode 100644 index 00000000000..aee8e6e410a --- /dev/null +++ b/queue-5.10/bpf-fix-kasan-use-after-free-read-in-compute_effective_progs.patch @@ -0,0 +1,138 @@ +From 4c46091ee985ae84c60c5e95055d779fcd291d87 Mon Sep 17 00:00:00 2001 +From: Tadeusz Struk +Date: Tue, 17 May 2022 11:04:20 -0700 +Subject: bpf: Fix KASAN use-after-free Read in compute_effective_progs + +From: Tadeusz Struk + +commit 4c46091ee985ae84c60c5e95055d779fcd291d87 upstream. + +Syzbot found a Use After Free bug in compute_effective_progs(). +The reproducer creates a number of BPF links, and causes a fault +injected alloc to fail, while calling bpf_link_detach on them. +Link detach triggers the link to be freed by bpf_link_free(), +which calls __cgroup_bpf_detach() and update_effective_progs(). +If the memory allocation in this function fails, the function restores +the pointer to the bpf_cgroup_link on the cgroup list, but the memory +gets freed just after it returns. After this, every subsequent call to +update_effective_progs() causes this already deallocated pointer to be +dereferenced in prog_list_length(), and triggers KASAN UAF error. + +To fix this issue don't preserve the pointer to the prog or link in the +list, but remove it and replace it with a dummy prog without shrinking +the table. The subsequent call to __cgroup_bpf_detach() or +__cgroup_bpf_detach() will correct it. + +Fixes: af6eea57437a ("bpf: Implement bpf_link-based cgroup BPF program attachment") +Reported-by: +Signed-off-by: Tadeusz Struk +Signed-off-by: Andrii Nakryiko +Cc: +Link: https://syzkaller.appspot.com/bug?id=8ebf179a95c2a2670f7cf1ba62429ec044369db4 +Link: https://lore.kernel.org/bpf/20220517180420.87954-1-tadeusz.struk@linaro.org +Signed-off-by: Pu Lehui +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/cgroup.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 60 insertions(+), 10 deletions(-) + +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -654,6 +654,60 @@ static struct bpf_prog_list *find_detach + } + + /** ++ * purge_effective_progs() - After compute_effective_progs fails to alloc new ++ * cgrp->bpf.inactive table we can recover by ++ * recomputing the array in place. ++ * ++ * @cgrp: The cgroup which descendants to travers ++ * @prog: A program to detach or NULL ++ * @link: A link to detach or NULL ++ * @type: Type of detach operation ++ */ ++static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog, ++ struct bpf_cgroup_link *link, ++ enum bpf_attach_type type) ++{ ++ struct cgroup_subsys_state *css; ++ struct bpf_prog_array *progs; ++ struct bpf_prog_list *pl; ++ struct list_head *head; ++ struct cgroup *cg; ++ int pos; ++ ++ /* recompute effective prog array in place */ ++ css_for_each_descendant_pre(css, &cgrp->self) { ++ struct cgroup *desc = container_of(css, struct cgroup, self); ++ ++ if (percpu_ref_is_zero(&desc->bpf.refcnt)) ++ continue; ++ ++ /* find position of link or prog in effective progs array */ ++ for (pos = 0, cg = desc; cg; cg = cgroup_parent(cg)) { ++ if (pos && !(cg->bpf.flags[type] & BPF_F_ALLOW_MULTI)) ++ continue; ++ ++ head = &cg->bpf.progs[type]; ++ list_for_each_entry(pl, head, node) { ++ if (!prog_list_prog(pl)) ++ continue; ++ if (pl->prog == prog && pl->link == link) ++ goto found; ++ pos++; ++ } ++ } ++found: ++ BUG_ON(!cg); ++ progs = rcu_dereference_protected( ++ desc->bpf.effective[type], ++ lockdep_is_held(&cgroup_mutex)); ++ ++ /* Remove the program from the array */ ++ WARN_ONCE(bpf_prog_array_delete_safe_at(progs, pos), ++ "Failed to purge a prog from array at index %d", pos); ++ } ++} ++ ++/** + * __cgroup_bpf_detach() - Detach the program or link from a cgroup, and + * propagate the change to descendants + * @cgrp: The cgroup which descendants to traverse +@@ -671,7 +725,6 @@ int __cgroup_bpf_detach(struct cgroup *c + u32 flags = cgrp->bpf.flags[type]; + struct bpf_prog_list *pl; + struct bpf_prog *old_prog; +- int err; + + if (prog && link) + /* only one of prog or link can be specified */ +@@ -686,9 +739,12 @@ int __cgroup_bpf_detach(struct cgroup *c + pl->prog = NULL; + pl->link = NULL; + +- err = update_effective_progs(cgrp, type); +- if (err) +- goto cleanup; ++ if (update_effective_progs(cgrp, type)) { ++ /* if update effective array failed replace the prog with a dummy prog*/ ++ pl->prog = old_prog; ++ pl->link = link; ++ purge_effective_progs(cgrp, old_prog, link, type); ++ } + + /* now can actually delete it from this cgroup list */ + list_del(&pl->node); +@@ -700,12 +756,6 @@ int __cgroup_bpf_detach(struct cgroup *c + bpf_prog_put(old_prog); + static_branch_dec(&cgroup_bpf_enabled_key); + return 0; +- +-cleanup: +- /* restore back prog or link */ +- pl->prog = old_prog; +- pl->link = link; +- return err; + } + + /* Must be called with cgroup_mutex held to avoid races. */ diff --git a/queue-5.10/series b/queue-5.10/series index 5cf80f7d0a1..770284047ed 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -155,3 +155,4 @@ can-j1939-j1939_sk_queue_activate_next_locked-replace-warn_on_once-with-netdev_w can-j1939-j1939_session_destroy-fix-memory-leak-of-skbs.patch pci-err-retain-status-from-error-notification.patch qrtr-convert-qrtr_ports-from-idr-to-xarray.patch +bpf-fix-kasan-use-after-free-read-in-compute_effective_progs.patch