Skip to content

Commit ccf25a6

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
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>
1 parent e41c237 commit ccf25a6

File tree

2 files changed

+10
-0
lines changed

2 files changed

+10
-0
lines changed

include/linux/bpf_verifier.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,7 @@ struct bpf_verifier_env {
852852
/* array of pointers to bpf_scc_info indexed by SCC id */
853853
struct bpf_scc_info **scc_info;
854854
u32 scc_cnt;
855+
bool internal_error;
855856
};
856857

857858
static inline struct bpf_func_info_aux *subprog_aux(struct bpf_verifier_env *env, int subprog)

kernel/bpf/verifier.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18576,6 +18576,11 @@ static void clean_func_state(struct bpf_verifier_env *env,
1857618576

1857718577
for (i = 0; i < st->allocated_stack / BPF_REG_SIZE; i++) {
1857818578
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+
}
1857918584
__mark_reg_not_init(env, &st->stack[i].spilled_ptr);
1858018585
for (j = 0; j < BPF_REG_SIZE; j++)
1858118586
st->stack[i].slot_type[j] = STACK_INVALID;
@@ -19546,6 +19551,8 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1954619551
loop = incomplete_read_marks(env, &sl->state);
1954719552
if (states_equal(env, &sl->state, cur, loop ? RANGE_WITHIN : NOT_EXACT)) {
1954819553
hit:
19554+
if (env->internal_error)
19555+
return -EFAULT;
1954919556
sl->hit_cnt++;
1955019557
/* reached equivalent register/stack state,
1955119558
* prune the search.
@@ -19660,6 +19667,8 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
1966019667
return 1;
1966119668
}
1966219669
miss:
19670+
if (env->internal_error)
19671+
return -EFAULT;
1966319672
/* when new state is not going to be added do not increase miss count.
1966419673
* Otherwise several loop iterations will remove the state
1966519674
* recorded earlier. The goal of these heuristics is to have

0 commit comments

Comments
 (0)