Skip to content

Commit c1aedd5

Browse files
Pu LehuiKernel Patches Daemon
authored andcommitted
bpf: Fix invalid mem access when update_effective_progs fails in __cgroup_bpf_detach
Syzkaller triggers an invalid memory access issue following fault injection in update_effective_progs. The issue can be described as follows: __cgroup_bpf_detach update_effective_progs compute_effective_progs bpf_prog_array_alloc <-- fault inject purge_effective_progs /* change to dummy_bpf_prog */ array->items[index] = &dummy_bpf_prog.prog ---softirq start--- __do_softirq ... __cgroup_bpf_run_filter_skb __bpf_prog_run_save_cb bpf_prog_run stats = this_cpu_ptr(prog->stats) /* invalid memory access */ flags = u64_stats_update_begin_irqsave(&stats->syncp) ---softirq end--- static_branch_dec(&cgroup_bpf_enabled_key[atype]) The reason is that fault injection caused update_effective_progs to fail and then changed the original prog into dummy_bpf_prog.prog in purge_effective_progs. Then a softirq came, and accessing the members of dummy_bpf_prog.prog in the softirq triggers invalid mem access. To fix it, we can skip executing the prog when it's dummy_bpf_prog.prog. Fixes: 4c46091 ("bpf: Fix KASAN use-after-free Read in compute_effective_progs") Signed-off-by: Pu Lehui <[email protected]>
1 parent cc1cabb commit c1aedd5

File tree

3 files changed

+11
-5
lines changed

3 files changed

+11
-5
lines changed

include/linux/bpf.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,12 @@ struct bpf_prog_array {
22122212
struct bpf_prog_array_item items[];
22132213
};
22142214

2215+
struct bpf_prog_dummy {
2216+
struct bpf_prog prog;
2217+
};
2218+
2219+
extern struct bpf_prog_dummy dummy_bpf_prog;
2220+
22152221
struct bpf_empty_prog_array {
22162222
struct bpf_prog_array hdr;
22172223
struct bpf_prog *null_prog;

kernel/bpf/cgroup.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,16 @@ bpf_prog_run_array_cg(const struct cgroup_bpf *cgrp,
7777
item = &array->items[0];
7878
old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
7979
while ((prog = READ_ONCE(item->prog))) {
80-
run_ctx.prog_item = item;
80+
run_ctx.prog_item = item++;
81+
if (prog == &dummy_bpf_prog.prog)
82+
continue;
8183
func_ret = run_prog(prog, ctx);
8284
if (ret_flags) {
8385
*(ret_flags) |= (func_ret >> 1);
8486
func_ret &= 1;
8587
}
8688
if (!func_ret && !IS_ERR_VALUE((long)run_ctx.retval))
8789
run_ctx.retval = -EPERM;
88-
item++;
8990
}
9091
bpf_reset_run_ctx(old_run_ctx);
9192
rcu_read_unlock_migrate();

kernel/bpf/core.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,13 +2536,12 @@ static unsigned int __bpf_prog_ret1(const void *ctx,
25362536
return 1;
25372537
}
25382538

2539-
static struct bpf_prog_dummy {
2540-
struct bpf_prog prog;
2541-
} dummy_bpf_prog = {
2539+
struct bpf_prog_dummy dummy_bpf_prog = {
25422540
.prog = {
25432541
.bpf_func = __bpf_prog_ret1,
25442542
},
25452543
};
2544+
EXPORT_SYMBOL(dummy_bpf_prog);
25462545

25472546
struct bpf_empty_prog_array bpf_empty_prog_array = {
25482547
.null_prog = NULL,

0 commit comments

Comments
 (0)