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>,
"Jose E . Marchesi" <jose.marchesi@oracle.com>,
kernel-team@fb.com, Martin KaFai Lau <martin.lau@kernel.org>
Subject: [PATCH bpf-next v4 20/25] selftests/bpf: Add BTF fixup for __naked subprog parameter names
Date: Tue, 12 May 2026 21:51:38 -0700 [thread overview]
Message-ID: <20260513045138.2398886-1-yonghong.song@linux.dev> (raw)
In-Reply-To: <20260513044949.2382019-1-yonghong.song@linux.dev>
When __naked subprogs are used in verifier tests, clang drops
parameter names from their BTF FUNC_PROTO entries. This prevents
the verifier from resolving stack argument slots by name.
Add a __btf_func_path(path) annotation that points to a separate
BTF file containing properly-named FUNC entries. The test_loader
matches FUNC entries by name, detects anonymous parameters, and
replaces the FUNC_PROTO with a new one that carries parameter
names from the custom file while preserving the original type IDs.
The custom BTF file also serves as btf_custom_path for kfunc
resolution when no separate btf_custom_path is specified.
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
---
tools/testing/selftests/bpf/progs/bpf_misc.h | 1 +
tools/testing/selftests/bpf/test_loader.c | 136 ++++++++++++++++++-
2 files changed, 136 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index a0d7b15a24b1..9eeb5b0b63d6 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -152,6 +152,7 @@
#define __auxiliary __test_tag("test_auxiliary")
#define __auxiliary_unpriv __test_tag("test_auxiliary_unpriv")
#define __btf_path(path) __test_tag("test_btf_path=" path)
+#define __btf_func_path(path) __test_tag("test_btf_func_path=" path)
#define __arch(arch) __test_tag("test_arch=" arch)
#define __arch_x86_64 __arch("X86_64")
#define __arch_arm64 __arch("ARM64")
diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index ee637809a1d4..abdb9e6e3713 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -63,6 +63,7 @@ struct test_spec {
struct test_subspec priv;
struct test_subspec unpriv;
const char *btf_custom_path;
+ const char *btf_custom_func_path;
int log_level;
int prog_flags;
int mode_mask;
@@ -590,6 +591,8 @@ static int parse_test_spec(struct test_loader *tester,
jit_on_next_line = true;
} else if ((val = str_has_pfx(s, "test_btf_path="))) {
spec->btf_custom_path = val;
+ } else if ((val = str_has_pfx(s, "test_btf_func_path="))) {
+ spec->btf_custom_func_path = val;
} else if ((val = str_has_pfx(s, "test_caps_unpriv="))) {
err = parse_caps(val, &spec->unpriv.caps, "test caps");
if (err)
@@ -1175,6 +1178,123 @@ static int get_stream(int stream_id, int prog_fd, char *text, size_t text_sz)
return ret;
}
+/*
+ * Fix up the program's BTF using BTF from a separate file.
+ *
+ * For __naked subprogs, clang drops parameter names from BTF. Find FUNC
+ * entries with anonymous parameters and replace their FUNC_PROTO with the
+ * properly-named version from the custom file.
+ */
+static int fixup_btf_from_path(struct bpf_object *obj, const char *path)
+{
+ struct btf *prog_btf, *custom_btf;
+ __u32 i, j, cnt, custom_cnt;
+ int err = 0;
+
+ prog_btf = bpf_object__btf(obj);
+ if (!prog_btf)
+ return 0;
+
+ custom_btf = btf__parse(path, NULL);
+ if (!ASSERT_OK_PTR(custom_btf, "parse_custom_btf"))
+ return -EINVAL;
+
+ cnt = btf__type_cnt(prog_btf);
+ custom_cnt = btf__type_cnt(custom_btf);
+
+ /* Fix up FUNC entries with anonymous params.
+ * Save all data from prog_btf BEFORE calling btf__add_*,
+ * since those calls may reallocate the BTF data buffer
+ * and invalidate any pointers obtained from btf__type_by_id.
+ */
+ for (i = 1; i < cnt; i++) {
+ const struct btf_type *t = btf__type_by_id(prog_btf, i);
+ const struct btf_type *fp, *custom_t, *custom_fp;
+ const struct btf_param *params, *custom_params;
+ __u32 ret_type_id, vlen;
+ __u32 *prog_param_types = NULL;
+ const char *name;
+ int new_proto_id;
+
+ if (!btf_is_func(t))
+ continue;
+
+ fp = btf__type_by_id(prog_btf, t->type);
+ if (!fp || !btf_is_func_proto(fp) || btf_vlen(fp) == 0)
+ continue;
+
+ /* Check if any param is anonymous */
+ params = btf_params(fp);
+ if (params[0].name_off != 0)
+ continue;
+
+ /* Find matching FUNC by name in custom BTF */
+ name = btf__name_by_offset(prog_btf, t->name_off);
+ if (!name)
+ continue;
+
+ for (j = 1; j < custom_cnt; j++) {
+ const char *cname;
+
+ custom_t = btf__type_by_id(custom_btf, j);
+ if (!btf_is_func(custom_t))
+ continue;
+ cname = btf__name_by_offset(custom_btf, custom_t->name_off);
+ if (cname && strcmp(name, cname) == 0)
+ break;
+ }
+ if (j >= custom_cnt)
+ continue;
+
+ custom_fp = btf__type_by_id(custom_btf, custom_t->type);
+ if (!custom_fp || !btf_is_func_proto(custom_fp))
+ continue;
+
+ vlen = btf_vlen(fp);
+ if (vlen != btf_vlen(custom_fp))
+ continue;
+
+ /* Save data before btf__add_* calls invalidate pointers */
+ ret_type_id = fp->type;
+ prog_param_types = malloc(vlen * sizeof(*prog_param_types));
+ if (!prog_param_types) {
+ err = -ENOMEM;
+ break;
+ }
+ for (j = 0; j < vlen; j++)
+ prog_param_types[j] = params[j].type;
+
+ /* Add a new FUNC_PROTO: param names from custom, types from prog */
+ new_proto_id = btf__add_func_proto(prog_btf, ret_type_id);
+ if (new_proto_id < 0) {
+ err = new_proto_id;
+ free(prog_param_types);
+ break;
+ }
+
+ custom_params = btf_params(custom_fp);
+ for (j = 0; j < vlen; j++) {
+ const char *pname;
+
+ pname = btf__name_by_offset(custom_btf, custom_params[j].name_off);
+ err = btf__add_func_param(prog_btf, pname ?: "", prog_param_types[j]);
+ if (err)
+ break;
+ }
+ free(prog_param_types);
+ if (err)
+ break;
+
+ /* Update the FUNC to point to the new FUNC_PROTO (re-fetch
+ * since btf__add_* may have reallocated the data buffer).
+ */
+ ((struct btf_type *)btf__type_by_id(prog_btf, i))->type = new_proto_id;
+ }
+
+ btf__free(custom_btf);
+ return err;
+}
+
/* this function is forced noinline and has short generic name to look better
* in test_progs output (in case of a failure)
*/
@@ -1231,13 +1351,27 @@ void run_subtest(struct test_loader *tester,
}
}
- /* Implicitly reset to NULL if next test case doesn't specify */
+ /* Implicitly reset to NULL if next test case doesn't specify.
+ * btf_custom_func_path also serves as btf_custom_path for kfunc resolution.
+ */
open_opts->btf_custom_path = spec->btf_custom_path;
+ if (!open_opts->btf_custom_path)
+ open_opts->btf_custom_path = spec->btf_custom_func_path;
tobj = bpf_object__open_mem(obj_bytes, obj_byte_cnt, open_opts);
if (!ASSERT_OK_PTR(tobj, "obj_open_mem")) /* shouldn't happen */
goto subtest_cleanup;
+ /* Fix up __naked subprog BTF using a separate file with named params */
+ if (spec->btf_custom_func_path) {
+ err = fixup_btf_from_path(tobj, spec->btf_custom_func_path);
+ if (err) {
+ PRINT_FAIL("failed to fixup BTF from %s: %d\n",
+ spec->btf_custom_func_path, err);
+ goto tobj_cleanup;
+ }
+ }
+
i = 0;
bpf_object__for_each_program(tprog_iter, tobj) {
spec_iter = &specs[i++];
--
2.53.0-Meta
next prev parent reply other threads:[~2026-05-13 4:51 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-13 4:49 [PATCH bpf-next v4 00/25] bpf: Support stack arguments for BPF functions and kfuncs Yonghong Song
2026-05-13 4:49 ` [PATCH bpf-next v4 01/25] bpf: Convert bpf_get_spilled_reg macro to static inline function Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 02/25] bpf: Remove copy_register_state wrapper function Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 03/25] bpf: Add helper functions for r11-based stack argument insns Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 04/25] bpf: Set sub->arg_cnt earlier in btf_prepare_func_args() Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 05/25] bpf: Support stack arguments for bpf functions Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 06/25] bpf: Refactor jmp history to use dedicated spi/frame fields Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 07/25] bpf: Add precision marking and backtracking for stack argument slots Yonghong Song
2026-05-13 5:44 ` bot+bpf-ci
2026-05-13 4:50 ` [PATCH bpf-next v4 08/25] bpf: Refactor record_call_access() to extract per-arg logic Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 09/25] bpf: Use arg_is_fp() in has_fp_args() Yonghong Song
2026-05-13 4:50 ` [PATCH bpf-next v4 10/25] bpf: Extend liveness analysis to track stack argument slots Yonghong Song
2026-05-13 5:44 ` bot+bpf-ci
2026-05-13 4:50 ` [PATCH bpf-next v4 11/25] bpf: Reject stack arguments in non-JITed programs Yonghong Song
2026-05-13 5:33 ` bot+bpf-ci
2026-05-13 4:50 ` [PATCH bpf-next v4 12/25] bpf: Prepare architecture JIT support for stack arguments Yonghong Song
2026-05-13 5:33 ` bot+bpf-ci
2026-05-13 4:50 ` [PATCH bpf-next v4 13/25] bpf: Enable r11 based insns Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 14/25] bpf: Support stack arguments for kfunc calls Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 15/25] bpf: Reject stack arguments if tail call reachable Yonghong Song
2026-05-13 5:33 ` bot+bpf-ci
2026-05-13 4:51 ` [PATCH bpf-next v4 16/25] bpf: Disable private stack for x86_64 if stack arguments used Yonghong Song
2026-05-13 5:33 ` bot+bpf-ci
2026-05-13 4:51 ` [PATCH bpf-next v4 17/25] bpf,x86: Implement JIT support for stack arguments Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 18/25] selftests/bpf: Add tests for BPF function " Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 19/25] selftests/bpf: Add tests for stack argument validation Yonghong Song
2026-05-13 4:51 ` Yonghong Song [this message]
2026-05-13 4:51 ` [PATCH bpf-next v4 21/25] selftests/bpf: Add verifier " Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 22/25] selftests/bpf: Add precision backtracking test for stack arguments Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 23/25] bpf, arm64: Map BPF_REG_0 to x8 instead of x7 Yonghong Song
2026-05-13 4:51 ` [PATCH bpf-next v4 24/25] bpf, arm64: Add JIT support for stack arguments Yonghong Song
2026-05-13 4:52 ` [PATCH bpf-next v4 25/25] selftests/bpf: Enable stack argument tests for arm64 Yonghong Song
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=20260513045138.2398886-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=jose.marchesi@oracle.com \
--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