bpf: Propagate scalar precision through stack arguments

Outgoing stack arguments retain scalar verifier state separately from
registers and ordinary spills. State comparison uses their precision
marks, but propagate_precision() does not carry those dependencies from
a reused state to the current path's ancestors. A path can consequently
reuse a state without making earlier checkpoints distinguish scalar
values that will later be used as memory offsets.

Seed the existing backtracking batch with precise scalar argument slots
from every frame. Incoming arguments live in the caller's outgoing
slots, so include caller frames as well as the current frame.

Also cover scalar argument slots in bpf_mark_all_scalars_precise(), so
conservative fallback preserves the same invariant. Keep its existing
ancestor-only traversal and leave pointer and uninitialized slots alone.

AI assistance was used in preparing this patch.

Fixes: 0f6bd5e7a8 ("bpf: Support stack arguments for bpf functions")
Signed-off-by: Xu Yunxiang <xyx2021@mail.ustc.edu.cn>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261102190350.788433-2-xyx2021@mail.ustc.edu.cn
This commit is contained in:
Xu Yunxiang 2026-11-03 03:03:49 +08:00 committed by Alexei Starovoitov
parent fdda033f7f
commit d537252cc8
No known key found for this signature in database
2 changed files with 25 additions and 0 deletions

View File

@ -746,6 +746,17 @@ void bpf_mark_all_scalars_precise(struct bpf_verifier_env *env,
i, -(j + 1) * 8);
}
}
for (j = 0; j < func->out_stack_arg_cnt; j++) {
reg = &func->stack_arg_regs[j];
if (reg->type != SCALAR_VALUE || reg->precise)
continue;
reg->precise = true;
if (env->log.level & BPF_LOG_LEVEL2) {
verbose(env,
"force_precise: frame%d: forcing r11%d to be precise\n",
i, -(j + 1) * BPF_REG_SIZE);
}
}
}
}
}

View File

@ -1116,6 +1116,20 @@ static int propagate_precision(struct bpf_verifier_env *env,
bpf_bt_set_frame_slot(&env->bt, fr, i);
first = false;
}
for (i = 0; i < state->out_stack_arg_cnt; i++) {
state_reg = &state->stack_arg_regs[i];
if (state_reg->type != SCALAR_VALUE || !state_reg->precise)
continue;
if (env->log.level & BPF_LOG_LEVEL2) {
if (first)
verbose(env, "frame %d: propagating r11%d",
fr, -(i + 1) * BPF_REG_SIZE);
else
verbose(env, ",r11%d", -(i + 1) * BPF_REG_SIZE);
}
bt_set_frame_stack_arg_slot(&env->bt, fr, i);
first = false;
}
if (!first && (env->log.level & BPF_LOG_LEVEL2))
verbose(env, "\n");
}