Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: signal error if old liveness is more conservative than new

Unlike the new algorithm, register chain based liveness tracking is
fully path sensitive, and thus should be strictly more accurate.
Validate the new algorithm by signaling an error whenever it considers
a stack slot dead while the old algorithm considers it alive.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250918-callchain-sensitive-liveness-v3-8-c3cd27bacc60@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
ccf25a67 e41c2379

+10
+1
include/linux/bpf_verifier.h
··· 852 852 /* array of pointers to bpf_scc_info indexed by SCC id */ 853 853 struct bpf_scc_info **scc_info; 854 854 u32 scc_cnt; 855 + bool internal_error; 855 856 }; 856 857 857 858 static inline struct bpf_func_info_aux *subprog_aux(struct bpf_verifier_env *env, int subprog)
+9
kernel/bpf/verifier.c
··· 18576 18576 18577 18577 for (i = 0; i < st->allocated_stack / BPF_REG_SIZE; i++) { 18578 18578 if (!bpf_stack_slot_alive(env, st->frameno, i)) { 18579 + if (st->stack[i].spilled_ptr.live & REG_LIVE_READ) { 18580 + verifier_bug(env, "incorrect live marks #1 for insn %d frameno %d spi %d\n", 18581 + env->insn_idx, st->frameno, i); 18582 + env->internal_error = true; 18583 + } 18579 18584 __mark_reg_not_init(env, &st->stack[i].spilled_ptr); 18580 18585 for (j = 0; j < BPF_REG_SIZE; j++) 18581 18586 st->stack[i].slot_type[j] = STACK_INVALID; ··· 19551 19546 loop = incomplete_read_marks(env, &sl->state); 19552 19547 if (states_equal(env, &sl->state, cur, loop ? RANGE_WITHIN : NOT_EXACT)) { 19553 19548 hit: 19549 + if (env->internal_error) 19550 + return -EFAULT; 19554 19551 sl->hit_cnt++; 19555 19552 /* reached equivalent register/stack state, 19556 19553 * prune the search. ··· 19667 19660 return 1; 19668 19661 } 19669 19662 miss: 19663 + if (env->internal_error) 19664 + return -EFAULT; 19670 19665 /* when new state is not going to be added do not increase miss count. 19671 19666 * Otherwise several loop iterations will remove the state 19672 19667 * recorded earlier. The goal of these heuristics is to have