BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches
@ 2026-09-24  2:37 chenyuan_fl
  2026-09-24  2:37 ` [PATCH bpf-next v2 1/2] " chenyuan_fl
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: chenyuan_fl @ 2026-09-24  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, ast, leon.hwang
  Cc: bpf, daniel, andrii, eddyz87, memxor, martin.lau, yonghong.song,
	john.fastabend, song, ihor.solodrai, Yuan Chen

From: Yuan Chen <chenyuan@kylinos.cn>

is_extended is a plain boolean, but one target prog can carry several
freplace links at the same time, one on its entry and one on a global
subprogram.  __bpf_trampoline_unlink_prog() cleared it whenever *any*
of them detached, so with two links on one target, detaching one of
them re-armed the unbounded tail call loop closed by commit
d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace"):
a single BPF_PROG_TEST_RUN on the tail-called target then panics the
kernel, reproduced on both bpf-next and master.

Patch 1 replaces the boolean with a count of the freplace links
attached to each target prog, so the target stays extended until its
last link detaches.  Patch 2 adds a selftest covering the sequence.

Changes since v1:

- freplace_link_cnt is u16 instead of u64, per Alexei's review: it is
  bounded by BPF_MAX_SUBPROGS, which counts the entry function too, so
  up to 256 links, one past u8, and it sits in the padding next to
  stack_arg_sp_adjust, so bpf_prog_aux does not grow
- dropped the separate is_extended boolean, deriving the extended state
  from the count itself
- renamed bpf_freplace_check_tgt_prog() to bpf_freplace_link_tgt_prog(),
  it reserves the target on success
- dropped the WARN_ON_ONCE() on detach, per Leon's review: the count is
  paired by the link lifetime and the sibling prog_array_member_cnt
  decrement is not guarded either

Yuan Chen (2):
  bpf: Keep target extended until its last freplace link detaches
  selftests/bpf: Verify is_extended with multiple freplace links

 include/linux/bpf.h                           |  4 +-
 kernel/bpf/arraymap.c                         |  2 +-
 kernel/bpf/trampoline.c                       |  8 +-
 .../selftests/bpf/prog_tests/tailcalls.c      | 74 +++++++++++++++++++
 .../bpf/progs/tailcall_freplace_multi.c       | 27 +++++++
 5 files changed, 108 insertions(+), 7 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c

-- 
2.54.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH bpf-next v2 1/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  2:37 [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
@ 2026-09-24  2:37 ` chenyuan_fl
  2026-09-24  7:06   ` Leon Hwang
  2026-09-24  2:37 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links chenyuan_fl
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: chenyuan_fl @ 2026-09-24  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, ast, leon.hwang
  Cc: bpf, daniel, andrii, eddyz87, memxor, martin.lau, yonghong.song,
	john.fastabend, song, ihor.solodrai, Yuan Chen

From: Yuan Chen <chenyuan@kylinos.cn>

The is_extended / prog_array_member_cnt protocol introduced by commit
d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
keeps a prog extended by a freplace program out of prog_array maps, and
vice versa: once a tail call re-enters an extended subprogram, its
tail_call_cnt resets on every execution and the loop never terminates.

But is_extended is a plain boolean, while one target prog can carry
several freplace links at the same time, one on its entry and one on a
global subprogram.  __bpf_trampoline_unlink_prog() cleared is_extended
whenever *any* freplace link detached, so detaching one of two links
re-armed the unbounded loop through the remaining one.

Replace the is_extended boolean with a count of the freplace links
attached to each target prog, so the target stays extended until its
last link detaches.  Also rename bpf_freplace_check_tgt_prog() to
bpf_freplace_link_tgt_prog(), as the helper has never been a pure
check: it reserves the target prog on success.

Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
 include/linux/bpf.h     | 4 ++--
 kernel/bpf/arraymap.c   | 2 +-
 kernel/bpf/trampoline.c | 8 ++++----
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 73bacfc6444d..44411a93d0ea 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1773,7 +1773,6 @@ struct bpf_prog_aux {
 	bool xdp_has_frags;
 	bool exception_cb;
 	bool exception_boundary;
-	bool is_extended; /* true if extended by freplace program */
 	bool jits_use_priv_stack;
 	bool priv_stack_requested;
 	bool changes_pkt_data;
@@ -1785,7 +1784,7 @@ struct bpf_prog_aux {
 		u8 verdict;
 	} sig;
 	u64 prog_array_member_cnt; /* counts how many times as member of prog_array */
-	struct mutex ext_mutex; /* mutex for is_extended and prog_array_member_cnt */
+	struct mutex ext_mutex; /* mutex for freplace_link_cnt and prog_array_member_cnt */
 	struct bpf_arena *arena;
 	void (*recursion_detected)(struct bpf_prog *prog); /* callback if recursion is detected */
 	/* BTF_KIND_FUNC_PROTO for valid attach_btf_id */
@@ -1817,6 +1816,7 @@ struct bpf_prog_aux {
 	char name[BPF_OBJ_NAME_LEN];
 	u64 (*bpf_exception_cb)(u64 cookie, u64 sp, u64 bp, u64, u64);
 	u16 stack_arg_sp_adjust;
+	u16 freplace_link_cnt; /* counts freplace links extending this prog */
 #ifdef CONFIG_SECURITY
 	void *security;
 #endif
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 248b4818178c..3bcff6a0430d 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -974,7 +974,7 @@ static void *prog_fd_array_get_ptr(struct bpf_map *map,
 	}
 
 	mutex_lock(&prog->aux->ext_mutex);
-	is_extended = prog->aux->is_extended;
+	is_extended = prog->aux->freplace_link_cnt > 0;
 	if (!is_extended)
 		prog->aux->prog_array_member_cnt++;
 	mutex_unlock(&prog->aux->ext_mutex);
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index ed7999ad6c66..68e57ceb34f6 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -813,7 +813,7 @@ static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
 	}
 }
 
-static int bpf_freplace_check_tgt_prog(struct bpf_prog *tgt_prog)
+static int bpf_freplace_link_tgt_prog(struct bpf_prog *tgt_prog)
 {
 	struct bpf_prog_aux *aux = tgt_prog->aux;
 
@@ -827,7 +827,7 @@ static int bpf_freplace_check_tgt_prog(struct bpf_prog *tgt_prog)
 		 */
 		return -EBUSY;
 
-	aux->is_extended = true;
+	aux->freplace_link_cnt++;
 	return 0;
 }
 
@@ -933,7 +933,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
 		/* Cannot attach extension if fentry/fexit are in use. */
 		if (cnt)
 			return -EBUSY;
-		err = bpf_freplace_check_tgt_prog(tgt_prog);
+		err = bpf_freplace_link_tgt_prog(tgt_prog);
 		if (err)
 			return err;
 		tr->extension_prog = node->link->prog;
@@ -979,7 +979,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_node *node,
 					 tr->extension_prog->bpf_func, NULL);
 		tr->extension_prog = NULL;
 		guard(mutex)(&tgt_prog->aux->ext_mutex);
-		tgt_prog->aux->is_extended = false;
+		tgt_prog->aux->freplace_link_cnt--;
 		return err;
 	}
 	bpf_trampoline_remove_prog(tr, node);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links
  2026-09-24  2:37 [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
  2026-09-24  2:37 ` [PATCH bpf-next v2 1/2] " chenyuan_fl
