* [PATCH bpf-next 0/2] bpf: Fix WARNING in bpf_tracing_link_release
@ 2026-07-21 13:30 Leon Hwang
2026-07-21 13:30 ` [PATCH bpf-next 1/2] " Leon Hwang
2026-07-21 13:30 ` [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link Leon Hwang
0 siblings, 2 replies; 5+ messages in thread
From: Leon Hwang @ 2026-07-21 13:30 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Shuah Khan, Jingguo Tan, Pu Lehui, Leon Hwang,
Lin Ma, Maciej Fijalkowski, linux-kernel, linux-kselftest,
kernel-patches-bot
The trampoline could be corrupted by the blindly
'tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX' in verifier.
1. A fexit attached to a tail_call_reachable prog.
2. Another fexit loaded with the same tail_call_reachable prog target.
3. Close the first fexit link.
[ 3.410719] WARNING: kernel/bpf/syscall.c:3551 at bpf_tracing_link_release+0x53/0x60, CPU#1: test_progs/98
...
[ 3.428793] bpf_link_free+0x58/0x130
[ 3.429293] bpf_link_release+0x23/0x30
Fix the warning by updating 'tr->flags' with '|=' and lock.
Leon Hwang (2):
bpf: Fix WARNING in bpf_tracing_link_release
selftests/bpf: Verify no warning when close fexit link
include/linux/bpf.h | 2 +
kernel/bpf/trampoline.c | 7 +++
kernel/bpf/verifier.c | 2 +-
.../selftests/bpf/prog_tests/tailcalls.c | 51 +++++++++++++++++++
4 files changed, 61 insertions(+), 1 deletion(-)
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf-next 1/2] bpf: Fix WARNING in bpf_tracing_link_release
2026-07-21 13:30 [PATCH bpf-next 0/2] bpf: Fix WARNING in bpf_tracing_link_release Leon Hwang
@ 2026-07-21 13:30 ` Leon Hwang
2026-07-22 11:19 ` Jiri Olsa
2026-07-21 13:30 ` [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link Leon Hwang
1 sibling, 1 reply; 5+ messages in thread
From: Leon Hwang @ 2026-07-21 13:30 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Shuah Khan, Jingguo Tan, Pu Lehui, Leon Hwang,
Lin Ma, Maciej Fijalkowski, linux-kernel, linux-kselftest,
kernel-patches-bot
The trampoline could be corrupted by the blindly
'tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX' in verifier.
1. A fexit attached to a tail_call_reachable prog.
2. Another fexit loaded with the same tail_call_reachable prog target.
3. Close the first fexit link.
[ 3.410719] WARNING: kernel/bpf/syscall.c:3551 at bpf_tracing_link_release+0x53/0x60, CPU#1: test_progs/98
...
[ 3.428793] bpf_link_free+0x58/0x130
[ 3.429293] bpf_link_release+0x23/0x30
Fix the warning by updating 'tr->flags' with '|=' and lock.
Fixes: 2b5dcb31a19a ("bpf, x64: Fix tailcall infinite loop")
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf.h | 2 ++
kernel/bpf/trampoline.c | 7 +++++++
kernel/bpf/verifier.c | 2 +-
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index d9542127dfdf..fc84f39967ae 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1523,6 +1523,7 @@ int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,
struct bpf_tracing_multi_link *link);
int bpf_trampoline_multi_detach(struct bpf_prog *prog,
struct bpf_tracing_multi_link *link);
+void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags);
/*
* When the architecture supports STATIC_CALL replace the bpf_dispatcher_fn
@@ -1646,6 +1647,7 @@ static inline int bpf_trampoline_multi_detach(struct bpf_prog *prog,
{
return -ENOTSUPP;
}
+static inline void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags) {}
#endif
struct bpf_func_info_aux {
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index 6eadf64f7ec9..129d07db117e 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -670,6 +670,13 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size)
return ERR_PTR(err);
}
+void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags)
+{
+ trampoline_lock(tr);
+ tr->flags |= flags;
+ trampoline_unlock(tr);
+}
+
static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex,
const struct bpf_trampoline_ops *ops, void *data)
{
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 52be0a118cce..66d8d9eaec05 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -19523,7 +19523,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
return -ENOMEM;
if (tgt_prog && tgt_prog->aux->tail_call_reachable)
- tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX;
+ bpf_trampoline_set_flags(tr, BPF_TRAMP_F_TAIL_CALL_CTX);
prog->aux->dst_trampoline = tr;
return 0;
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link
2026-07-21 13:30 [PATCH bpf-next 0/2] bpf: Fix WARNING in bpf_tracing_link_release Leon Hwang
2026-07-21 13:30 ` [PATCH bpf-next 1/2] " Leon Hwang
@ 2026-07-21 13:30 ` Leon Hwang
2026-07-22 11:20 ` Jiri Olsa
1 sibling, 1 reply; 5+ messages in thread
From: Leon Hwang @ 2026-07-21 13:30 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Shuah Khan, Jingguo Tan, Pu Lehui, Leon Hwang,
Lin Ma, Maciej Fijalkowski, linux-kernel, linux-kselftest,
kernel-patches-bot
Add a test to verify that there's no WARNING when detaching fexit link by
following the repro steps of previous commit.
Without the fix, the WARNING could be triggered by this test.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
.../selftests/bpf/prog_tests/tailcalls.c | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
index c66037162da5..86d87d5817cf 100644
--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
@@ -13,6 +13,8 @@
#include "tailcall_cgrp_storage.skel.h"
#include "tailcall_sleepable.skel.h"
#include "tailcall_callback.skel.h"
+#include "tailcall_bpf2bpf2.skel.h"
+#include "tailcall_bpf2bpf_fexit.skel.h"
/* test_tailcall_1 checks basic functionality by patching multiple locations
* in a single program for a single tail call slot with nop->jmp, jmp->nop
@@ -1907,6 +1909,53 @@ static void test_tailcall_callback(void)
RUN_TESTS(tailcall_callback);
}
+static void test_tailcall_bpf2bpf_fexit_links(void)
+{
+ struct tailcall_bpf2bpf_fexit *skel1 = NULL, *skel2 = NULL;
+ struct tailcall_bpf2bpf2 *skel_tc;
+ struct bpf_link *link;
+ int err, prog_fd;
+
+ skel_tc = tailcall_bpf2bpf2__open_and_load();
+ if (!ASSERT_OK_PTR(skel_tc, "tailcall_bpf2bpf2__open_and_load"))
+ return;
+
+ skel1 = tailcall_bpf2bpf_fexit__open();
+ if (!ASSERT_OK_PTR(skel1, "tailcall_bpf2bpf_fexit__open"))
+ goto out;
+
+ prog_fd = bpf_program__fd(skel_tc->progs.classifier_0);
+ err = bpf_program__set_attach_target(skel1->progs.fexit, prog_fd, "subprog_tail");
+ if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
+ goto out;
+
+ err = tailcall_bpf2bpf_fexit__load(skel1);
+ if (!ASSERT_OK(err, "tailcall_bpf2bpf_fexit__load"))
+ goto out;
+
+ link = bpf_program__attach_trace(skel1->progs.fexit);
+ if (!ASSERT_OK_PTR(link, "bpf_program__attach_trace"))
+ goto out;
+ skel1->links.fexit = link;
+
+ skel2 = tailcall_bpf2bpf_fexit__open();
+ if (!ASSERT_OK_PTR(skel2, "tailcall_bpf2bpf_fexit__open"))
+ goto out;
+
+ err = bpf_program__set_attach_target(skel2->progs.fexit, prog_fd, "subprog_tail");
+ if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
+ goto out;
+
+ err = tailcall_bpf2bpf_fexit__load(skel2);
+ if (!ASSERT_OK(err, "tailcall_bpf2bpf_fexit__load"))
+ goto out;
+
+out:
+ tailcall_bpf2bpf_fexit__destroy(skel1);
+ tailcall_bpf2bpf_fexit__destroy(skel2);
+ tailcall_bpf2bpf2__destroy(skel_tc);
+}
+
void test_tailcalls(void)
{
if (test__start_subtest("tailcall_1"))
@@ -1974,4 +2023,6 @@ void test_tailcalls(void)
if (test__start_subtest("tailcall_cgrp_storage_no_storage_bridge"))
test_tailcall_cgrp_storage_no_storage_bridge();
test_tailcall_callback();
+ if (test__start_subtest("tailcall_bpf2bpf_fexit_links"))
+ test_tailcall_bpf2bpf_fexit_links();
}
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next 1/2] bpf: Fix WARNING in bpf_tracing_link_release
2026-07-21 13:30 ` [PATCH bpf-next 1/2] " Leon Hwang
@ 2026-07-22 11:19 ` Jiri Olsa
0 siblings, 0 replies; 5+ messages in thread
From: Jiri Olsa @ 2026-07-22 11:19 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Emil Tsalapatis,
Shuah Khan, Jingguo Tan, Pu Lehui, Lin Ma, Maciej Fijalkowski,
linux-kernel, linux-kselftest, kernel-patches-bot
On Tue, Jul 21, 2026 at 09:30:34PM +0800, Leon Hwang wrote:
> The trampoline could be corrupted by the blindly
> 'tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX' in verifier.
>
> 1. A fexit attached to a tail_call_reachable prog.
> 2. Another fexit loaded with the same tail_call_reachable prog target.
> 3. Close the first fexit link.
had to ask ai for more details on how the warning was trigered ;-)
would be nice to have that info in the changelog
Acked-by: Jiri Olsa <jolsa@kernel.org>
jirka
>
> [ 3.410719] WARNING: kernel/bpf/syscall.c:3551 at bpf_tracing_link_release+0x53/0x60, CPU#1: test_progs/98
> ...
> [ 3.428793] bpf_link_free+0x58/0x130
> [ 3.429293] bpf_link_release+0x23/0x30
>
> Fix the warning by updating 'tr->flags' with '|=' and lock.
>
> Fixes: 2b5dcb31a19a ("bpf, x64: Fix tailcall infinite loop")
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf.h | 2 ++
> kernel/bpf/trampoline.c | 7 +++++++
> kernel/bpf/verifier.c | 2 +-
> 3 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index d9542127dfdf..fc84f39967ae 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1523,6 +1523,7 @@ int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,
> struct bpf_tracing_multi_link *link);
> int bpf_trampoline_multi_detach(struct bpf_prog *prog,
> struct bpf_tracing_multi_link *link);
> +void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags);
>
> /*
> * When the architecture supports STATIC_CALL replace the bpf_dispatcher_fn
> @@ -1646,6 +1647,7 @@ static inline int bpf_trampoline_multi_detach(struct bpf_prog *prog,
> {
> return -ENOTSUPP;
> }
> +static inline void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags) {}
> #endif
>
> struct bpf_func_info_aux {
> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> index 6eadf64f7ec9..129d07db117e 100644
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c
> @@ -670,6 +670,13 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size)
> return ERR_PTR(err);
> }
>
> +void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags)
> +{
> + trampoline_lock(tr);
> + tr->flags |= flags;
> + trampoline_unlock(tr);
> +}
> +
> static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex,
> const struct bpf_trampoline_ops *ops, void *data)
> {
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 52be0a118cce..66d8d9eaec05 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -19523,7 +19523,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
> return -ENOMEM;
>
> if (tgt_prog && tgt_prog->aux->tail_call_reachable)
> - tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX;
> + bpf_trampoline_set_flags(tr, BPF_TRAMP_F_TAIL_CALL_CTX);
>
> prog->aux->dst_trampoline = tr;
> return 0;
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link
2026-07-21 13:30 ` [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link Leon Hwang
@ 2026-07-22 11:20 ` Jiri Olsa
0 siblings, 0 replies; 5+ messages in thread
From: Jiri Olsa @ 2026-07-22 11:20 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Emil Tsalapatis,
Shuah Khan, Jingguo Tan, Pu Lehui, Lin Ma, Maciej Fijalkowski,
linux-kernel, linux-kselftest, kernel-patches-bot
On Tue, Jul 21, 2026 at 09:30:35PM +0800, Leon Hwang wrote:
> Add a test to verify that there's no WARNING when detaching fexit link by
> following the repro steps of previous commit.
>
> Without the fix, the WARNING could be triggered by this test.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
left 2 nits below
Acked-by: Jiri Olsa <jolsa@kernel.org>
jirka
> ---
> .../selftests/bpf/prog_tests/tailcalls.c | 51 +++++++++++++++++++
> 1 file changed, 51 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> index c66037162da5..86d87d5817cf 100644
> --- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> +++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> @@ -13,6 +13,8 @@
> #include "tailcall_cgrp_storage.skel.h"
> #include "tailcall_sleepable.skel.h"
> #include "tailcall_callback.skel.h"
> +#include "tailcall_bpf2bpf2.skel.h"
> +#include "tailcall_bpf2bpf_fexit.skel.h"
>
> /* test_tailcall_1 checks basic functionality by patching multiple locations
> * in a single program for a single tail call slot with nop->jmp, jmp->nop
> @@ -1907,6 +1909,53 @@ static void test_tailcall_callback(void)
> RUN_TESTS(tailcall_callback);
> }
>
> +static void test_tailcall_bpf2bpf_fexit_links(void)
> +{
> + struct tailcall_bpf2bpf_fexit *skel1 = NULL, *skel2 = NULL;
> + struct tailcall_bpf2bpf2 *skel_tc;
> + struct bpf_link *link;
> + int err, prog_fd;
> +
> + skel_tc = tailcall_bpf2bpf2__open_and_load();
> + if (!ASSERT_OK_PTR(skel_tc, "tailcall_bpf2bpf2__open_and_load"))
> + return;
> +
> + skel1 = tailcall_bpf2bpf_fexit__open();
> + if (!ASSERT_OK_PTR(skel1, "tailcall_bpf2bpf_fexit__open"))
> + goto out;
> +
> + prog_fd = bpf_program__fd(skel_tc->progs.classifier_0);
> + err = bpf_program__set_attach_target(skel1->progs.fexit, prog_fd, "subprog_tail");
> + if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
> + goto out;
> +
> + err = tailcall_bpf2bpf_fexit__load(skel1);
> + if (!ASSERT_OK(err, "tailcall_bpf2bpf_fexit__load"))
> + goto out;
> +
> + link = bpf_program__attach_trace(skel1->progs.fexit);
> + if (!ASSERT_OK_PTR(link, "bpf_program__attach_trace"))
> + goto out;
> + skel1->links.fexit = link;
nit, you could use skel1->links.fexit directly and remove link
> +
> + skel2 = tailcall_bpf2bpf_fexit__open();
> + if (!ASSERT_OK_PTR(skel2, "tailcall_bpf2bpf_fexit__open"))
> + goto out;
> +
> + err = bpf_program__set_attach_target(skel2->progs.fexit, prog_fd, "subprog_tail");
> + if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
> + goto out;
> +
> + err = tailcall_bpf2bpf_fexit__load(skel2);
> + if (!ASSERT_OK(err, "tailcall_bpf2bpf_fexit__load"))
> + goto out;
nit, no need to if/goto, just ASSERT_OK would be enough
> +
> +out:
> + tailcall_bpf2bpf_fexit__destroy(skel1);
> + tailcall_bpf2bpf_fexit__destroy(skel2);
> + tailcall_bpf2bpf2__destroy(skel_tc);
> +}
> +
> void test_tailcalls(void)
> {
> if (test__start_subtest("tailcall_1"))
> @@ -1974,4 +2023,6 @@ void test_tailcalls(void)
> if (test__start_subtest("tailcall_cgrp_storage_no_storage_bridge"))
> test_tailcall_cgrp_storage_no_storage_bridge();
> test_tailcall_callback();
> + if (test__start_subtest("tailcall_bpf2bpf_fexit_links"))
> + test_tailcall_bpf2bpf_fexit_links();
> }
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-22 11:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 13:30 [PATCH bpf-next 0/2] bpf: Fix WARNING in bpf_tracing_link_release Leon Hwang
2026-07-21 13:30 ` [PATCH bpf-next 1/2] " Leon Hwang
2026-07-22 11:19 ` Jiri Olsa
2026-07-21 13:30 ` [PATCH bpf-next 2/2] selftests/bpf: Verify no warning when close fexit link Leon Hwang
2026-07-22 11:20 ` Jiri Olsa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox