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

Configure Feed

Select the types of activity you want to include in your feed.

bpf: account for current allocated stack depth in widen_imprecise_scalars()

The usage pattern for widen_imprecise_scalars() looks as follows:

prev_st = find_prev_entry(env, ...);
queued_st = push_stack(...);
widen_imprecise_scalars(env, prev_st, queued_st);

Where prev_st is an ancestor of the queued_st in the explored states
tree. This ancestor is not guaranteed to have same allocated stack
depth as queued_st. E.g. in the following case:

def main():
for i in 1..2:
foo(i) // same callsite, differnt param

def foo(i):
if i == 1:
use 128 bytes of stack
iterator based loop

Here, for a second 'foo' call prev_st->allocated_stack is 128,
while queued_st->allocated_stack is much smaller.
widen_imprecise_scalars() needs to take this into account and avoid
accessing bpf_verifier_state->frame[*]->stack out of bounds.

Fixes: 2793a8b015f7 ("bpf: exact states comparison for iterator convergence checks")
Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20251114025730.772723-1-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
b0c8e6d3 4ef92743

+4 -2
+4 -2
kernel/bpf/verifier.c
··· 8866 8866 struct bpf_verifier_state *cur) 8867 8867 { 8868 8868 struct bpf_func_state *fold, *fcur; 8869 - int i, fr; 8869 + int i, fr, num_slots; 8870 8870 8871 8871 reset_idmap_scratch(env); 8872 8872 for (fr = old->curframe; fr >= 0; fr--) { ··· 8879 8879 &fcur->regs[i], 8880 8880 &env->idmap_scratch); 8881 8881 8882 - for (i = 0; i < fold->allocated_stack / BPF_REG_SIZE; i++) { 8882 + num_slots = min(fold->allocated_stack / BPF_REG_SIZE, 8883 + fcur->allocated_stack / BPF_REG_SIZE); 8884 + for (i = 0; i < num_slots; i++) { 8883 8885 if (!is_spilled_reg(&fold->stack[i]) || 8884 8886 !is_spilled_reg(&fcur->stack[i])) 8885 8887 continue;