@ 2026-09-24  2:37 ` chenyuan_fl
  2026-09-24  7:06   ` Leon Hwang
  2026-09-24  8:42 ` [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches Jiri Olsa
  2026-09-24  9:00 ` patchwork-bot+netdevbpf
  3 siblings, 1 reply; 13+ messages in thread
From: chenyuan_fl @ 2026-09-24  2:37 UTC (permalink / raw)
  To: alexei.starovoitov, ast, leon.hwang
  Cc: bpf, daniel, andrii, eddyz87, memxor, martin.lau, yonghong.song,
	john.fastabend, song, ihor.solodrai, Yuan Chen

From: Yuan Chen <chenyuan@kylinos.cn>

Extend tc_bpf2bpf with two freplace links, one on entry_tc and one on
subprog_tc, and detach the one on the entry: while subprog_tc is still
extended, updating entry_tc into a prog_array map must keep failing
with -EBUSY, and succeed again once the last link detaches.  The test
asserts the rejection instead of running the prog, as the update
succeeds and the prog loops unbounded on an unfixed kernel.

Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
 .../selftests/bpf/prog_tests/tailcalls.c      | 74 +++++++++++++++++++
 .../bpf/progs/tailcall_freplace_multi.c       | 27 +++++++
 2 files changed, 101 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c

diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
index c5c9d6c359bb..aefb46778307 100644
--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
@@ -6,6 +6,7 @@
 #include "tailcall_bpf2bpf_hierarchy2.skel.h"
 #include "tailcall_bpf2bpf_hierarchy3.skel.h"
 #include "tailcall_freplace.skel.h"
+#include "tailcall_freplace_multi.skel.h"
 #include "tc_bpf2bpf.skel.h"
 #include "tailcall_fail.skel.h"
 #include "tailcall_cgrp_storage_owner.skel.h"
@@ -1655,6 +1656,77 @@ static void test_tailcall_bpf2bpf_freplace(void)
 	tc_bpf2bpf__destroy(tc_skel);
 }
 
