]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bpf: account for current allocated stack depth in widen_imprecise_scalars()
authorEduard Zingerman <eddyz87@gmail.com>
Fri, 14 Nov 2025 02:57:29 +0000 (18:57 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Nov 2025 09:35:55 +0000 (10:35 +0100)
[ Upstream commit b0c8e6d3d866b6a7f73877f71968dbffd27b7785 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
kernel/bpf/verifier.c

index 218c238d6139895cda6f9cd1e95b8051c72ec2df..7b75a2dd8cb8f361fe9093e02e000016a61b9fc2 100644 (file)
@@ -8228,7 +8228,7 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
                                   struct bpf_verifier_state *cur)
 {
        struct bpf_func_state *fold, *fcur;
-       int i, fr;
+       int i, fr, num_slots;
 
        reset_idmap_scratch(env);
        for (fr = old->curframe; fr >= 0; fr--) {
@@ -8241,7 +8241,9 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
                                        &fcur->regs[i],
                                        &env->idmap_scratch);
 
-               for (i = 0; i < fold->allocated_stack / BPF_REG_SIZE; i++) {
+               num_slots = min(fold->allocated_stack / BPF_REG_SIZE,
+                               fcur->allocated_stack / BPF_REG_SIZE);
+               for (i = 0; i < num_slots; i++) {
                        if (!is_spilled_reg(&fold->stack[i]) ||
                            !is_spilled_reg(&fcur->stack[i]))
                                continue;