On Mon, Feb 23, 2026 at 12:32 AM Slava Imameev <[email protected]> wrote: > > Multi-level pointer params and return value test coverage for BPF > trampolines: > - fentry/fexit programs covering struct and void double/triple > pointer parameters and returned values > - verifier context tests covering multi-level pointers as parameters > - verifier context tests covering multi-level pointers as returned > values > - verifier context tests for lsm to check trusted parameters handling > - verifier context tests covering out-of-bound access after cast > - verifier BPF helper tests to validate no change in verifier > behaviour > > Signed-off-by: Slava Imameev <[email protected]> > --- > net/bpf/test_run.c | 130 ++++++ > .../prog_tests/fentry_fexit_multi_level_ptr.c | 206 +++++++++ > .../selftests/bpf/prog_tests/verifier.c | 2 + > .../progs/fentry_fexit_pptr_nullable_test.c | 56 +++ > .../bpf/progs/fentry_fexit_pptr_test.c | 67 +++ > .../bpf/progs/fentry_fexit_void_ppptr_test.c | 38 ++ > .../bpf/progs/fentry_fexit_void_pptr_test.c | 71 +++ > .../bpf/progs/verifier_ctx_multilevel_ptr.c | 435 ++++++++++++++++++ > 8 files changed, 1005 insertions(+) > create mode 100644 > tools/testing/selftests/bpf/prog_tests/fentry_fexit_multi_level_ptr.c > create mode 100644 > tools/testing/selftests/bpf/progs/fentry_fexit_pptr_nullable_test.c > create mode 100644 tools/testing/selftests/bpf/progs/fentry_fexit_pptr_test.c > create mode 100644 > tools/testing/selftests/bpf/progs/fentry_fexit_void_ppptr_test.c > create mode 100644 > tools/testing/selftests/bpf/progs/fentry_fexit_void_pptr_test.c > create mode 100644 > tools/testing/selftests/bpf/progs/verifier_ctx_multilevel_ptr.c > > diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c > index 178c4738e63b..9f6ee2eb01cd 100644 > --- a/net/bpf/test_run.c > +++ b/net/bpf/test_run.c > @@ -24,6 +24,9 @@ > #include <net/netdev_rx_queue.h> > #include <net/xdp.h> > #include <net/netfilter/nf_bpf_link.h> > +#include <linux/set_memory.h> > +#include <linux/string.h> > +#include <asm/tlbflush.h> > > #define CREATE_TRACE_POINTS > #include <trace/events/bpf_test_run.h> > @@ -563,6 +566,42 @@ noinline int bpf_fentry_test10(const void *a) > return (long)a; > } > > +struct bpf_fentry_test_pptr_t { > + u32 value1; > + u32 value2; > +}; > + > +noinline int bpf_fentry_test11_pptr_nullable(struct bpf_fentry_test_pptr_t > **pptr__nullable) > +{ > + if (!pptr__nullable) > + return -1; > + > + return (*pptr__nullable)->value1; > +} > + > +noinline u32 **bpf_fentry_test12_pptr(u32 id, u32 **pptr) > +{ > + /* prevent DCE */ > + asm volatile("" : "+r"(id)); > + asm volatile("" : "+r"(pptr)); > + return pptr; > +} > + > +noinline u8 bpf_fentry_test13_pptr(void **pptr) > +{ > + void *ptr; > + > + return copy_from_kernel_nofault(&ptr, pptr, sizeof(pptr)) == 0; > +} > + > +/* Test the verifier can handle multi-level pointer types with qualifiers. */ > +noinline void ***bpf_fentry_test14_ppptr(void **volatile *const ppptr) > +{ > + /* prevent DCE */ > + asm volatile("" :: "r"(ppptr) : "memory"); > + return (void ***)ppptr; > +} > + > noinline void bpf_fentry_test_sinfo(struct skb_shared_info *sinfo) > { > } > @@ -670,20 +709,110 @@ static void *bpf_test_init(const union bpf_attr > *kattr, u32 user_size, > return data; > } > > +static void *create_bad_kaddr(void) > +{ > + /* > + * Try to get an address that passes kernel range checks but causes > + * a page fault handler invocation if accessed from a BPF program. > + */ > +#if defined(CONFIG_ARCH_HAS_SET_MEMORY) && defined(CONFIG_X86) > + void *addr = vmalloc(PAGE_SIZE); > + > + if (!addr) > + return NULL; > + /* Make it non-present - any access will fault */ > + if (set_memory_np((unsigned long)addr, 1)) { > + vfree(addr); > + return NULL; > + } > + return addr; > +#elif defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP) > + struct page *page = alloc_page(GFP_KERNEL); > + > + if (!page) > + return NULL; > + /* Remove from direct map - any access will fault */ > + if (set_direct_map_invalid_noflush(page)) { > + __free_page(page); > + return NULL; > + } > + flush_tlb_kernel_range((unsigned long)page_address(page), > + (unsigned long)page_address(page) + PAGE_SIZE); > + return page_address(page); > +#endif
This is serious overkill for a test. See how bpf_testmod_return_ptr() does it. pw-bot: cr