+static void test_tailcall_freplace_multi(void)
+{
+	struct tailcall_freplace_multi *freplace_skel = NULL;
+	struct bpf_link *link_subprog = NULL, *link_entry = NULL;
+	struct tc_bpf2bpf *tc_skel = NULL;
+	int tc_prog_fd, map_fd, key = 0, err;
+
+	tc_skel = tc_bpf2bpf__open_and_load();
+	if (!ASSERT_OK_PTR(tc_skel, "tc_bpf2bpf__open_and_load"))
+		return;
+
+	tc_prog_fd = bpf_program__fd(tc_skel->progs.entry_tc);
+
+	freplace_skel = tailcall_freplace_multi__open();
+	if (!ASSERT_OK_PTR(freplace_skel, "tailcall_freplace_multi__open"))
+		goto out;
+
+	err = bpf_program__set_attach_target(freplace_skel->progs.subprog_freplace,
+					     tc_prog_fd, "subprog_tc");
+	if (!ASSERT_OK(err, "set_attach_target subprog_tc"))
+		goto out;
+
+	err = bpf_program__set_attach_target(freplace_skel->progs.entry_freplace,
+					     tc_prog_fd, "entry_tc");
+	if (!ASSERT_OK(err, "set_attach_target entry_tc"))
+		goto out;
+
+	err = tailcall_freplace_multi__load(freplace_skel);
+	if (!ASSERT_OK(err, "tailcall_freplace_multi__load"))
+		goto out;
+
+	map_fd = bpf_map__fd(freplace_skel->maps.jmp_table);
+
+	link_subprog = bpf_program__attach_freplace(freplace_skel->progs.subprog_freplace,
+						    tc_prog_fd, "subprog_tc");
+	if (!ASSERT_OK_PTR(link_subprog, "attach_freplace subprog_tc"))
+		goto out;
+
+	link_entry = bpf_program__attach_freplace(freplace_skel->progs.entry_freplace,
+						  tc_prog_fd, "entry_tc");
+	if (!ASSERT_OK_PTR(link_entry, "attach_freplace entry_tc"))
+		goto out;
+
+	err = bpf_map_update_elem(map_fd, &key, &tc_prog_fd, BPF_ANY);
+	if (!ASSERT_ERR(err, "update jmp_table with extended prog"))
+		goto out;
+
+	err = bpf_link__destroy(link_entry);
+	link_entry = NULL;
+	if (!ASSERT_OK(err, "destroy entry link"))
+		goto out;
+
+	err = bpf_map_update_elem(map_fd, &key, &tc_prog_fd, BPF_ANY);
+	if (!ASSERT_ERR(err, "update jmp_table with still extended prog"))
+		goto out;
+
+	err = bpf_link__destroy(link_subprog);
+	link_subprog = NULL;
+	if (!ASSERT_OK(err, "destroy subprog link"))
+		goto out;
+
+	err = bpf_map_update_elem(map_fd, &key, &tc_prog_fd, BPF_ANY);
+	ASSERT_OK(err, "update jmp_table");
+
+out:
+	bpf_link__destroy(link_subprog);
+	bpf_link__destroy(link_entry);
+	tailcall_freplace_multi__destroy(freplace_skel);
+	tc_bpf2bpf__destroy(tc_skel);
+}
+
 static void test_tailcall_failure()
 {
 	RUN_TESTS(tailcall_fail);
@@ -2005,6 +2077,8 @@ void test_tailcalls(void)
 		test_tailcall_freplace();
 	if (test__start_subtest("tailcall_bpf2bpf_freplace"))
 		test_tailcall_bpf2bpf_freplace();
+	if (test__start_subtest("tailcall_freplace_multi"))
+		test_tailcall_freplace_multi();
 	if (test__start_subtest("tailcall_failure"))
 		test_tailcall_failure();
 	if (test__start_subtest("tailcall_sleepable"))
diff --git a/tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c b/tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c
new file mode 100644
index 000000000000..ca764411dc0b
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 KylinSoft Corporation. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+struct {
+	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
+	__uint(max_entries, 1);
+	__uint(key_size, sizeof(__u32));
+	__uint(value_size, sizeof(__u32));
+} jmp_table SEC(".maps");
+
+SEC("freplace")
+int subprog_freplace(struct __sk_buff *skb)
+{
+	bpf_tail_call_static(skb, &jmp_table, 0);
+	return 0;
+}
+
+SEC("freplace")
+int entry_freplace(struct __sk_buff *skb)
+{
+	return 0;
+}
+
+char __license[] SEC("license") = "GPL";
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next v2 1/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  2:37 ` [PATCH bpf-next v2 1/2] " chenyuan_fl
@ 2026-09-24  7:06   ` Leon Hwang
  2026-09-24  9:48     ` Jiri Olsa
  2026-09-24  9:58     ` chenyuan
  0 siblings, 2 replies; 13+ messages in thread
From: Leon Hwang @ 2026-09-24  7:06 UTC (permalink / raw)
  To: chenyuan_fl, alexei.starovoitov, ast, leon.hwang
  Cc: bpf, daniel, andrii, eddyz87, memxor, martin.lau, yonghong.song,
	john.fastabend, song, ihor.solodrai, Yuan Chen

On 24/9/26 10:37, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> The is_extended / prog_array_member_cnt protocol introduced by commit
> d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
> keeps a prog extended by a freplace program out of prog_array maps, and
> vice versa: once a tail call re-enters an extended subprogram, its
> tail_call_cnt resets on every execution and the loop never terminates.
> 
> But is_extended is a plain boolean, while one target prog can carry
> several freplace links at the same time, one on its entry and one on a
> global subprogram.  __bpf_trampoline_unlink_prog() cleared is_extended
> whenever *any* freplace link detached, so detaching one of two links
> re-armed the unbounded loop through the remaining one.

A prog may have multiple global subprogs. And each of the subprogs can
be attached with freplace prog. When all the subprogs are attached with
freplace progs then detach one of the freplace prog, the *is_extended*
becomes *false*, which relaxes the restriction between tailcall and
freplace introduced by the commit d6083f040d5d ("bpf: Prevent tailcall
infinite loop caused by freplace").

> 
> Replace the is_extended boolean with a count of the freplace links
> attached to each target prog, so the target stays extended until its
> last link detaches.  Also rename bpf_freplace_check_tgt_prog() to
> bpf_freplace_link_tgt_prog(), as the helper has never been a pure
> check: it reserves the target prog on success.
> 
> Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> 

[...]

> @@ -933,7 +933,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
>  		/* Cannot attach extension if fentry/fexit are in use. */
>  		if (cnt)
>  			return -EBUSY;
> -		err = bpf_freplace_check_tgt_prog(tgt_prog);
> +		err = bpf_freplace_link_tgt_prog(tgt_prog);
>  		if (err)
>  			return err;
>  		tr->extension_prog = node->link->prog;

                return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
                                          BPF_MOD_JUMP, NULL,
                                          node->link->prog->bpf_func);


I think there are existing issues here: if bpf_arch_text_poke() returns
error, the tr->extension_prog and aux->freplace_link_cnt should be
rollbacked.

Thanks,
Leon

> @@ -979,7 +979,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_node *node,
>  					 tr->extension_prog->bpf_func, NULL);
>  		tr->extension_prog = NULL;
>  		guard(mutex)(&tgt_prog->aux->ext_mutex);
> -		tgt_prog->aux->is_extended = false;
> +		tgt_prog->aux->freplace_link_cnt--;
>  		return err;
>  	}
>  	bpf_trampoline_remove_prog(tr, node);


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links
  2026-09-24  2:37 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links chenyuan_fl
