ARG_PTR_TO_ARENA accepts both arena pointers and scalars. The existing BPF-subprogram contract includes a constant-zero scalar; it is an arena address value rather than a conventional pointer rejected by nullability checking. Kfunc prototype generation already records this zero acceptance with PTR_MAYBE_NULL for both arena suffixes; separate JIT metadata determines whether the kernel callee receives the arena base or NULL. Apply the same call-site representation to the temporary BPF-subprogram prototype, then extend the guarded check_func_arg() path to cover arena arguments. Signed-off-by: Amery Hung --- kernel/bpf/verifier.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a7b245e90f33..96749d9b3e26 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10815,6 +10815,8 @@ static void gen_subprog_arg_proto(const struct bpf_subprog_info *sub, const stru * to protect against invalid memory access. */ arg_type = ARG_IGNORE; + } else if (base_type(arg_type) == ARG_PTR_TO_ARENA) { + arg_type |= PTR_MAYBE_NULL; } proto->arg_type[arg] = arg_type; t = btf_type_skip_modifiers(btf, args[arg].type, NULL); @@ -10880,7 +10882,8 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, nslots = btf_arg_slots(t); if (arg_type == ARG_SCALAR || arg_type == ARG_IGNORE || - arg_type == ARG_PTR_TO_CTX) { + arg_type == ARG_PTR_TO_CTX || + base_type(arg_type) == ARG_PTR_TO_ARENA) { ret = check_func_arg(env, arg, slot, 0, &meta, env->insn_idx); if (ret) return ret; @@ -10908,19 +10911,6 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, reg_arg_name(env, argno)); return -EINVAL; } - } else if (base_type(arg_type) == ARG_PTR_TO_ARENA) { - /* - * Can pass any value and the kernel won't crash, but - * only PTR_TO_ARENA or SCALAR make sense. Everything - * else is a bug in the bpf program. Point it out to - * the user at the verification time instead of - * run-time debug nightmare. - */ - if (reg->type != PTR_TO_ARENA && reg->type != SCALAR_VALUE) { - bpf_log(log, "%s is not a pointer to arena or scalar.\n", - reg_arg_name(env, argno)); - return -EINVAL; - } } else if (arg_type == ARG_PTR_TO_DYNPTR) { ret = check_func_arg_reg_off(env, reg, argno, ARG_PTR_TO_DYNPTR); if (ret) -- 2.52.0