bpf: Do not allow tail call in strcut_ops program with __ref argument

Reject struct_ops programs with refcounted kptr arguments (arguments
tagged with __ref suffix) that tail call. Once a refcounted kptr is
passed to a struct_ops program from the kernel, it can be freed or
xchged into maps. As there is no guarantee a callee can get the same
valid refcounted kptr in the ctx, we cannot allow such usage.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20250220221532.1079331-1-ameryhung@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Amery Hung 2025-02-20 14:15:31 -08:00 committed by Alexei Starovoitov
parent e0525cd72b
commit 38f1e66abd

View File

@ -22542,10 +22542,11 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
const struct bpf_struct_ops *st_ops;
const struct btf_member *member;
struct bpf_prog *prog = env->prog;
bool has_refcounted_arg = false;
u32 btf_id, member_idx;
struct btf *btf;
const char *mname;
int err;
int i, err;
if (!prog->gpl_compatible) {
verbose(env, "struct ops programs must have a GPL compatible license\n");
@ -22615,6 +22616,23 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
return -EACCES;
}
for (i = 0; i < st_ops_desc->arg_info[member_idx].cnt; i++) {
if (st_ops_desc->arg_info[member_idx].info->refcounted) {
has_refcounted_arg = true;
break;
}
}
/* Tail call is not allowed for programs with refcounted arguments since we
* cannot guarantee that valid refcounted kptrs will be passed to the callee.
*/
for (i = 0; i < env->subprog_cnt; i++) {
if (has_refcounted_arg && env->subprog_info[i].has_tail_call) {
verbose(env, "program with __ref argument cannot tail call\n");
return -EINVAL;
}
}
prog->aux->attach_func_proto = func_proto;
prog->aux->attach_func_name = mname;
env->ops = st_ops->verifier_ops;