@ 2026-09-24  7:06   ` Leon Hwang
  0 siblings, 0 replies; 13+ messages in thread
From: Leon Hwang @ 2026-09-24  7:06 UTC (permalink / raw)
  To: chenyuan_fl, alexei.starovoitov, ast, leon.hwang
  Cc: bpf, daniel, andrii, eddyz87, memxor, martin.lau, yonghong.song,
	john.fastabend, song, ihor.solodrai, Yuan Chen

On 24/9/26 10:37, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> Extend tc_bpf2bpf with two freplace links, one on entry_tc and one on
> subprog_tc, and detach the one on the entry: while subprog_tc is still
> extended, updating entry_tc into a prog_array map must keep failing
> with -EBUSY, and succeed again once the last link detaches.  The test
> asserts the rejection instead of running the prog, as the update
> succeeds and the prog loops unbounded on an unfixed kernel.
> 
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
>  .../selftests/bpf/prog_tests/tailcalls.c      | 74 +++++++++++++++++++
>  .../bpf/progs/tailcall_freplace_multi.c       | 27 +++++++
>  2 files changed, 101 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> index c5c9d6c359bb..aefb46778307 100644
> --- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> +++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
> @@ -6,6 +6,7 @@
>  #include "tailcall_bpf2bpf_hierarchy2.skel.h"
>  #include "tailcall_bpf2bpf_hierarchy3.skel.h"
>  #include "tailcall_freplace.skel.h"
> +#include "tailcall_freplace_multi.skel.h"
>  #include "tc_bpf2bpf.skel.h"
>  #include "tailcall_fail.skel.h"
>  #include "tailcall_cgrp_storage_owner.skel.h"
> @@ -1655,6 +1656,77 @@ static void test_tailcall_bpf2bpf_freplace(void)
>  	tc_bpf2bpf__destroy(tc_skel);
>  }
>  
> +static void test_tailcall_freplace_multi(void)
> +{
> +	struct tailcall_freplace_multi *freplace_skel = NULL;
> +	struct bpf_link *link_subprog = NULL, *link_entry = NULL;
> +	struct tc_bpf2bpf *tc_skel = NULL;
> +	int tc_prog_fd, map_fd, key = 0, err;


Pls keep the above lines with inverted Christmas tree style.

And, drop '= NULL' for tc_skel, because tc_skel is the first variable to
be initialized.

Thanks,
Leon

> +
> +	tc_skel = tc_bpf2bpf__open_and_load();
> +	if (!ASSERT_OK_PTR(tc_skel, "tc_bpf2bpf__open_and_load"))
> +		return;
> [...]


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  2:37 [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
  2026-09-24  2:37 ` [PATCH bpf-next v2 1/2] " chenyuan_fl
  2026-09-24  2:37 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links chenyuan_fl
