Re: [PATCH bpf-next v4 04/13] bpf: Support __arena and __arena__nullable kfunc argument suffixes
Amery Hung <[email protected]>
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <CAMB2axP+dm0r3U4-Wk2Z4T9+G8VmWLjMjrNKyV9CapzvPT_LqA@mail.gmail.com> |
On Thu, Aug 6, 2026 at 12:23 PM Kumar Kartikeya Dwivedi <[email protected]> wrote: > > On Thu Aug 6, 2026 at 9:20 PM CEST, Kumar Kartikeya Dwivedi wrote: > > On Thu Aug 6, 2026 at 7:22 PM CEST, Amery Hung wrote: > >> On Wed, Aug 5, 2026 at 2:05 PM Kumar Kartikeya Dwivedi <[email protected]> wrote: > >>> > >>> From: Tejun Heo <[email protected]> > >>> > >>> Passing an arena pointer to a kfunc takes two steps today. There is no > >>> arena pointer argument type, so the pointer crosses the boundary as a > >>> bare scalar, and the kfunc then offsets it by the arena base and casts > >>> it before it can touch the memory. Every such kfunc open-codes the same > >>> translation. > >>> > >>> Add the __arena and __arena__nullable argument suffixes to make this more > >>> convenient. The kfunc declares the parameter by its real pointer type > >>> and dereferences it directly, with the JIT rebasing the value at the > >>> call site, rN = kern_vm_start + (u32)rN. No bounds check is needed: the > >>> u32 offset stays within the guard-padded arena kernel mapping, and a > >>> fault on an unpopulated page recovers through the per-arena scratch > >>> page. A suffixed argument accepts a PTR_TO_ARENA or scalar register, > >>> matching global subprog arena arguments. > >>> > >>> __arena rebases unconditionally, so the kfunc never sees NULL and a > >>> value with zero in the low 32 bits arrives as the arena base. > >>> __arena__nullable preserves NULL for optional arguments by skipping the > >>> rebase when the truncated value, arena offset 0, is zero. Keeping the > >>> plain form NULL-free saves the NULL test on every call. > >>> > >>> The double separator makes the annotations composable: > >>> __arena__nullable also ends in __nullable. Match the composite suffix > >>> first when classifying kfunc arguments and function-model flags so it > >>> retains arena semantics while carrying the nullable flag. > >> > >> Since __arena__nullable will match is_kfunc_arg_arena() case and go > >> through JIT + regno check, and get its PTR_MAYBE_NULL anyway. How > >> about just keep it as __arena_nullable to simplify the patch? > >> > >> 1. No need to introudce is_kfunc_arg_arena_nullable() and changes in > >> is_kfunc_arg_nullable() > > > > For consistency, would you prefer that I don't manually set | PTR_MAYBE_NULL and > > let is_kfunc_arg_nullable() handle that? That would be another way to address > > this. Yeah. This also makes sense. No strong preference here. > > > > In some sense, __arena includes __nullable for the purposes of type checking, so > > it might make sense to add it to the predicate that determines NULL-ness, then > > it will acquire PTR_MAYBE_NULL automatically. > > > > We will still drop is_kfunc_arg_arena_nullable() though. > > > > Anyhow, I don't have any strong preference one way or the other, but thought I'd > > float this as an alternative since it appears to fit better, and details are > > hidden the predicates. > > This will amount to adding extra OR for __arena prefix match inside > is_kfunc_arg_nullable(), since __nullable should already match on > __arena__nullable. > > > > >> 2. is_kfunc_arg_arena() returns btf_param_match_suffix(btf, arg, > >> "__arena_nullable") || btf_param_match_suffix(btf, arg, "__arena"); > >> > > > > Yeah, makes sense. > > > >> [...] > >> > >>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > >>> index b62e77949542..2b7f6f6bbe76 100644 > >>> --- a/kernel/bpf/verifier.c > >>> +++ b/kernel/bpf/verifier.c > >>> @@ -10909,9 +10909,16 @@ static bool is_kfunc_arg_refcounted_kptr(const struct btf *btf, const struct btf > >>> return btf_param_match_suffix(btf, arg, "__refcounted_kptr"); > >>> } > >>> > >>> +static bool is_kfunc_arg_arena_nullable(const struct btf *btf, > >>> + const struct btf_param *arg) > >>> +{ > >>> + return btf_param_match_suffix(btf, arg, "__arena__nullable"); > >>> +} > >>> + > >>> static bool is_kfunc_arg_nullable(const struct btf *btf, const struct btf_param *arg) > >>> { > >>> - return btf_param_match_suffix(btf, arg, "__nullable"); > >>> + return !is_kfunc_arg_arena_nullable(btf, arg) && > >>> + btf_param_match_suffix(btf, arg, "__nullable"); > >>> } > >> > >> No need for the changes above. > >> > >>> > >>> static bool is_kfunc_arg_nonown_allowed(const struct btf *btf, const struct btf_param *arg) > >>> @@ -10929,6 +10936,12 @@ static bool is_kfunc_arg_irq_flag(const struct btf *btf, const struct btf_param > >>> return btf_param_match_suffix(btf, arg, "__irq_flag"); > >>> } > >>> > >>> +static bool is_kfunc_arg_arena(const struct btf *btf, const struct btf_param *arg) > >>> +{ > >>> + return is_kfunc_arg_arena_nullable(btf, arg) || > >>> + btf_param_match_suffix(btf, arg, "__arena"); > >> > >> return btf_param_match_suffix(btf, arg, "__arena_nullable") || > >> btf_param_match_suffix(btf, arg, "__arena"); > >> > > > > Ack, I'll adjust this bit. > > > >> [...] >