diff options
| author | Eduard Zingerman <eddyz87@gmail.com> | 2026-02-28 13:47:56 -0500 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-03-03 08:47:23 -0800 |
| commit | 63ec29623943bd55fa026017a93b2d739fcdbb32 (patch) | |
| tree | 9408f3309a1e4514c73b97b9c11bf1700a94726b /kernel | |
| parent | 83419c8fdbbc1dacd12fa614c5a3561e498aac5f (diff) | |
| download | linux-63ec29623943bd55fa026017a93b2d739fcdbb32.tar.gz linux-63ec29623943bd55fa026017a93b2d739fcdbb32.zip | |
bpf: Extract program_returns_void() for clarity
From: Eduard Zingerman <eddyz87@gmail.com>
The check_return_code function has explicit checks on whether
a program type can return void. Factor this logic out to reuse
it later for both main progs and subprogs.
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/r/20260228184759.108145-3-emil@etsalapatis.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/verifier.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 89e6d2f6bdf6..bb9abd42ab12 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -17953,6 +17953,28 @@ static bool return_retval_range(struct bpf_verifier_env *env, struct bpf_retval_ return true; } +static bool program_returns_void(struct bpf_verifier_env *env) +{ + const struct bpf_prog *prog = env->prog; + enum bpf_prog_type prog_type = resolve_prog_type(prog); + + switch (prog_type) { + case BPF_PROG_TYPE_LSM: + /* See return_retval_range, for BPF_LSM_CGROUP can be 0 or 0-1 depending on hook. */ + if (prog->expected_attach_type != BPF_LSM_CGROUP && + !prog->aux->attach_func_proto->type) + return true; + break; + case BPF_PROG_TYPE_STRUCT_OPS: + if (!prog->aux->attach_func_proto->type) + return true; + break; + default: + break; + } + return false; +} + static int check_return_code(struct bpf_verifier_env *env, int regno, const char *reg_name) { const char *exit_ctx = "At program exit"; @@ -17968,35 +17990,21 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char /* LSM and struct_ops func-ptr's return type could be "void" */ if (!is_subprog || frame->in_exception_callback_fn) { - switch (prog_type) { - case BPF_PROG_TYPE_LSM: - if (prog->expected_attach_type == BPF_LSM_CGROUP) - /* See return_retval_range, can be 0 or 0-1 depending on hook. */ - break; - if (!prog->aux->attach_func_proto->type) - return 0; - break; - case BPF_PROG_TYPE_STRUCT_OPS: - if (!prog->aux->attach_func_proto->type) - return 0; - - if (frame->in_exception_callback_fn) - break; + if (program_returns_void(env)) + return 0; + } - /* Allow a struct_ops program to return a referenced kptr if it - * matches the operator's return type and is in its unmodified - * form. A scalar zero (i.e., a null pointer) is also allowed. - */ - reg_type = reg->btf ? btf_type_by_id(reg->btf, reg->btf_id) : NULL; - ret_type = btf_type_resolve_ptr(prog->aux->attach_btf, - prog->aux->attach_func_proto->type, - NULL); - if (ret_type && ret_type == reg_type && reg->ref_obj_id) - return __check_ptr_off_reg(env, reg, regno, false); - break; - default: - break; - } + if (!is_subprog && prog_type == BPF_PROG_TYPE_STRUCT_OPS) { + /* Allow a struct_ops program to return a referenced kptr if it + * matches the operator's return type and is in its unmodified + * form. A scalar zero (i.e., a null pointer) is also allowed. + */ + reg_type = reg->btf ? btf_type_by_id(reg->btf, reg->btf_id) : NULL; + ret_type = btf_type_resolve_ptr(prog->aux->attach_btf, + prog->aux->attach_func_proto->type, + NULL); + if (ret_type && ret_type == reg_type && reg->ref_obj_id) + return __check_ptr_off_reg(env, reg, regno, false); } /* eBPF calling convention is such that R0 is used |