@ 2026-09-24  8:42 ` Jiri Olsa
  2026-09-24  9:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 13+ messages in thread
From: Jiri Olsa @ 2026-09-24  8:42 UTC (permalink / raw)
  To: chenyuan_fl
  Cc: alexei.starovoitov, ast, leon.hwang, bpf, daniel, andrii, eddyz87,
	memxor, martin.lau, yonghong.song, john.fastabend, song,
	ihor.solodrai, Yuan Chen

On Thu, Sep 24, 2026 at 10:37:35AM +0800, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> is_extended is a plain boolean, but one target prog can carry several
> freplace links at the same time, one on its entry and one on a global
> subprogram.  __bpf_trampoline_unlink_prog() cleared it whenever *any*
> of them detached, so with two links on one target, detaching one of
> them re-armed the unbounded tail call loop closed by commit
> d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace"):
> a single BPF_PROG_TEST_RUN on the tail-called target then panics the
> kernel, reproduced on both bpf-next and master.
> 
> Patch 1 replaces the boolean with a count of the freplace links
> attached to each target prog, so the target stays extended until its
> last link detaches.  Patch 2 adds a selftest covering the sequence.
> 
> Changes since v1:
> 
> - freplace_link_cnt is u16 instead of u64, per Alexei's review: it is
>   bounded by BPF_MAX_SUBPROGS, which counts the entry function too, so
>   up to 256 links, one past u8, and it sits in the padding next to
>   stack_arg_sp_adjust, so bpf_prog_aux does not grow
> - dropped the separate is_extended boolean, deriving the extended state
>   from the count itself
> - renamed bpf_freplace_check_tgt_prog() to bpf_freplace_link_tgt_prog(),
>   it reserves the target on success
> - dropped the WARN_ON_ONCE() on detach, per Leon's review: the count is
>   paired by the link lifetime and the sibling prog_array_member_cnt
>   decrement is not guarded either
> 
> Yuan Chen (2):
>   bpf: Keep target extended until its last freplace link detaches
>   selftests/bpf: Verify is_extended with multiple freplace links

Acked-by: Jiri Olsa <jolsa@kernel.org>

jirka

> 
>  include/linux/bpf.h                           |  4 +-
>  kernel/bpf/arraymap.c                         |  2 +-
>  kernel/bpf/trampoline.c                       |  8 +-
>  .../selftests/bpf/prog_tests/tailcalls.c      | 74 +++++++++++++++++++
>  .../bpf/progs/tailcall_freplace_multi.c       | 27 +++++++
>  5 files changed, 108 insertions(+), 7 deletions(-)
>  create mode 100644 tools/testing/selftests/bpf/progs/tailcall_freplace_multi.c
> 
> -- 
> 2.54.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  2:37 [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
                   ` (2 preceding siblings ...)
  2026-09-24  8:42 ` [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches Jiri Olsa
@ 2026-09-24  9:00 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 13+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-24  9:00 UTC (permalink / raw)
  To: chenyuan
  Cc: alexei.starovoitov, ast, leon.hwang, bpf, daniel, andrii, eddyz87,
	memxor, martin.lau, yonghong.song, john.fastabend, song,
	ihor.solodrai, chenyuan

Hello:

This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:

On Thu, 24 Sep 2026 10:37:35 +0800 you wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> is_extended is a plain boolean, but one target prog can carry several
> freplace links at the same time, one on its entry and one on a global
> subprogram.  __bpf_trampoline_unlink_prog() cleared it whenever *any*
> of them detached, so with two links on one target, detaching one of
> them re-armed the unbounded tail call loop closed by commit
> d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace"):
> a single BPF_PROG_TEST_RUN on the tail-called target then panics the
> kernel, reproduced on both bpf-next and master.
> 
> [...]

Here is the summary with links:
  - [bpf-next,v2,1/2] bpf: Keep target extended until its last freplace link detaches
    https://git.kernel.org/bpf/bpf-next/c/c43c348a8446
  - [bpf-next,v2,2/2] selftests/bpf: Verify is_extended with multiple freplace links
    https://git.kernel.org/bpf/bpf-next/c/01d37848bf5b

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next v2 1/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  7:06   ` Leon Hwang
@ 2026-09-24  9:48     ` Jiri Olsa
  2026-09-24  9:58     ` chenyuan
  1 sibling, 0 replies; 13+ messages in thread
From: Jiri Olsa @ 2026-09-24  9:48 UTC (permalink / raw)
  To: Leon Hwang
  Cc: chenyuan_fl, alexei.starovoitov, ast, bpf, daniel, andrii,
	eddyz87, memxor, martin.lau, yonghong.song, john.fastabend, song,
	ihor.solodrai, Yuan Chen

On Thu, Sep 24, 2026 at 03:06:16PM +0800, Leon Hwang wrote:
> On 24/9/26 10:37, chenyuan_fl@163.com wrote:
> > From: Yuan Chen <chenyuan@kylinos.cn>
> > 
> > The is_extended / prog_array_member_cnt protocol introduced by commit
> > d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
> > keeps a prog extended by a freplace program out of prog_array maps, and
> > vice versa: once a tail call re-enters an extended subprogram, its
> > tail_call_cnt resets on every execution and the loop never terminates.
> > 
> > But is_extended is a plain boolean, while one target prog can carry
> > several freplace links at the same time, one on its entry and one on a
> > global subprogram.  __bpf_trampoline_unlink_prog() cleared is_extended
> > whenever *any* freplace link detached, so detaching one of two links
> > re-armed the unbounded loop through the remaining one.
> 
> A prog may have multiple global subprogs. And each of the subprogs can
> be attached with freplace prog. When all the subprogs are attached with
> freplace progs then detach one of the freplace prog, the *is_extended*
> becomes *false*, which relaxes the restriction between tailcall and
> freplace introduced by the commit d6083f040d5d ("bpf: Prevent tailcall
> infinite loop caused by freplace").
> 
> > 
> > Replace the is_extended boolean with a count of the freplace links
> > attached to each target prog, so the target stays extended until its
> > last link detaches.  Also rename bpf_freplace_check_tgt_prog() to
> > bpf_freplace_link_tgt_prog(), as the helper has never been a pure
> > check: it reserves the target prog on success.
> > 
> > Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
> > Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> > 
> 
> [...]
> 
> > @@ -933,7 +933,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
> >  		/* Cannot attach extension if fentry/fexit are in use. */
> >  		if (cnt)
> >  			return -EBUSY;
> > -		err = bpf_freplace_check_tgt_prog(tgt_prog);
> > +		err = bpf_freplace_link_tgt_prog(tgt_prog);
> >  		if (err)
> >  			return err;
> >  		tr->extension_prog = node->link->prog;
> 
>                 return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
>                                           BPF_MOD_JUMP, NULL,
>                                           node->link->prog->bpf_func);
> 
> 
> I think there are existing issues here: if bpf_arch_text_poke() returns
> error, the tr->extension_prog and aux->freplace_link_cnt should be
> rollbacked.

+1, let's set tr->extension_prog and tgt_prog->aux->freplace_link_cnt++
only if bpf_arch_text_poke succeeds

jirka

> 
> Thanks,
> Leon
> 
> > @@ -979,7 +979,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_node *node,
> >  					 tr->extension_prog->bpf_func, NULL);
> >  		tr->extension_prog = NULL;
> >  		guard(mutex)(&tgt_prog->aux->ext_mutex);
> > -		tgt_prog->aux->is_extended = false;
> > +		tgt_prog->aux->freplace_link_cnt--;
> >  		return err;
> >  	}
> >  	bpf_trampoline_remove_prog(tr, node);
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re:Re: [PATCH bpf-next v2 1/2] bpf: Keep target extended until its last freplace link detaches
  2026-09-24  7:06   ` Leon Hwang
  2026-09-24  9:48     ` Jiri Olsa
@ 2026-09-24  9:58     ` chenyuan
  2026-09-25  4:35       ` [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails chenyuan_fl
  1 sibling, 1 reply; 13+ messages in thread
From: chenyuan @ 2026-09-24  9:58 UTC (permalink / raw)
  To: Leon Hwang
  Cc: alexei.starovoitov, ast, bpf, daniel, andrii, eddyz87, memxor,
	martin.lau, yonghong.song, john.fastabend, song, ihor.solodrai,
	Yuan Chen


Thanks for the review. This is a pre-existing bug in the link path, not introduced by this patch. I'll send a
separate fix for the rollback later. This patch stays focused on the is_extended counting.













At 2026-09-24 15:06:16, "Leon Hwang" <leon.hwang@linux.dev> wrote:
>On 24/9/26 10:37, chenyuan_fl@163.com wrote:
>> From: Yuan Chen <chenyuan@kylinos.cn>
>> 
>> The is_extended / prog_array_member_cnt protocol introduced by commit
>> d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
>> keeps a prog extended by a freplace program out of prog_array maps, and
>> vice versa: once a tail call re-enters an extended subprogram, its
>> tail_call_cnt resets on every execution and the loop never terminates.
>> 
>> But is_extended is a plain boolean, while one target prog can carry
>> several freplace links at the same time, one on its entry and one on a
>> global subprogram.  __bpf_trampoline_unlink_prog() cleared is_extended
>> whenever *any* freplace link detached, so detaching one of two links
>> re-armed the unbounded loop through the remaining one.
>
>A prog may have multiple global subprogs. And each of the subprogs can
>be attached with freplace prog. When all the subprogs are attached with
>freplace progs then detach one of the freplace prog, the *is_extended*
>becomes *false*, which relaxes the restriction between tailcall and
>freplace introduced by the commit d6083f040d5d ("bpf: Prevent tailcall
>infinite loop caused by freplace").
>
>> 
>> Replace the is_extended boolean with a count of the freplace links
>> attached to each target prog, so the target stays extended until its
>> last link detaches.  Also rename bpf_freplace_check_tgt_prog() to
>> bpf_freplace_link_tgt_prog(), as the helper has never been a pure
>> check: it reserves the target prog on success.
>> 
>> Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
>> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
>> 
>
>[...]
>
>> @@ -933,7 +933,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
>>  		/* Cannot attach extension if fentry/fexit are in use. */
>>  		if (cnt)
>>  			return -EBUSY;
>> -		err = bpf_freplace_check_tgt_prog(tgt_prog);
>> +		err = bpf_freplace_link_tgt_prog(tgt_prog);
>>  		if (err)
>>  			return err;
>>  		tr->extension_prog = node->link->prog;
>
>                return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
>                                          BPF_MOD_JUMP, NULL,
>                                          node->link->prog->bpf_func);
>
>
>I think there are existing issues here: if bpf_arch_text_poke() returns
>error, the tr->extension_prog and aux->freplace_link_cnt should be
>rollbacked.
>
>Thanks,
>Leon
>
>> @@ -979,7 +979,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_node *node,
>>  					 tr->extension_prog->bpf_func, NULL);
>>  		tr->extension_prog = NULL;
>>  		guard(mutex)(&tgt_prog->aux->ext_mutex);
>> -		tgt_prog->aux->is_extended = false;
>> +		tgt_prog->aux->freplace_link_cnt--;
>>  		return err;
>>  	}
>>  	bpf_trampoline_remove_prog(tr, node);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails
  2026-09-24  9:58     ` chenyuan
@ 2026-09-25  4:35       ` chenyuan_fl
  2026-09-25  5:18         ` bot+bpf-ci
  2026-09-25  6:05         ` Leon Hwang
  0 siblings, 2 replies; 13+ messages in thread
