Re: Re: [PATCH bpf-next v2 0/2] bpf: Add multi-level pointer parameter
From: Alexei Starovoitov <hidden>
Date: 2026-02-19 03:16:00
Also in:
bpf, linux-kselftest, lkml
On Wed, Feb 18, 2026 at 2:44 AM Slava Imameev [off-list ref] wrote:
- This programs cannot be compiled as bpf_core_cast cannot cast to a
multi-level pointer:
SEC("lsm/sb_eat_lsm_opts")
int BPF_PROG(sb_eat_lsm_opts_1,char *options, void **mnt_opts)
{
void** ppt = bpf_core_cast(mnt_opts, void*);
bpf_printk("%p\t", *ppt);
return 0;
}
Looks like there is a bug in llvm, since it crashes on the above.
But the following works:
void** ppt = bpf_rdonly_cast(mnt_opts, 0);
bpf_printk("%lx\t", *ppt);
Plus Eduard's diff:
- if (is_void_or_int_ptr(btf, t))
+ if (is_void_or_int_ptr(btf, t) || !btf_type_is_struct_ptr(btf, t))
- There is a workaround, which requires introducing a wrapper for
a pointer or typedef:
struct pvoid {
void* v;
};llvm should have handled it without the workaround. It's a bug that should be fixed.
I think there are no technical restrictions for treating single level pointers as PTR_TO_MEM.
I think it will be a missed opportunity and a potential foot gun. We didn't support access to 'char *' initially. Later relaxed it to mean that it's a valid pointer to a single byte, but since the code is generic it also became the case that 'char *' is allowed in kfunc and the verifier checks that one valid byte is there. That was a bad footgun, since we saw several cases of broken kfunc implementations that assume that 'char *' means a string. There are only two lsm hooks that pass 'struct foo **'. If we make it ptr_to_mem of 8 bytes we lose the ability to do something smarter in the future. I think we better add support to annotate such '**' as an actual array with given size and track types completely, so 'struct foo * var[N]' will become array_to_ptr_to_btf_id. That's probably more work that you signed up to do, so I suggest treating 'void **' as a scalar as Eduard suggested. This particular sb_eat_lsm_opts() hook doesn't have a useful type behind it anyway. I'm less certain about 'char **'. If we make it scalar too it will be harder to make it a pointer to nul terminated string later. So I would do 'void **' -> scalar for now only.