BPF List
 help / color / mirror / Atom feed
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


  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