mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 11:21:26 -04:00
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>
This commit is contained in:
committed by
Alexei Starovoitov
parent
83419c8fdb
commit
63ec296239
@@ -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 (program_returns_void(env))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (frame->in_exception_callback_fn)
|
||||
break;
|
||||
|
||||
/* 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
|
||||
|
||||
Reference in New Issue
Block a user