Arena pointer kfunc calls and struct_ops callbacks need different JIT support. The former rebases BPF arena offsets before a kfunc call, while the latter converts kernel pointers when an indirect trampoline builds a callback context. A single bpf_jit_supports_arena_args() hook forces an architecture to implement both paths at once. That ties bpf_arena_alloc_pages() conversion to struct_ops trampoline support and prevents the paths from being enabled and reviewed independently. Replace it with separate kfunc and struct_ops capability hooks. Make the verifier query the hook for the path it is checking, and have x86-64 and arm64 advertise both capabilities to preserve their current behavior. Signed-off-by: Kumar Kartikeya Dwivedi --- arch/arm64/net/bpf_jit_comp.c | 7 ++++++- arch/x86/net/bpf_jit_comp.c | 7 ++++++- include/linux/filter.h | 3 ++- kernel/bpf/core.c | 7 ++++++- kernel/bpf/verifier.c | 4 ++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 3aa3ea0bc30b..eecaa0027a95 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -2398,7 +2398,12 @@ bool bpf_jit_supports_stack_args(void) return true; } -bool bpf_jit_supports_arena_args(void) +bool bpf_jit_supports_arena_kfunc_args(void) +{ + return true; +} + +bool bpf_jit_supports_arena_struct_ops_args(void) { return true; } diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 48429fae0641..6e89f1c8738b 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -4174,7 +4174,12 @@ bool bpf_jit_supports_stack_args(void) return true; } -bool bpf_jit_supports_arena_args(void) +bool bpf_jit_supports_arena_kfunc_args(void) +{ + return true; +} + +bool bpf_jit_supports_arena_struct_ops_args(void) { return true; } diff --git a/include/linux/filter.h b/include/linux/filter.h index 6e746b0a0930..907d774fd355 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1239,7 +1239,8 @@ bool bpf_jit_supports_percpu_insn(void); bool bpf_jit_supports_kfunc_call(void); bool bpf_jit_supports_kfunc_ret_reg_pair(void); bool bpf_jit_supports_stack_args(void); -bool bpf_jit_supports_arena_args(void); +bool bpf_jit_supports_arena_kfunc_args(void); +bool bpf_jit_supports_arena_struct_ops_args(void); bool bpf_jit_supports_far_kfunc_call(void); bool bpf_jit_supports_exceptions(void); bool bpf_jit_supports_ptr_xchg(void); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 5db77d7915df..92b0a3bf27be 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -3297,7 +3297,12 @@ bool __weak bpf_jit_supports_stack_args(void) return false; } -bool __weak bpf_jit_supports_arena_args(void) +bool __weak bpf_jit_supports_arena_kfunc_args(void) +{ + return false; +} + +bool __weak bpf_jit_supports_arena_struct_ops_args(void) { return false; } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e036ae20bf6b..6402e94c2097 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12013,7 +12013,7 @@ get_kfunc_arg_type(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta, else if (is_kfunc_arg_callback(env, meta->btf, &args[arg])) arg_type = KF_ARG_PTR_TO_CALLBACK; else if (is_kfunc_arg_arena(meta->btf, &args[arg])) { - if (!bpf_jit_supports_arena_args()) { + if (!bpf_jit_supports_arena_kfunc_args()) { verbose(env, "JIT does not support kfunc %s() with arena pointer arguments\n", meta->func_name); return -ENOTSUPP; @@ -19778,7 +19778,7 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) if (info->refcounted) has_refcounted_arg = true; if (base_type(info->reg_type) == PTR_TO_ARENA) { - if (!bpf_jit_supports_arena_args()) { + if (!bpf_jit_supports_arena_struct_ops_args()) { verbose(env, "JIT does not support arena arguments\n"); return -ENOTSUPP; } -- 2.53.0