From: Yonghong Song <yonghong.song@linux.dev>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
kernel-team@fb.com, Martin KaFai Lau <martin.lau@kernel.org>
Subject: [PATCH bpf-next v2 1/2] selftests/bpf: Keep int return type for tailcall subprogs
Date: Tue, 9 Jun 2026 16:34:07 -0700 [thread overview]
Message-ID: <20260609233407.2711577-1-yonghong.song@linux.dev> (raw)
In-Reply-To: <20260609233402.2711071-1-yonghong.song@linux.dev>
LLVM23 ([1]) supports 'true' function signature in BTF. The return type
of the caller of a tailcall must be an 'int'. Otherwise, verification will
fail (see check_btf_func() in check_btf.c). So with llvm23, it is possible
that the compiler may change the caller's return type from 'int' to 'void'.
To prevent this, barrier_var() and __sink() are used to avoid returning
a constant prone to be optimized.
[1] https://github.com/llvm/llvm-project/pull/198426
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
.../selftests/bpf/progs/tailcall_bpf2bpf2.c | 5 +++-
.../bpf/progs/tailcall_bpf2bpf_hierarchy1.c | 13 ++++++----
.../bpf/progs/tailcall_bpf2bpf_hierarchy2.c | 24 +++++++++++++------
.../bpf/progs/tailcall_bpf2bpf_hierarchy3.c | 13 +++++++---
.../progs/tailcall_bpf2bpf_hierarchy_fentry.c | 13 +++++++---
.../selftests/bpf/progs/verifier_sock.c | 9 +++++--
6 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf2.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf2.c
index ce97d141daee..c4fadee5aadc 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf2.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf2.c
@@ -13,11 +13,14 @@ struct {
static __noinline
int subprog_tail(struct __sk_buff *skb)
{
+ int ret = 1;
+
if (load_byte(skb, 0))
bpf_tail_call_static(skb, &jmp_table, 1);
else
bpf_tail_call_static(skb, &jmp_table, 0);
- return 1;
+ barrier_var(ret);
+ return ret;
}
int count = 0;
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy1.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy1.c
index d556b19413d7..1fd07824d88a 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy1.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy1.c
@@ -16,20 +16,25 @@ int count = 0;
static __noinline
int subprog_tail(struct __sk_buff *skb)
{
+ int ret = 0;
+
bpf_tail_call_static(skb, &jmp_table, 0);
- return 0;
+ barrier_var(ret);
+ return ret;
}
SEC("tc")
int entry(struct __sk_buff *skb)
{
- int ret = 1;
+ int ret = 1, ret1, ret2;
clobber_regs_stack();
count++;
- subprog_tail(skb);
- subprog_tail(skb);
+ ret1 = subprog_tail(skb);
+ ret2 = subprog_tail(skb);
+ __sink(ret1);
+ __sink(ret2);
return ret;
}
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy2.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy2.c
index ae94c9c70ab7..6fde0ab92148 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy2.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy2.c
@@ -25,8 +25,11 @@ int count1 = 0;
static __noinline
int subprog_tail0(struct __sk_buff *skb)
{
+ int ret = 0;
+
bpf_tail_call_static(skb, &jmp_table, 0);
- return 0;
+ barrier_var(ret);
+ return ret;
}
__auxiliary
@@ -41,16 +44,22 @@ int classifier_0(struct __sk_buff *skb)
static __noinline
int subprog_tail1(struct __sk_buff *skb)
{
+ int ret = 0;
+
bpf_tail_call_static(skb, &jmp_table, 1);
- return 0;
+ barrier_var(ret);
+ return ret;
}
__auxiliary
SEC("tc")
int classifier_1(struct __sk_buff *skb)
{
+ int ret;
+
count1++;
- subprog_tail1(skb);
+ ret = subprog_tail1(skb);
+ __sink(ret);
return 0;
}
@@ -59,13 +68,14 @@ __retval(33)
SEC("tc")
int tailcall_bpf2bpf_hierarchy_2(struct __sk_buff *skb)
{
- int ret = 0;
+ int ret = 0, ret1, ret2;
clobber_regs_stack();
- subprog_tail0(skb);
- subprog_tail1(skb);
-
+ ret1 = subprog_tail0(skb);
+ ret2 = subprog_tail1(skb);
+ __sink(ret1);
+ __sink(ret2);
__sink(ret);
return (count1 << 16) | count0;
}
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy3.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy3.c
index 56b6b0099840..0ef9cfb2da8d 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy3.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy3.c
@@ -33,17 +33,24 @@ int count = 0;
static __noinline
int subprog_tail(struct __sk_buff *skb, void *jmp_table)
{
+ int ret = 0;
+
bpf_tail_call_static(skb, jmp_table, 0);
- return 0;
+ barrier_var(ret);
+ return ret;
}
__auxiliary
SEC("tc")
int classifier_0(struct __sk_buff *skb)
{
+ int ret1, ret2;
+
count++;
- subprog_tail(skb, &jmp_table0);
- subprog_tail(skb, &jmp_table1);
+ ret1 = subprog_tail(skb, &jmp_table0);
+ ret2 = subprog_tail(skb, &jmp_table1);
+ __sink(ret1);
+ __sink(ret2);
return count;
}
diff --git a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy_fentry.c b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy_fentry.c
index 5261395713cd..6db9afee2095 100644
--- a/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy_fentry.c
+++ b/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy_fentry.c
@@ -18,18 +18,25 @@ int count = 0;
static __noinline
int subprog_tail(void *ctx)
{
+ int ret = 0;
+
bpf_tail_call_static(ctx, &jmp_table, 0);
- return 0;
+ barrier_var(ret);
+ return ret;
}
SEC("fentry/dummy")
int BPF_PROG(fentry, struct sk_buff *skb)
{
+ int ret1, ret2;
+
clobber_regs_stack();
count++;
- subprog_tail(ctx);
- subprog_tail(ctx);
+ ret1 = subprog_tail(ctx);
+ ret2 = subprog_tail(ctx);
+ __sink(ret1);
+ __sink(ret2);
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/verifier_sock.c b/tools/testing/selftests/bpf/progs/verifier_sock.c
index 9f680cf44512..4f2f3209eec8 100644
--- a/tools/testing/selftests/bpf/progs/verifier_sock.c
+++ b/tools/testing/selftests/bpf/progs/verifier_sock.c
@@ -1120,8 +1120,11 @@ int tail_call(struct __sk_buff *sk)
static __noinline
int static_tail_call(struct __sk_buff *sk)
{
+ int ret = 0;
+
bpf_tail_call_static(sk, &jmp_table, 0);
- return 0;
+ barrier_var(ret);
+ return ret;
}
/* Tail calls in sub-programs invalidate packet pointers. */
@@ -1144,10 +1147,12 @@ __failure __msg("invalid mem access")
int invalidate_pkt_pointers_by_static_tail_call(struct __sk_buff *sk)
{
int *p = (void *)(long)sk->data;
+ int ret;
if ((void *)(p + 1) > (void *)(long)sk->data_end)
return TCX_DROP;
- static_tail_call(sk);
+ ret = static_tail_call(sk);
+ __sink(ret);
*p = 42; /* this is unsafe */
return TCX_PASS;
}
--
2.53.0-Meta
next prev parent reply other threads:[~2026-06-09 23:34 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-09 23:34 [PATCH bpf-next v2 0/2] selftests/bpf: Fix tests for llvm23 true signature Yonghong Song
2026-06-09 23:34 ` Yonghong Song [this message]
2026-06-09 23:42 ` [PATCH bpf-next v2 1/2] selftests/bpf: Keep int return type for tailcall subprogs sashiko-bot
2026-06-10 3:41 ` Yonghong Song
2026-06-10 4:06 ` Yonghong Song
2026-06-10 0:07 ` bot+bpf-ci
2026-06-10 3:45 ` Yonghong Song
2026-06-09 23:34 ` [PATCH bpf-next v2 2/2] selftests/bpf: Adjust fexit_bpf2bpf ctx layout for llvm23 true signature Yonghong Song
2026-06-10 4:30 ` [PATCH bpf-next v2 0/2] selftests/bpf: Fix tests " patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260609233407.2711577-1-yonghong.song@linux.dev \
--to=yonghong.song@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=martin.lau@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox