From: chenyuan_fl@163.com
To: bpf@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
Alexei Starovoitov <alexei.starovoitov@gmail.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Yuan Chen <chenyuan@kylinos.cn>
Subject: [PATCH bpf-next 2/2] selftests/bpf: Verify is_extended with multiple freplace links
Date: Wed, 23 Sep 2026 17:06:35 +0800 [thread overview]
Message-ID: <20260923090635.368488-3-chenyuan_fl@163.com> (raw)
In-Reply-To: <20260923090635.368488-1-chenyuan_fl@163.com>
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
prev parent reply other threads:[~2026-09-23 9:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 9:06 [PATCH bpf-next 0/2] bpf: Keep target extended until its last freplace link detaches chenyuan_fl
2026-09-23 9:06 ` [PATCH bpf-next 1/2] " chenyuan_fl
2026-09-23 9:54 ` Leon Hwang
2026-09-23 10:02 ` bot+bpf-ci
2026-09-23 22:14 ` Alexei Starovoitov
2026-09-23 9:06 ` chenyuan_fl [this message]
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=20260923090635.368488-3-chenyuan_fl@163.com \
--to=chenyuan_fl@163.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=chenyuan@kylinos.cn \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/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
all inboxes | Powered by JetHome®