From: chenyuan_fl @ 2026-09-25  4:35 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, jolsa, leon.hwang,
	linux-kernel, Yuan Chen

From: Yuan Chen <chenyuan@kylinos.cn>

A freplace attach claims the target prog by bumping
tgt_prog->aux->freplace_link_cnt and setting tr->extension_prog.
bpf_arch_text_poke() then makes the extension take effect.  If the
poke fails, the claims are never released: the attach unwinds
through bpf_link_cleanup(), which clears link->prog, so
bpf_trampoline_unlink_prog() never runs.

Drop the link count under ext_mutex on the error path, and set
tr->extension_prog only after the poke succeeded.  The count is
still bumped before the poke: it blocks prog_array updates while
the entry is patched.

Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
Suggested-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
 kernel/bpf/trampoline.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index da85bd580ef0..bf4ab0ac264e 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -973,10 +973,17 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
 		err = bpf_freplace_link_tgt_prog(tgt_prog);
 		if (err)
 			return err;
+		err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
+					 BPF_MOD_JUMP, NULL,
+					 node->link->prog->bpf_func);
+		if (err) {
+			/* Undo the claim from bpf_freplace_link_tgt_prog(). */
+			guard(mutex)(&tgt_prog->aux->ext_mutex);
+			tgt_prog->aux->freplace_link_cnt--;
+			return err;
+		}
 		tr->extension_prog = node->link->prog;
