* [PATCH bpf-next v5 0/2] bpf: Add multi-level pointer parameter support for trampolines
@ 2026-03-13 13:02 Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 1/2] bpf: Support pointer param types via SCALAR_VALUE " Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage Slava Imameev
0 siblings, 2 replies; 6+ messages in thread
From: Slava Imameev @ 2026-03-13 13:02 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh,
sdf, haoluo, jolsa, davem, edumazet, kuba, pabeni, horms, shuah,
linux-kernel, bpf, netdev, linux-kselftest, linux-open-source,
Slava Imameev
This is v5 of a series adding support for new pointer types for
trampoline parameters.
Originally, only support for multi-level pointers was proposed.
As suggested during review, it was extended to single-level pointers.
During discussion, it was proposed to add support for any single or
multi-level pointer type that is not a single-level pointer to a
structure, with the condition if (!btf_type_is_struct_ptr(t)). The
safety of this condition is based on BTF data verification performed
for modules and programs, and vmlinux BTF being trusted to not
contain invalid types, so it is not possible for invalid types, like
PTR->DATASEC, PTR->FUNC, PTR->VAR and corresponding multi-level
pointers, to reach btf_ctx_access.
These changes appear to be a safe extension since any future support
for arrays and output values would require annotation (similar to
Microsoft SAL), which differentiates between current unannotated
scalar cases and new annotated cases.
This series adds BPF verifier support for single- and multi-level
pointer parameters and return values in BPF trampolines. The
implementation treats these parameters as SCALAR_VALUE.
This is consistent with existing pointers to int and void that are
already treated as SCALAR.
This provides consistent logic for single- and multi-level pointers:
if the type is treated as SCALAR for a single-level pointer, the
same applies to multi-level pointers, except for pointers to structs
which are currently PTR_TO_BTF_ID. However, in the case of
multi-level pointers, they are treated as scalar since the verifier
lacks the context to infer the size of their target memory regions.
Background:
Prior to these changes, accessing multi-level pointer parameters or
return values through BPF trampoline context arrays resulted in
verification failures in btf_ctx_access, producing errors such as:
func '%s' arg%d type %s is not a struct
For example, consider a BPF program that logs an input parameter of
type struct posix_acl **:
SEC("fentry/__posix_acl_chmod")
int BPF_PROG(trace_posix_acl_chmod, struct posix_acl **ppacl, gfp_t gfp,
umode_t mode)
{
bpf_printk("__posix_acl_chmod ppacl = %px\n", ppacl);
return 0;
}
This program failed BPF verification with the following error:
libbpf: prog 'trace_posix_acl_chmod': -- BEGIN PROG LOAD LOG --
0: R1=ctx() R10=fp0
; int BPF_PROG(trace_posix_acl_chmod, struct posix_acl **ppacl,
gfp_t gfp, umode_t mode) @ posix_acl_monitor.bpf.c:23
0: (79) r6 = *(u64 *)(r1 +16) ; R1=ctx() R6_w=scalar()
1: (79) r1 = *(u64 *)(r1 +0)
func '__posix_acl_chmod' arg0 type PTR is not a struct
invalid bpf_context access off=0 size=8
processed 2 insns (limit 1000000) max_states_per_insn 0 total_states 0
peak_states 0 mark_read 0
-- END PROG LOAD LOG --
The common workaround involved using helper functions to fetch
parameter values by passing the address of the context array entry:
SEC("fentry/__posix_acl_chmod")
int BPF_PROG(trace_posix_acl_chmod, struct posix_acl **ppacl, gfp_t gfp,
umode_t mode)
{
struct posix_acl **pp;
bpf_probe_read_kernel(&pp, sizeof(ppacl), &ctx[0]);
bpf_printk("__posix_acl_chmod %px\n", pp);
return 0;
}
This approach introduced helper call overhead and created
inconsistency with parameter access patterns.
Improvements:
With this patch, trampoline programs can directly access multi-level
pointer parameters, eliminating helper call overhead and explicit ctx
access while ensuring consistent parameter handling. For example, the
following ctx access with a helper call:
SEC("fentry/__posix_acl_chmod")
int BPF_PROG(trace_posix_acl_chmod, struct posix_acl **ppacl, gfp_t gfp,
umode_t mode)
{
struct posix_acl **pp;
bpf_probe_read_kernel(&pp, sizeof(pp), &ctx[0]);
bpf_printk("__posix_acl_chmod %px\n", pp);
...
}
is replaced by a load instruction:
SEC("fentry/__posix_acl_chmod")
int BPF_PROG(trace_posix_acl_chmod, struct posix_acl **ppacl, gfp_t gfp,
umode_t mode)
{
bpf_printk("__posix_acl_chmod %px\n", ppacl);
...
}
The bpf_core_cast macro can be used for deeper level dereferences.
v1 -> v2:
* corrected maintainer's email
v2 -> v3:
* Addressed reviewers' feedback:
* Changed the register type from PTR_TO_MEM to SCALAR_VALUE.
* Modified tests to accommodate SCALAR_VALUE handling.
* Fixed a compilation error for loongarch
* https://lore.kernel.org/oe-kbuild-all/202602181710.tEK6nOl6-lkp@intel.com/
* Addressed AI bot review
* Added a commentary to address a NULL pointer case
* Removed WARN_ON
* Fixed a commentary
v3 -> v4:
* Added more consistent support for single and multi-level pointers
as suggested by reviewers.
* added single level pointers to enum 32 and 64
* added single level pointers to functions
* harmonized support for single and multi-level pointer types
* added new tests to support the above changes
* Removed create_bad_kaddr that allocated and invalidated kernel VA
for tests, and replaced it with hardcoded values similar to
bpf_testmod_return_ptr as suggested by reviewers.
v4 -> v5:
* As suggested, extended support to single-level pointers and
covered all supported valid pointer (single- and multi-level) types
with a wider condition if (!btf_type_is_struct_ptr(t)).
* As requested, simplified tests by keeping only tests that check
the verifier log for scalar().
Slava Imameev (2):
bpf: Support pointer param types via SCALAR_VALUE for trampolines
selftests/bpf: Add trampolines single and multi-level pointer params
test coverage
kernel/bpf/btf.c | 17 ++---
net/bpf/test_run.c | 17 +++++
.../selftests/bpf/prog_tests/verifier.c | 2 +
.../bpf/progs/verifier_ctx_ptr_param.c | 68 +++++++++++++++++++
4 files changed, 94 insertions(+), 10 deletions(-)
create mode 100644 tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH bpf-next v5 1/2] bpf: Support pointer param types via SCALAR_VALUE for trampolines
2026-03-13 13:02 [PATCH bpf-next v5 0/2] bpf: Add multi-level pointer parameter support for trampolines Slava Imameev
@ 2026-03-13 13:02 ` Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage Slava Imameev
1 sibling, 0 replies; 6+ messages in thread
From: Slava Imameev @ 2026-03-13 13:02 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh,
sdf, haoluo, jolsa, davem, edumazet, kuba, pabeni, horms, shuah,
linux-kernel, bpf, netdev, linux-kselftest, linux-open-source,
Slava Imameev
Add BPF verifier support for single- and multi-level pointer
parameters and return values in BPF trampolines by treating these
parameters as SCALAR_VALUE.
This extends the existing support for int and void pointers that are
already treated as SCALAR_VALUE.
This provides consistent logic for single and multi-level pointers:
if a type is treated as SCALAR for a single-level pointer, the same
applies to multi-level pointers. The exception is pointer-to-struct,
which is currently PTR_TO_BTF_ID for single-level but treated as
scalar for multi-level pointers since the verifier lacks context
to infer the size of target memory regions.
Safety is ensured by existing BTF verification, which rejects invalid
pointer types at the BTF verification stage.
Signed-off-by: Slava Imameev <slava.imameev@crowdstrike.com>
---
kernel/bpf/btf.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 09fcbb125155..524bb2d6d964 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6508,13 +6508,6 @@ struct btf *bpf_prog_get_target_btf(const struct bpf_prog *prog)
return prog->aux->attach_btf;
}
-static bool is_void_or_int_ptr(struct btf *btf, const struct btf_type *t)
-{
- /* skip modifiers */
- t = btf_type_skip_modifiers(btf, t->type, NULL);
- return btf_type_is_void(t) || btf_type_is_int(t);
-}
-
u32 btf_ctx_arg_idx(struct btf *btf, const struct btf_type *func_proto,
int off)
{
@@ -6903,10 +6896,14 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
}
/*
- * If it's a pointer to void, it's the same as scalar from the verifier
- * safety POV. Either way, no futher pointer walking is allowed.
+ * If it's a single or multilevel pointer, except a pointer
+ * to a structure, it's the same as scalar from the verifier
+ * safety POV. Multilevel pointers to structures are treated as
+ * scalars. The verifier lacks the context to infer the size of
+ * their target memory regions. Either way, no further pointer
+ * walking is allowed.
*/
- if (is_void_or_int_ptr(btf, t))
+ if (!btf_type_is_struct_ptr(btf, t))
return true;
/* this is a pointer to another type */
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage
2026-03-13 13:02 [PATCH bpf-next v5 0/2] bpf: Add multi-level pointer parameter support for trampolines Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 1/2] bpf: Support pointer param types via SCALAR_VALUE " Slava Imameev
@ 2026-03-13 13:02 ` Slava Imameev
2026-03-13 13:55 ` bot+bpf-ci
1 sibling, 1 reply; 6+ messages in thread
From: Slava Imameev @ 2026-03-13 13:02 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh,
sdf, haoluo, jolsa, davem, edumazet, kuba, pabeni, horms, shuah,
linux-kernel, bpf, netdev, linux-kselftest, linux-open-source,
Slava Imameev
Add single and multi-level pointer parameters and return value test
coverage for BPF trampolines. Includes verifier tests for single and
multi-level pointers. The tests check verifier logs for pointers
inferred as scalar() type.
Signed-off-by: Slava Imameev <slava.imameev@crowdstrike.com>
---
net/bpf/test_run.c | 17 +++++
.../selftests/bpf/prog_tests/verifier.c | 2 +
.../bpf/progs/verifier_ctx_ptr_param.c | 68 +++++++++++++++++++
3 files changed, 87 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 56bc8dc1e281..14c4814a7dab 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -567,6 +567,23 @@ noinline void bpf_fentry_test_sinfo(struct skb_shared_info *sinfo)
{
}
+noinline void bpf_fentry_test_ppvoid(void **pp)
+{
+}
+
+noinline void bpf_fentry_test_pppvoid(void ***ppp)
+{
+}
+
+noinline void bpf_fentry_test_ppfile(struct file **ppf)
+{
+}
+
+noinline struct file **bpf_fexit_test_ret_ppfile(void)
+{
+ return (struct file **)NULL;
+}
+
__bpf_kfunc int bpf_modify_return_test(int a, int *b)
{
*b += 1;
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index 8cdfd74c95d7..bcf01cb4cfe4 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -115,6 +115,7 @@
#include "verifier_lsm.skel.h"
#include "verifier_jit_inline.skel.h"
#include "irq.skel.h"
+#include "verifier_ctx_ptr_param.skel.h"
#define MAX_ENTRIES 11
@@ -259,6 +260,7 @@ void test_verifier_lsm(void) { RUN(verifier_lsm); }
void test_irq(void) { RUN(irq); }
void test_verifier_mtu(void) { RUN(verifier_mtu); }
void test_verifier_jit_inline(void) { RUN(verifier_jit_inline); }
+void test_verifier_ctx_ptr_param(void) { RUN(verifier_ctx_ptr_param); }
static int init_test_val_map(struct bpf_object *obj, char *map_name)
{
diff --git a/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
new file mode 100644
index 000000000000..b507dc850543
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Verifier tests for single- and multi-level pointer parameter handling
+ * Copyright (c) 2026 CrowdStrike, Inc.
+ */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
+
+SEC("fentry/bpf_fentry_test_ppvoid")
+__description("fentry/void**: void ** inferred as scalar")
+__success __retval(0)
+__log_level(2)
+__msg("R1=ctx() R2=scalar()")
+__naked void fentry_ppvoid_as_scalar(void)
+{
+ asm volatile (" \
+ r2 = *(u64 *)(r1 + 0); \
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+}
+
+SEC("fentry/bpf_fentry_test_pppvoid")
+__description("fentry/void***: void *** inferred as scalar")
+__success __retval(0)
+__log_level(2)
+__msg("R1=ctx() R2=scalar()")
+__naked void fentry_pppvoid_as_scalar(void)
+{
+ asm volatile (" \
+ r2 = *(u64 *)(r1 + 0); \
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+}
+
+SEC("fentry/bpf_fentry_test_ppfile")
+__description("fentry/struct file***: struct file *** inferred as scalar")
+__success __retval(0)
+__log_level(2)
+__msg("R1=ctx() R2=scalar()")
+__naked void fentry_ppfile_as_scalar(void)
+{
+ asm volatile (" \
+ r2 = *(u64 *)(r1 + 0); \
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+}
+
+SEC("fexit/bpf_fexit_test_ret_ppfile")
+__description("fexit/return struct file**: returned struct file ** inferred as scalar")
+__success __retval(0)
+__log_level(2)
+__msg("R1=ctx() R2=scalar()")
+__naked void fexit_ppfile_as_scalar(void)
+{
+ asm volatile (" \
+ r2 = *(u64 *)(r1 + 0); \
+ r0 = 0; \
+ exit; \
+ " ::: __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage
2026-03-13 13:02 ` [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage Slava Imameev
@ 2026-03-13 13:55 ` bot+bpf-ci
2026-03-14 2:42 ` Alexei Starovoitov
0 siblings, 1 reply; 6+ messages in thread
From: bot+bpf-ci @ 2026-03-13 13:55 UTC (permalink / raw)
To: slava.imameev, ast, daniel, andrii
Cc: martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh,
sdf, haoluo, jolsa, davem, edumazet, kuba, pabeni, horms, shuah,
linux-kernel, bpf, netdev, linux-kselftest, linux-open-source,
slava.imameev, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1080 bytes --]
> diff --git a/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
> new file mode 100644
> index 000000000000..b507dc850543
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
[ ... ]
> +SEC("fentry/bpf_fentry_test_ppfile")
> +__description("fentry/struct file***: struct file *** inferred as scalar")
The description says "struct file ***" (triple pointer), but
bpf_fentry_test_ppfile() takes a struct file ** (double pointer):
net/bpf/test_run.c:
noinline void bpf_fentry_test_ppfile(struct file **ppf)
Should the description be
"fentry/struct file**: struct file ** inferred as scalar" instead?
> +__success __retval(0)
> +__log_level(2)
> +__msg("R1=ctx() R2=scalar()")
> +__naked void fentry_ppfile_as_scalar(void)
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/23052798110
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage
2026-03-13 13:55 ` bot+bpf-ci
@ 2026-03-14 2:42 ` Alexei Starovoitov
2026-03-14 6:16 ` Slava Imameev
0 siblings, 1 reply; 6+ messages in thread
From: Alexei Starovoitov @ 2026-03-14 2:42 UTC (permalink / raw)
To: bot+bpf-ci
Cc: Slava Imameev, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Shuah Khan, LKML, bpf,
Network Development, open list:KERNEL SELFTEST FRAMEWORK,
DL Linux Open Source Team, Martin KaFai Lau, Chris Mason,
Ihor Solodrai
On Fri, Mar 13, 2026 at 6:55 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
> > new file mode 100644
> > index 000000000000..b507dc850543
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
>
> [ ... ]
>
> > +SEC("fentry/bpf_fentry_test_ppfile")
> > +__description("fentry/struct file***: struct file *** inferred as scalar")
>
> The description says "struct file ***" (triple pointer), but
> bpf_fentry_test_ppfile() takes a struct file ** (double pointer):
>
> net/bpf/test_run.c:
> noinline void bpf_fentry_test_ppfile(struct file **ppf)
>
> Should the description be
> "fentry/struct file**: struct file ** inferred as scalar" instead?
Pls don't ignore bot reviews...
Do you agree or not?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage
2026-03-14 2:42 ` Alexei Starovoitov
@ 2026-03-14 6:16 ` Slava Imameev
0 siblings, 0 replies; 6+ messages in thread
From: Slava Imameev @ 2026-03-14 6:16 UTC (permalink / raw)
To: alexei.starovoitov
Cc: andrii, ast, bot+bpf-ci, bpf, clm, daniel, davem, eddyz87,
edumazet, haoluo, horms, ihor.solodrai, john.fastabend, jolsa,
kpsingh, kuba, linux-kernel, linux-kselftest, linux-open-source,
martin.lau, martin.lau, netdev, pabeni, sdf, shuah, slava.imameev,
song, yonghong.song
On Sat, 14 Mar 2026 02:42:28 Alexei Starovoitov wrote:
> On Fri, Mar 13, 2026 at 6:55=E2=80=AFAM <bot+bpf-ci@kernel.org> wrote:
> >
> > > diff --git a/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c=
> b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
> > > new file mode 100644
> > > index 000000000000..b507dc850543
> > > --- /dev/null
> > > +++ b/tools/testing/selftests/bpf/progs/verifier_ctx_ptr_param.c
> >
> > [ ... ]
> >
> > > +SEC("fentry/bpf_fentry_test_ppfile")
> > > +__description("fentry/struct file***: struct file *** inferred as scal=
> ar")
> >
> > The description says "struct file ***" (triple pointer), but
> > bpf_fentry_test_ppfile() takes a struct file ** (double pointer):
> >
> > net/bpf/test_run.c:
> noinline void bpf_fentry_test_ppfile(struct file **ppf)
> >
> > Should the description be
> > "fentry/struct file**: struct file ** inferred as scalar" instead?
>
> Pls don't ignore bot reviews...
> Do you agree or not?
I'm not ignoring the bot - I'm in Australia and pushed this
patch late at night at 12:05 AM Saturday. The bot replied 50 minutes
later at 12:55 AM Saturday, and I was already not at my desktop.
I will make the necessary changes to the test description. The bot is
correct that it should have been "struct file **" - I mistakenly
carried over the triple pointer description when copy-pasting the
comments.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-14 6:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-13 13:02 [PATCH bpf-next v5 0/2] bpf: Add multi-level pointer parameter support for trampolines Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 1/2] bpf: Support pointer param types via SCALAR_VALUE " Slava Imameev
2026-03-13 13:02 ` [PATCH bpf-next v5 2/2] selftests/bpf: Add trampolines single and multi-level pointer params test coverage Slava Imameev
2026-03-13 13:55 ` bot+bpf-ci
2026-03-14 2:42 ` Alexei Starovoitov
2026-03-14 6:16 ` Slava Imameev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox