]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Validate outgoing stack args when btf_prepare_func_args fails
authorYonghong Song <yonghong.song@linux.dev>
Fri, 15 May 2026 22:50:40 +0000 (15:50 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 17 May 2026 00:46:16 +0000 (17:46 -0700)
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: 3ab5bd317ee2 ("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>
kernel/bpf/verifier.c

index 76a07f09ab642831fc6ad8ecf33cef3854732cad..8dd79b735a69e0cce49a1d88c2ef706dadd27364 100644 (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)