-		return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
-					  BPF_MOD_JUMP, NULL,
-					  node->link->prog->bpf_func);
+		return 0;
 	}
 	err = bpf_trampoline_add_prog(tr, node, cnt);
 	if (err)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails
  2026-09-25  4:35       ` [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails chenyuan_fl
@ 2026-09-25  5:18         ` bot+bpf-ci
  2026-09-25  6:05         ` Leon Hwang
  1 sibling, 0 replies; 13+ messages in thread
From: bot+bpf-ci @ 2026-09-25  5:18 UTC (permalink / raw)
  To: chenyuan_fl, bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, jolsa, leon.hwang,
	linux-kernel, chenyuan, ast, andrii, daniel, martin.lau, eddyz87,
	yonghong.song, mason, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1617 bytes --]

> bpf: Roll back freplace link state when bpf_arch_text_poke() fails
>
> A freplace attach claims the target prog by bumping
> tgt_prog->aux->freplace_link_cnt and setting tr->extension_prog.
> bpf_arch_text_poke() then makes the extension take effect.  If the
> poke fails, the claims are never released: the attach unwinds
> through bpf_link_cleanup(), which clears link->prog, so
> bpf_trampoline_unlink_prog() never runs.
>
> Drop the link count under ext_mutex on the error path, and set
> tr->extension_prog only after the poke succeeded.  The count is
> still bumped before the poke: it blocks prog_array updates while
> the entry is patched.
>
> Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
> Suggested-by: Leon Hwang <leon.hwang@linux.dev>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>

The Fixes: tag points to d6083f040d5d, but should this be commit
c43c348a8446 instead?

Looking at the commit history, c43c348a8446 ("bpf: Keep target extended
until its last freplace link detaches") introduced the freplace_link_cnt
field and the bpf_freplace_link_tgt_prog() function that increments it.

The bug being fixed here is that when bpf_freplace_link_tgt_prog() succeeds
but bpf_arch_text_poke() subsequently fails, the incremented count is not
rolled back. This exact code pattern was introduced by c43c348a8446, not
d6083f040d5d.


---
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/36096074687

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails
  2026-09-25  4:35       ` [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails chenyuan_fl
  2026-09-25  5:18         ` bot+bpf-ci
@ 2026-09-25  6:05         ` Leon Hwang
  2026-09-28  9:08           ` chenyuan
  1 sibling, 1 reply; 13+ messages in thread
From: Leon Hwang @ 2026-09-25  6:05 UTC (permalink / raw)
  To: chenyuan_fl, bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, jolsa, linux-kernel,
	Yuan Chen

On 25/9/26 12:35, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
> 
> A freplace attach claims the target prog by bumping
> tgt_prog->aux->freplace_link_cnt and setting tr->extension_prog.
> bpf_arch_text_poke() then makes the extension take effect.  If the
> poke fails, the claims are never released: the attach unwinds
> through bpf_link_cleanup(), which clears link->prog, so
> bpf_trampoline_unlink_prog() never runs.
> 
> Drop the link count under ext_mutex on the error path, and set
> tr->extension_prog only after the poke succeeded.  The count is
> still bumped before the poke: it blocks prog_array updates while
> the entry is patched.
> 
> Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")

Your commit msg also says the issue about tr->extension_prog.

An extra Fixes tag for tr->extension_prog should be added.

Fixes: be8704ff07d2 ("bpf: Introduce dynamic program extensions")

The changes below lgtm:

Acked-by: Leon Hwang <leon.hwang@linux.dev>

Thanks,
Leon

> Suggested-by: Leon Hwang <leon.hwang@linux.dev>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
>  kernel/bpf/trampoline.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> index da85bd580ef0..bf4ab0ac264e 100644
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c
> @@ -973,10 +973,17 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
>  		err = bpf_freplace_link_tgt_prog(tgt_prog);
>  		if (err)
>  			return err;
> +		err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
> +					 BPF_MOD_JUMP, NULL,
> +					 node->link->prog->bpf_func);
> +		if (err) {
> +			/* Undo the claim from bpf_freplace_link_tgt_prog(). */
> +			guard(mutex)(&tgt_prog->aux->ext_mutex);
> +			tgt_prog->aux->freplace_link_cnt--;
> +			return err;
> +		}
>  		tr->extension_prog = node->link->prog;
> -		return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
> -					  BPF_MOD_JUMP, NULL,
> -					  node->link->prog->bpf_func);
> +		return 0;
>  	}
>  	err = bpf_trampoline_add_prog(tr, node, cnt);
>  	if (err)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re:Re: [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails
  2026-09-25  6:05         ` Leon Hwang
@ 2026-09-28  9:08           ` chenyuan
  0 siblings, 0 replies; 13+ messages in thread
From: chenyuan @ 2026-09-28  9:08 UTC (permalink / raw)
  To: Leon Hwang
  Cc: bpf, ast, daniel, andrii, eddyz87, memxor, jolsa, linux-kernel,
	Yuan Chen


Thanks for the review. v2 adds the be8704ff07d2 Fixes tag and collects your Ack.









At 2026-09-25 14:05:59, "Leon Hwang" <leon.hwang@linux.dev> wrote:
>On 25/9/26 12:35, chenyuan_fl@163.com wrote:
>> From: Yuan Chen <chenyuan@kylinos.cn>
>> 
>> A freplace attach claims the target prog by bumping
>> tgt_prog->aux->freplace_link_cnt and setting tr->extension_prog.
>> bpf_arch_text_poke() then makes the extension take effect.  If the
>> poke fails, the claims are never released: the attach unwinds
>> through bpf_link_cleanup(), which clears link->prog, so
>> bpf_trampoline_unlink_prog() never runs.
>> 
>> Drop the link count under ext_mutex on the error path, and set
>> tr->extension_prog only after the poke succeeded.  The count is
>> still bumped before the poke: it blocks prog_array updates while
>> the entry is patched.
>> 
>> Fixes: d6083f040d5d ("bpf: Prevent tailcall infinite loop caused by freplace")
>
>Your commit msg also says the issue about tr->extension_prog.
>
>An extra Fixes tag for tr->extension_prog should be added.
>
>Fixes: be8704ff07d2 ("bpf: Introduce dynamic program extensions")
>
>The changes below lgtm:
>
>Acked-by: Leon Hwang <leon.hwang@linux.dev>
>
>Thanks,
>Leon
>
>> Suggested-by: Leon Hwang <leon.hwang@linux.dev>
>> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
>> ---
>>  kernel/bpf/trampoline.c | 13 ++++++++++---
>>  1 file changed, 10 insertions(+), 3 deletions(-)
>> 
>> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
>> index da85bd580ef0..bf4ab0ac264e 100644
>> --- a/kernel/bpf/trampoline.c
>> +++ b/kernel/bpf/trampoline.c
>> @@ -973,10 +973,17 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
>>  		err = bpf_freplace_link_tgt_prog(tgt_prog);
>>  		if (err)
>>  			return err;
>> +		err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
>> +					 BPF_MOD_JUMP, NULL,
>> +					 node->link->prog->bpf_func);
>> +		if (err) {
>> +			/* Undo the claim from bpf_freplace_link_tgt_prog(). */
>> +			guard(mutex)(&tgt_prog->aux->ext_mutex);
>> +			tgt_prog->aux->freplace_link_cnt--;
>> +			return err;
>> +		}
>>  		tr->extension_prog = node->link->prog;
>> -		return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
>> -					  BPF_MOD_JUMP, NULL,
>> -					  node->link->prog->bpf_func);
>> +		return 0;
>>  	}
>>  	err = bpf_trampoline_add_prog(tr, node, cnt);
>>  	if (err)

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-09-28  9:09 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-24  2:37 [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
2026-09-24  2:37 ` [PATCH bpf-next v2 1/2] " chenyuan_fl
2026-09-24  7:06   ` Leon Hwang
2026-09-24  9:48     ` Jiri Olsa
2026-09-24  9:58     ` chenyuan
2026-09-25  4:35       ` [PATCH bpf-next] bpf: Roll back freplace link state when bpf_arch_text_poke() fails chenyuan_fl
2026-09-25  5:18         ` bot+bpf-ci
2026-09-25  6:05         ` Leon Hwang
2026-09-28  9:08           ` chenyuan
2026-09-24  2:37 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify is_extended with multiple freplace links chenyuan_fl
2026-09-24  7:06   ` Leon Hwang
2026-09-24  8:42 ` [PATCH bpf-next v2 0/2] bpf: Keep target extended until its last freplace link detaches Jiri Olsa
2026-09-24  9:00 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox