mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'bpf-follow-up-fixes-for-stack-argument-support'
Yonghong Song says:
====================
bpf: Follow-up fixes for stack argument support
Commit cd59fa185a ("bpf: Support stack arguments for BPF functions and kfuncs")
added stack argument support for bpf functions and kfuncs. This patch set
is to fix various issues related to stack arguments, mainly include:
- Validate outgoing stack args when btf_prepare_func_args fails
- Fix arg_track_join log to use sa prefix for stack arg slots
- Clean up redundant stack arg checks for non-JITed programs
Changelog:
v2 -> v3:
- v2: https://lore.kernel.org/bpf/20260515014958.1186132-1-yonghong.song@linux.dev/
- Add additional fix (fix arg_track_join log, fix exception with outgoing stack
arguments, some cleanup, etc.).
v1 -> v2:
- v1: https://lore.kernel.org/bpf/20260514184827.1619863-1-yonghong.song@linux.dev/
- Remove 'Reported-by: Sashiko <sashiko-bot@kernel.org>'.
- Add proper fix tag.
====================
Link: https://patch.msgid.link/20260515225035.821178-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
50d00ea660
|
|
@ -2609,7 +2609,7 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct
|
|||
goto finalize;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) ||
|
||||
bpf_prog_has_kfunc_call(fp) || (env && env->subprog_info[0].stack_arg_cnt))
|
||||
bpf_prog_has_kfunc_call(fp))
|
||||
jit_needed = true;
|
||||
|
||||
if (!bpf_prog_select_interpreter(fp))
|
||||
|
|
|
|||
|
|
@ -1407,7 +1407,7 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
|
|||
verbose(env, "calling kernel functions are not allowed in non-JITed programs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 1; i < env->subprog_cnt; i++) {
|
||||
for (i = 0; i < env->subprog_cnt; i++) {
|
||||
if (bpf_in_stack_arg_cnt(&env->subprog_info[i])) {
|
||||
verbose(env, "stack args are not supported in non-JITed programs\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -806,7 +806,9 @@ static bool arg_track_join(struct bpf_verifier_env *env, int idx, int target, in
|
|||
return true;
|
||||
|
||||
verbose(env, "arg JOIN insn %d -> %d ", idx, target);
|
||||
if (r >= 0)
|
||||
if (r >= MAX_BPF_REG)
|
||||
verbose(env, "sa%d: ", r - MAX_BPF_REG);
|
||||
else if (r >= 0)
|
||||
verbose(env, "r%d: ", r);
|
||||
else
|
||||
verbose(env, "fp%+d: ", r * 8);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ int subprog_pruning_call_before_load_6args(int a, int b, int c, int d, int e, in
|
|||
return a + b + c + d + e + f;
|
||||
}
|
||||
|
||||
void subprog_bad_ptr_7args(long *a, int b, int c, int d, int e, int f, int g)
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int subprog_bad_order_6args(void)
|
||||
|
|
@ -38,4 +42,8 @@ int subprog_pruning_call_before_load_6args(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void subprog_bad_ptr_7args(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -114,8 +114,10 @@ __naked void stack_arg_gap_at_minus8(void)
|
|||
|
||||
SEC("tc")
|
||||
__description("stack_arg: pruning with different stack arg types")
|
||||
__failure
|
||||
__failure __log_level(2)
|
||||
__flag(BPF_F_TEST_STATE_FREQ)
|
||||
__msg("arg JOIN insn 9 -> 10 r1: fp0-8 + _ => fp0-8|fp0+0")
|
||||
__msg("arg JOIN insn 9 -> 10 sa0: fp0-8 + _ => fp0-8|fp0+0")
|
||||
__msg("R{{[0-9]}} invalid mem access 'scalar'")
|
||||
__naked void stack_arg_pruning_type_mismatch(void)
|
||||
{
|
||||
|
|
@ -152,7 +154,7 @@ __naked void stack_arg_pruning_type_mismatch(void)
|
|||
SEC("tc")
|
||||
__description("stack_arg: release_reference invalidates stack arg slot")
|
||||
__failure
|
||||
__msg("R{{[0-9]}} !read_ok")
|
||||
__msg("callee expects 6 args, stack arg1 is not initialized")
|
||||
__naked void stack_arg_release_ref(void)
|
||||
{
|
||||
asm volatile (
|
||||
|
|
@ -201,7 +203,7 @@ __naked void stack_arg_release_ref(void)
|
|||
SEC("tc")
|
||||
__description("stack_arg: pkt pointer in stack arg slot invalidated after pull_data")
|
||||
__failure
|
||||
__msg("R{{[0-9]}} !read_ok")
|
||||
__msg("callee expects 6 args, stack arg1 is not initialized")
|
||||
__naked void stack_arg_stale_pkt_ptr(void)
|
||||
{
|
||||
asm volatile (
|
||||
|
|
|
|||
|
|
@ -112,6 +112,64 @@ __naked void stack_arg_pruning_load_after_call(void)
|
|||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* "bad_ptr": the first arg is 'long *', which is not a recognized pointer
|
||||
* type for static subprogs (not ctx, dynptr, or tagged). btf_prepare_func_args()
|
||||
* sets arg_cnt = 7 / stack_arg_cnt = 2, then fails with -EINVAL. The subprog
|
||||
* is marked unreliable but the call still proceeds for static subprogs.
|
||||
*/
|
||||
__noinline __used __naked
|
||||
static void subprog_bad_ptr_7args(long *a, int b, int c, int d, int e, int f, int g)
|
||||
{
|
||||
asm volatile (
|
||||
"r0 = *(u64 *)(r11 + 8);"
|
||||
"r1 = *(u64 *)(r11 + 16);"
|
||||
"exit;"
|
||||
::: __clobber_all
|
||||
);
|
||||
}
|
||||
|
||||
SEC("tc")
|
||||
__description("stack_arg: read without caller write")
|
||||
__failure
|
||||
__msg("callee expects 7 args, stack arg1 is not initialized")
|
||||
__btf_func_path("btf__verifier_stack_arg_order.bpf.o")
|
||||
__naked void stack_arg_read_without_write_1(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r1 = 0;"
|
||||
"r2 = 0;"
|
||||
"r3 = 0;"
|
||||
"r4 = 0;"
|
||||
"r5 = 0;"
|
||||
"call subprog_bad_ptr_7args;"
|
||||
"exit;"
|
||||
::: __clobber_all
|
||||
);
|
||||
}
|
||||
|
||||
SEC("tc")
|
||||
__description("stack_arg: read with not-initialized caller write")
|
||||
__failure
|
||||
__msg("R0 !read_ok")
|
||||
__btf_func_path("btf__verifier_stack_arg_order.bpf.o")
|
||||
__naked void stack_arg_read_without_write_2(void)
|
||||
{
|
||||
asm volatile (
|
||||
"r1 = 0;"
|
||||
"r2 = 0;"
|
||||
"r3 = 0;"
|
||||
"r4 = 0;"
|
||||
"r5 = 0;"
|
||||
"*(u64 *)(r11 - 8) = 0;"
|
||||
"*(u64 *)(r11 - 16) = 0;"
|
||||
"call subprog_bad_ptr_7args;"
|
||||
"call subprog_bad_ptr_7args;"
|
||||
"exit;"
|
||||
::: __clobber_all
|
||||
);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
SEC("socket")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user