bpf: Validate outgoing stack args when btf_prepare_func_args fails

btf_prepare_func_args() sets sub->arg_cnt before validating arg types.
If validation fails (e.g. unsupported pointer type in a static subprog),
check_outgoing_stack_args() is skipped because btf_check_func_arg_match()
returns early. For static subprogs, check_func_call() ignores non-EFAULT
errors and proceeds with the call.

This causes the callee to read stack arg slots that the caller never
stored or not initialized, potentially dereferencing NULL caller->stack_arg_regs
or getting no-initialized value.

To fix the issue, when btf_prepare_func_args() fails and the subprog expects
stack args, call check_outgoing_stack_args() to verify the caller initialized
the slots. Return -EFAULT on failure so the error is not ignored.

Fixes: 3ab5bd317e ("bpf: Set sub->arg_cnt earlier in btf_prepare_func_args()")
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20260515225040.821515-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Yonghong Song 2026-05-15 15:50:40 -07:00 committed by Alexei Starovoitov
parent c8993263ff
commit 4286f5deee

View File

@ -9118,11 +9118,17 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
struct bpf_func_state *caller = cur_func(env);
struct bpf_verifier_log *log = &env->log;
u32 i;
int ret;
int ret, err;
ret = btf_prepare_func_args(env, subprog);
if (ret)
if (ret) {
if (bpf_in_stack_arg_cnt(sub) > 0) {
err = check_outgoing_stack_args(env, caller, sub->arg_cnt);
if (err)
return err;
}
return ret;
}
ret = check_outgoing_stack_args(env, caller, sub->arg_cnt);
if (ret)