| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/06/24 01:18 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies userspace tools and selftests (tools/include/linux/btf_ids.h and tools/testing/selftests/bpf/). It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
} |
| 1/1 | 2026/06/24 01:18 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit e4fe53b91a323149377b3515d8cb851211065ac7\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jun 24 01:18:07 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/tools/include/linux/btf_ids.h b/tools/include/linux/btf_ids.h\nindex 72ea363d434db0..4fe5c5f1558ca9 100644\n--- a/tools/include/linux/btf_ids.h\n+++ b/tools/include/linux/btf_ids.h\n@@ -10,6 +10,9 @@ struct btf_id_set {\n \tu32 ids[];\n };\n \n+/* This flag implies BTF_SET8 holds kfunc(s) */\n+#define BTF_SET8_KFUNCS\t\t(1 \u003c\u003c 0)\n+\n struct btf_id_set8 {\n \tu32 cnt;\n \tu32 flags;\n@@ -22,6 +25,7 @@ struct btf_id_set8 {\n #ifdef CONFIG_DEBUG_INFO_BTF\n \n #include \u003clinux/compiler.h\u003e /* for __PASTE */\n+#include \u003clinux/stringify.h\u003e\n \n /*\n * Following macros help to define lists of BTF IDs placed\n@@ -35,7 +39,7 @@ struct btf_id_set8 {\n \n #define BTF_IDS_SECTION \".BTF_ids\"\n \n-#define ____BTF_ID(symbol)\t\t\t\t\\\n+#define ____BTF_ID(symbol, word)\t\t\t\\\n asm(\t\t\t\t\t\t\t\\\n \".pushsection \" BTF_IDS_SECTION \",\\\"a\\\"; \\n\"\t\\\n \".local \" #symbol \" ; \\n\"\t\\\n@@ -43,10 +47,11 @@ asm(\t\t\t\t\t\t\t\\\n \".size \" #symbol \", 4; \\n\"\t\\\n #symbol \": \\n\"\t\\\n \".zero 4 \\n\"\t\\\n+word\t\t\t\t\t\t\t\\\n \".popsection; \\n\");\n \n-#define __BTF_ID(symbol) \\\n-\t____BTF_ID(symbol)\n+#define __BTF_ID(symbol, word) \\\n+\t____BTF_ID(symbol, word)\n \n #define __ID(prefix) \\\n \t__PASTE(__PASTE(prefix, __COUNTER__), __LINE__)\n@@ -56,7 +61,14 @@ asm(\t\t\t\t\t\t\t\\\n * to 4 zero bytes.\n */\n #define BTF_ID(prefix, name) \\\n-\t__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__))\n+\t__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), \"\")\n+\n+#define ____BTF_ID_FLAGS(prefix, name, flags) \\\n+\t__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), \".long \" #flags \"\\n\")\n+#define __BTF_ID_FLAGS(prefix, name, flags, ...) \\\n+\t____BTF_ID_FLAGS(prefix, name, flags)\n+#define BTF_ID_FLAGS(prefix, name, ...) \\\n+\t__BTF_ID_FLAGS(prefix, name, ##__VA_ARGS__, 0)\n \n /*\n * The BTF_ID_LIST macro defines pure (unsorted) list\n@@ -155,10 +167,58 @@ asm(\t\t\t\t\t\t\t\\\n \".popsection; \\n\");\t\\\n extern struct btf_id_set name;\n \n+/*\n+ * The BTF_SET8_START/END macros pair defines sorted list of\n+ * BTF IDs and their flags plus its members count, with the\n+ * following layout:\n+ *\n+ * BTF_SET8_START(list)\n+ * BTF_ID_FLAGS(type1, name1, flags)\n+ * BTF_ID_FLAGS(type2, name2, flags)\n+ * BTF_SET8_END(list)\n+ *\n+ * __BTF_ID__set8__list:\n+ * .zero 8\n+ * list:\n+ * __BTF_ID__type1__name1__3:\n+ * .zero 4\n+ * .word (1 \u003c\u003c 0) | (1 \u003c\u003c 2)\n+ * __BTF_ID__type2__name2__5:\n+ * .zero 4\n+ * .word (1 \u003c\u003c 3) | (1 \u003c\u003c 1) | (1 \u003c\u003c 2)\n+ *\n+ */\n+#define __BTF_SET8_START(name, scope, flags)\t\t\\\n+__BTF_ID_LIST(name, local)\t\t\t\t\\\n+asm(\t\t\t\t\t\t\t\\\n+\".pushsection \" BTF_IDS_SECTION \",\\\"a\\\"; \\n\"\t\\\n+\".\" #scope \" __BTF_ID__set8__\" #name \"; \\n\"\t\\\n+\"__BTF_ID__set8__\" #name \":; \\n\"\t\\\n+\".zero 4 \\n\"\t\\\n+\".long \" __stringify(flags) \"\\n\"\t\\\n+\".popsection; \\n\");\n+\n+#define BTF_SET8_START(name)\t\t\t\t\\\n+__BTF_SET8_START(name, local, 0)\n+\n+#define BTF_SET8_END(name)\t\t\t\t\\\n+asm(\t\t\t\t\t\t\t\\\n+\".pushsection \" BTF_IDS_SECTION \",\\\"a\\\"; \\n\"\t\\\n+\".size __BTF_ID__set8__\" #name \", .-\" #name \" \\n\"\t\\\n+\".popsection; \\n\");\t\\\n+extern struct btf_id_set8 name;\n+\n+#define BTF_KFUNCS_START(name)\t\t\t\t\\\n+__BTF_SET8_START(name, local, BTF_SET8_KFUNCS)\n+\n+#define BTF_KFUNCS_END(name)\t\t\t\t\\\n+BTF_SET8_END(name)\n+\n #else\n \n-#define BTF_ID_LIST(name) static u32 __maybe_unused name[5];\n+#define BTF_ID_LIST(name) static u32 __maybe_unused name[128];\n #define BTF_ID(prefix, name)\n+#define BTF_ID_FLAGS(prefix, name, ...)\n #define BTF_ID_UNUSED\n #define BTF_ID_LIST_GLOBAL(name, n) u32 __maybe_unused name[n];\n #define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 __maybe_unused name[1];\n@@ -166,6 +226,10 @@ extern struct btf_id_set name;\n #define BTF_SET_START(name) static struct btf_id_set __maybe_unused name = { 0 };\n #define BTF_SET_START_GLOBAL(name) static struct btf_id_set __maybe_unused name = { 0 };\n #define BTF_SET_END(name)\n+#define BTF_SET8_START(name) static struct btf_id_set8 __maybe_unused name = { 0 };\n+#define BTF_SET8_END(name)\n+#define BTF_KFUNCS_START(name) static struct btf_id_set8 __maybe_unused name = { .flags = BTF_SET8_KFUNCS };\n+#define BTF_KFUNCS_END(name)\n \n #endif /* CONFIG_DEBUG_INFO_BTF */\n \n@@ -215,5 +279,9 @@ MAX_BTF_TRACING_TYPE,\n };\n \n extern u32 btf_tracing_ids[];\n+extern u32 bpf_cgroup_btf_id[];\n+extern u32 bpf_local_storage_map_btf_id[];\n+extern u32 btf_bpf_map_id[];\n+extern u32 bpf_kmem_cache_btf_id[];\n \n #endif\ndiff --git a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c\nindex 41dfaaabb73f4b..ac51fd45482140 100644\n--- a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c\n+++ b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c\n@@ -10,7 +10,11 @@\n #include \u003clinux/btf_ids.h\u003e\n #include \"test_progs.h\"\n \n-static int duration;\n+#define BTF_DATA_FILE \"resolve_btfids.test.o.BTF\"\n+\n+#ifndef KF_FASTCALL\n+#define KF_FASTCALL (1 \u003c\u003c 12)\n+#endif\n \n struct symbol {\n \tconst char\t*name;\n@@ -28,12 +32,41 @@ struct symbol test_symbols[] = {\n \t{ \"func\", BTF_KIND_FUNC, -1 },\n };\n \n+struct kfunc_symbol {\n+\tconst char\t*name;\n+\ts32\t\t id;\n+\tu32\t\t flags;\n+};\n+\n+static struct kfunc_symbol kfunc_symbols[] = {\n+\t{ \"kfunc_a\", -1, 0 },\n+\t{ \"kfunc_b\", -1, KF_FASTCALL },\n+};\n+\n /* Align the .BTF_ids section to 4 bytes */\n asm (\n \".pushsection \" BTF_IDS_SECTION \" ,\\\"a\\\"; \\n\"\n \".balign 4, 0; \\n\"\n \".popsection; \\n\");\n \n+/*\n+ * test_list_local, test_set and test_kfunc_set are .local symbols placed\n+ * in .BTF_ids by inline asm, and are read here directly by C name. To the\n+ * compiler they are plain, default-visibility extern objects.\n+ *\n+ * When test_progs is linked as a position-independent executable (PIE),\n+ * taking the address of such an extern is routed through the GOT. The\n+ * GNU assembler on aarch64 unconditionally converts references to .local\n+ * symbols into section + addend form (\".BTF_ids + \u003coffset\u003e\"), but a GOT\n+ * slot cannot carry an addend (the AArch64 ELF spec mandates zero), so\n+ * the linker resolves it to the .BTF_ids base.\n+ *\n+ * Mark them hidden so the compiler treats them as non-interposable and\n+ * emits a direct, addend-preserving PC-relative access instead of a GOT\n+ * load, in both PIE and non-PIE builds. test_list_global is .globl and\n+ * not affected, so it is left at default visibility.\n+ */\n+#pragma GCC visibility push(hidden)\n BTF_ID_LIST(test_list_local)\n BTF_ID_UNUSED\n BTF_ID(typedef, S)\n@@ -43,24 +76,39 @@ BTF_ID(struct, S)\n BTF_ID(union, U)\n BTF_ID(func, func)\n \n-extern __u32 test_list_global[];\n-BTF_ID_LIST_GLOBAL(test_list_global, 1)\n-BTF_ID_UNUSED\n+BTF_SET_START(test_set)\n BTF_ID(typedef, S)\n BTF_ID(typedef, T)\n BTF_ID(typedef, U)\n BTF_ID(struct, S)\n BTF_ID(union, U)\n BTF_ID(func, func)\n+BTF_SET_END(test_set)\n \n-BTF_SET_START(test_set)\n+BTF_KFUNCS_START(test_kfunc_set)\n+BTF_ID_FLAGS(func, kfunc_a)\n+BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL)\n+BTF_KFUNCS_END(test_kfunc_set)\n+\n+/*\n+ * Same kfuncs in reverse declaration order, so resolve_btfids has to\n+ * actually sort at least one of the two sets.\n+ */\n+BTF_KFUNCS_START(test_kfunc_set_rev)\n+BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL)\n+BTF_ID_FLAGS(func, kfunc_a)\n+BTF_KFUNCS_END(test_kfunc_set_rev)\n+#pragma GCC visibility pop\n+\n+extern __u32 test_list_global[];\n+BTF_ID_LIST_GLOBAL(test_list_global, 1)\n+BTF_ID_UNUSED\n BTF_ID(typedef, S)\n BTF_ID(typedef, T)\n BTF_ID(typedef, U)\n BTF_ID(struct, S)\n BTF_ID(union, U)\n BTF_ID(func, func)\n-BTF_SET_END(test_set)\n \n static int\n __resolve_symbol(struct btf *btf, int type_id)\n@@ -70,10 +118,10 @@ __resolve_symbol(struct btf *btf, int type_id)\n \tunsigned int i;\n \n \ttype = btf__type_by_id(btf, type_id);\n-\tif (!type) {\n-\t\tPRINT_FAIL(\"Failed to get type for ID %d\\n\", type_id);\n+\tif (!ASSERT_OK_PTR(type, \"btf__type_by_id\"))\n \t\treturn -1;\n-\t}\n+\n+\tstr = btf__name_by_offset(btf, type-\u003ename_off);\n \n \tfor (i = 0; i \u003c ARRAY_SIZE(test_symbols); i++) {\n \t\tif (test_symbols[i].id \u003e= 0)\n@@ -82,64 +130,80 @@ __resolve_symbol(struct btf *btf, int type_id)\n \t\tif (BTF_INFO_KIND(type-\u003einfo) != test_symbols[i].type)\n \t\t\tcontinue;\n \n-\t\tstr = btf__name_by_offset(btf, type-\u003ename_off);\n-\t\tif (!str) {\n-\t\t\tPRINT_FAIL(\"Failed to get name for BTF ID %d\\n\", type_id);\n-\t\t\treturn -1;\n-\t\t}\n-\n \t\tif (!strcmp(str, test_symbols[i].name))\n \t\t\ttest_symbols[i].id = type_id;\n \t}\n \n+\tif (!btf_is_func(type))\n+\t\treturn 0;\n+\n+\tfor (i = 0; i \u003c ARRAY_SIZE(kfunc_symbols); i++) {\n+\t\tif (kfunc_symbols[i].id \u003e= 0)\n+\t\t\tcontinue;\n+\t\tif (!strcmp(str, kfunc_symbols[i].name))\n+\t\t\tkfunc_symbols[i].id = type_id;\n+\t}\n+\n \treturn 0;\n }\n \n-static int resolve_symbols(void)\n+static int resolve_symbols(struct btf *btf)\n {\n-\tstruct btf *btf;\n+\t__u32 nr = btf__type_cnt(btf);\n \tint type_id;\n-\t__u32 nr;\n-\n-\tbtf = btf__parse_raw(\"resolve_btfids.test.o.BTF\");\n-\tif (CHECK(libbpf_get_error(btf), \"resolve\",\n-\t\t \"Failed to load BTF from resolve_btfids.test.o.BTF\\n\"))\n-\t\treturn -1;\n-\n-\tnr = btf__type_cnt(btf);\n \n \tfor (type_id = 1; type_id \u003c nr; type_id++) {\n \t\tif (__resolve_symbol(btf, type_id))\n-\t\t\tbreak;\n+\t\t\treturn -1;\n \t}\n-\n-\tbtf__free(btf);\n \treturn 0;\n }\n \n+static void check_kfunc_set(struct btf_id_set8 *set)\n+{\n+\tunsigned int i, j;\n+\n+\tASSERT_EQ(set-\u003eflags, BTF_SET8_KFUNCS, \"kfunc_set_flags\");\n+\tASSERT_EQ(set-\u003ecnt, ARRAY_SIZE(kfunc_symbols), \"kfunc_set_cnt\");\n+\n+\tfor (i = 0; i \u003c set-\u003ecnt; i++) {\n+\t\tfor (j = 0; j \u003c ARRAY_SIZE(kfunc_symbols); j++) {\n+\t\t\tif (kfunc_symbols[j].id == (s32)set-\u003epairs[i].id) {\n+\t\t\t\tASSERT_EQ(set-\u003epairs[i].flags,\n+\t\t\t\t\t kfunc_symbols[j].flags, \"kfunc_flags_check\");\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tASSERT_TRUE(j \u003c ARRAY_SIZE(kfunc_symbols), \"kfunc_id_found\");\n+\n+\t\tif (i \u003e 0) {\n+\t\t\tASSERT_LE(set-\u003epairs[i - 1].id,\n+\t\t\t\t set-\u003epairs[i].id, \"kfunc_sort_check\");\n+\t\t}\n+\t}\n+}\n+\n void test_resolve_btfids(void)\n {\n \t__u32 *test_list, *test_lists[] = { test_list_local, test_list_global };\n \tunsigned int i, j;\n-\tint ret = 0;\n+\tstruct btf *btf;\n \n-\tif (resolve_symbols())\n+\tbtf = btf__parse_raw(BTF_DATA_FILE);\n+\tif (!ASSERT_OK_PTR(btf, \"btf_parse\"))\n \t\treturn;\n \n+\tif (resolve_symbols(btf))\n+\t\tgoto out;\n+\n \t/* Check BTF_ID_LIST(test_list_local) and\n \t * BTF_ID_LIST_GLOBAL(test_list_global) IDs\n \t */\n \tfor (j = 0; j \u003c ARRAY_SIZE(test_lists); j++) {\n \t\ttest_list = test_lists[j];\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(test_symbols); i++) {\n-\t\t\tret = CHECK(test_list[i] != test_symbols[i].id,\n-\t\t\t\t \"id_check\",\n-\t\t\t\t \"wrong ID for %s (%d != %d)\\n\",\n-\t\t\t\t test_symbols[i].name,\n-\t\t\t\t test_list[i], test_symbols[i].id);\n-\t\t\tif (ret)\n-\t\t\t\treturn;\n-\t\t}\n+\t\tfor (i = 0; i \u003c ARRAY_SIZE(test_symbols); i++)\n+\t\t\tASSERT_EQ(test_list[i], test_symbols[i].id, test_symbols[i].name);\n \t}\n \n \t/* Check BTF_SET_START(test_set) IDs */\n@@ -153,15 +217,16 @@ void test_resolve_btfids(void)\n \t\t\tbreak;\n \t\t}\n \n-\t\tret = CHECK(!found, \"id_check\",\n-\t\t\t \"ID %d not found in test_symbols\\n\",\n-\t\t\t test_set.ids[i]);\n-\t\tif (ret)\n+\t\tif (!ASSERT_TRUE(found, \"id_in_test_symbols\"))\n \t\t\tbreak;\n \n-\t\tif (i \u003e 0) {\n-\t\t\tif (!ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], \"sort_check\"))\n-\t\t\t\treturn;\n-\t\t}\n+\t\tif (i \u003e 0)\n+\t\t\tASSERT_LE(test_set.ids[i - 1], test_set.ids[i], \"sort_check\");\n \t}\n+\n+\tcheck_kfunc_set(\u0026test_kfunc_set);\n+\tcheck_kfunc_set(\u0026test_kfunc_set_rev);\n+\n+out:\n+\tbtf__free(btf);\n }\ndiff --git a/tools/testing/selftests/bpf/progs/btf_data.c b/tools/testing/selftests/bpf/progs/btf_data.c\nindex baa525275bde31..8587658012c3ee 100644\n--- a/tools/testing/selftests/bpf/progs/btf_data.c\n+++ b/tools/testing/selftests/bpf/progs/btf_data.c\n@@ -48,3 +48,13 @@ int func(struct root_struct *root)\n {\n \treturn 0;\n }\n+\n+int kfunc_a(struct root_struct *root)\n+{\n+\treturn 0;\n+}\n+\n+int kfunc_b(struct root_struct *root)\n+{\n+\treturn 0;\n+}\n"
} |
| 2/1 | 2026/06/24 01:18 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies userspace tools and selftests (tools/include/linux/btf_ids.h and tools/testing/selftests/bpf/). It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit e4fe53b91a323149377b3515d8cb851211065ac7
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jun 24 01:18:07 2026 +0000
syz-cluster: applied patch under review
diff --git a/tools/include/linux/btf_ids.h b/tools/include/linux/btf_ids.h
index 72ea363d434db0..4fe5c5f1558ca9 100644
--- a/tools/include/linux/btf_ids.h
+++ b/tools/include/linux/btf_ids.h
@@ -10,6 +10,9 @@ struct btf_id_set {
u32 ids[];
};
+/* This flag implies BTF_SET8 holds kfunc(s) */
+#define BTF_SET8_KFUNCS (1 << 0)
+
struct btf_id_set8 {
u32 cnt;
u32 flags;
@@ -22,6 +25,7 @@ struct btf_id_set8 {
#ifdef CONFIG_DEBUG_INFO_BTF
#include <linux/compiler.h> /* for __PASTE */
+#include <linux/stringify.h>
/*
* Following macros help to define lists of BTF IDs placed
@@ -35,7 +39,7 @@ struct btf_id_set8 {
#define BTF_IDS_SECTION ".BTF_ids"
-#define ____BTF_ID(symbol) \
+#define ____BTF_ID(symbol, word) \
asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
".local " #symbol " ; \n" \
@@ -43,10 +47,11 @@ asm( \
".size " #symbol ", 4; \n" \
#symbol ": \n" \
".zero 4 \n" \
+word \
".popsection; \n");
-#define __BTF_ID(symbol) \
- ____BTF_ID(symbol)
+#define __BTF_ID(symbol, word) \
+ ____BTF_ID(symbol, word)
#define __ID(prefix) \
__PASTE(__PASTE(prefix, __COUNTER__), __LINE__)
@@ -56,7 +61,14 @@ asm( \
* to 4 zero bytes.
*/
#define BTF_ID(prefix, name) \
- __BTF_ID(__ID(__BTF_ID__##prefix##__##name##__))
+ __BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), "")
+
+#define ____BTF_ID_FLAGS(prefix, name, flags) \
+ __BTF_ID(__ID(__BTF_ID__##prefix##__##name##__), ".long " #flags "\n")
+#define __BTF_ID_FLAGS(prefix, name, flags, ...) \
+ ____BTF_ID_FLAGS(prefix, name, flags)
+#define BTF_ID_FLAGS(prefix, name, ...) \
+ __BTF_ID_FLAGS(prefix, name, ##__VA_ARGS__, 0)
/*
* The BTF_ID_LIST macro defines pure (unsorted) list
@@ -155,10 +167,58 @@ asm( \
".popsection; \n"); \
extern struct btf_id_set name;
+/*
+ * The BTF_SET8_START/END macros pair defines sorted list of
+ * BTF IDs and their flags plus its members count, with the
+ * following layout:
+ *
+ * BTF_SET8_START(list)
+ * BTF_ID_FLAGS(type1, name1, flags)
+ * BTF_ID_FLAGS(type2, name2, flags)
+ * BTF_SET8_END(list)
+ *
+ * __BTF_ID__set8__list:
+ * .zero 8
+ * list:
+ * __BTF_ID__type1__name1__3:
+ * .zero 4
+ * .word (1 << 0) | (1 << 2)
+ * __BTF_ID__type2__name2__5:
+ * .zero 4
+ * .word (1 << 3) | (1 << 1) | (1 << 2)
+ *
+ */
+#define __BTF_SET8_START(name, scope, flags) \
+__BTF_ID_LIST(name, local) \
+asm( \
+".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
+"." #scope " __BTF_ID__set8__" #name "; \n" \
+"__BTF_ID__set8__" #name ":; \n" \
+".zero 4 \n" \
+".long " __stringify(flags) "\n" \
+".popsection; \n");
+
+#define BTF_SET8_START(name) \
+__BTF_SET8_START(name, local, 0)
+
+#define BTF_SET8_END(name) \
+asm( \
+".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
+".size __BTF_ID__set8__" #name ", .-" #name " \n" \
+".popsection; \n"); \
+extern struct btf_id_set8 name;
+
+#define BTF_KFUNCS_START(name) \
+__BTF_SET8_START(name, local, BTF_SET8_KFUNCS)
+
+#define BTF_KFUNCS_END(name) \
+BTF_SET8_END(name)
+
#else
-#define BTF_ID_LIST(name) static u32 __maybe_unused name[5];
+#define BTF_ID_LIST(name) static u32 __maybe_unused name[128];
#define BTF_ID(prefix, name)
+#define BTF_ID_FLAGS(prefix, name, ...)
#define BTF_ID_UNUSED
#define BTF_ID_LIST_GLOBAL(name, n) u32 __maybe_unused name[n];
#define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 __maybe_unused name[1];
@@ -166,6 +226,10 @@ extern struct btf_id_set name;
#define BTF_SET_START(name) static struct btf_id_set __maybe_unused name = { 0 };
#define BTF_SET_START_GLOBAL(name) static struct btf_id_set __maybe_unused name = { 0 };
#define BTF_SET_END(name)
+#define BTF_SET8_START(name) static struct btf_id_set8 __maybe_unused name = { 0 };
+#define BTF_SET8_END(name)
+#define BTF_KFUNCS_START(name) static struct btf_id_set8 __maybe_unused name = { .flags = BTF_SET8_KFUNCS };
+#define BTF_KFUNCS_END(name)
#endif /* CONFIG_DEBUG_INFO_BTF */
@@ -215,5 +279,9 @@ MAX_BTF_TRACING_TYPE,
};
extern u32 btf_tracing_ids[];
+extern u32 bpf_cgroup_btf_id[];
+extern u32 bpf_local_storage_map_btf_id[];
+extern u32 btf_bpf_map_id[];
+extern u32 bpf_kmem_cache_btf_id[];
#endif
diff --git a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
index 41dfaaabb73f4b..ac51fd45482140 100644
--- a/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
+++ b/tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
@@ -10,7 +10,11 @@
#include <linux/btf_ids.h>
#include "test_progs.h"
-static int duration;
+#define BTF_DATA_FILE "resolve_btfids.test.o.BTF"
+
+#ifndef KF_FASTCALL
+#define KF_FASTCALL (1 << 12)
+#endif
struct symbol {
const char *name;
@@ -28,12 +32,41 @@ struct symbol test_symbols[] = {
{ "func", BTF_KIND_FUNC, -1 },
};
+struct kfunc_symbol {
+ const char *name;
+ s32 id;
+ u32 flags;
+};
+
+static struct kfunc_symbol kfunc_symbols[] = {
+ { "kfunc_a", -1, 0 },
+ { "kfunc_b", -1, KF_FASTCALL },
+};
+
/* Align the .BTF_ids section to 4 bytes */
asm (
".pushsection " BTF_IDS_SECTION " ,\"a\"; \n"
".balign 4, 0; \n"
".popsection; \n");
+/*
+ * test_list_local, test_set and test_kfunc_set are .local symbols placed
+ * in .BTF_ids by inline asm, and are read here directly by C name. To the
+ * compiler they are plain, default-visibility extern objects.
+ *
+ * When test_progs is linked as a position-independent executable (PIE),
+ * taking the address of such an extern is routed through the GOT. The
+ * GNU assembler on aarch64 unconditionally converts references to .local
+ * symbols into section + addend form (".BTF_ids + <offset>"), but a GOT
+ * slot cannot carry an addend (the AArch64 ELF spec mandates zero), so
+ * the linker resolves it to the .BTF_ids base.
+ *
+ * Mark them hidden so the compiler treats them as non-interposable and
+ * emits a direct, addend-preserving PC-relative access instead of a GOT
+ * load, in both PIE and non-PIE builds. test_list_global is .globl and
+ * not affected, so it is left at default visibility.
+ */
+#pragma GCC visibility push(hidden)
BTF_ID_LIST(test_list_local)
BTF_ID_UNUSED
BTF_ID(typedef, S)
@@ -43,24 +76,39 @@ BTF_ID(struct, S)
BTF_ID(union, U)
BTF_ID(func, func)
-extern __u32 test_list_global[];
-BTF_ID_LIST_GLOBAL(test_list_global, 1)
-BTF_ID_UNUSED
+BTF_SET_START(test_set)
BTF_ID(typedef, S)
BTF_ID(typedef, T)
BTF_ID(typedef, U)
BTF_ID(struct, S)
BTF_ID(union, U)
BTF_ID(func, func)
+BTF_SET_END(test_set)
-BTF_SET_START(test_set)
+BTF_KFUNCS_START(test_kfunc_set)
+BTF_ID_FLAGS(func, kfunc_a)
+BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL)
+BTF_KFUNCS_END(test_kfunc_set)
+
+/*
+ * Same kfuncs in reverse declaration order, so resolve_btfids has to
+ * actually sort at least one of the two sets.
+ */
+BTF_KFUNCS_START(test_kfunc_set_rev)
+BTF_ID_FLAGS(func, kfunc_b, KF_FASTCALL)
+BTF_ID_FLAGS(func, kfunc_a)
+BTF_KFUNCS_END(test_kfunc_set_rev)
+#pragma GCC visibility pop
+
+extern __u32 test_list_global[];
+BTF_ID_LIST_GLOBAL(test_list_global, 1)
+BTF_ID_UNUSED
BTF_ID(typedef, S)
BTF_ID(typedef, T)
BTF_ID(typedef, U)
BTF_ID(struct, S)
BTF_ID(union, U)
BTF_ID(func, func)
-BTF_SET_END(test_set)
static int
__resolve_symbol(struct btf *btf, int type_id)
@@ -70,10 +118,10 @@ __resolve_symbol(struct btf *btf, int type_id)
unsigned int i;
type = btf__type_by_id(btf, type_id);
- if (!type) {
- PRINT_FAIL("Failed to get type for ID %d\n", type_id);
+ if (!ASSERT_OK_PTR(type, "btf__type_by_id"))
return -1;
- }
+
+ str = btf__name_by_offset(btf, type->name_off);
for (i = 0; i < ARRAY_SIZE(test_symbols); i++) {
if (test_symbols[i].id >= 0)
@@ -82,64 +130,80 @@ __resolve_symbol(struct btf *btf, int type_id)
if (BTF_INFO_KIND(type->info) != test_symbols[i].type)
continue;
- str = btf__name_by_offset(btf, type->name_off);
- if (!str) {
- PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id);
- return -1;
- }
-
if (!strcmp(str, test_symbols[i].name))
test_symbols[i].id = type_id;
}
+ if (!btf_is_func(type))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(kfunc_symbols); i++) {
+ if (kfunc_symbols[i].id >= 0)
+ continue;
+ if (!strcmp(str, kfunc_symbols[i].name))
+ kfunc_symbols[i].id = type_id;
+ }
+
return 0;
}
-static int resolve_symbols(void)
+static int resolve_symbols(struct btf *btf)
{
- struct btf *btf;
+ __u32 nr = btf__type_cnt(btf);
int type_id;
- __u32 nr;
-
- btf = btf__parse_raw("resolve_btfids.test.o.BTF");
- if (CHECK(libbpf_get_error(btf), "resolve",
- "Failed to load BTF from resolve_btfids.test.o.BTF\n"))
- return -1;
-
- nr = btf__type_cnt(btf);
for (type_id = 1; type_id < nr; type_id++) {
if (__resolve_symbol(btf, type_id))
- break;
+ return -1;
}
-
- btf__free(btf);
return 0;
}
+static void check_kfunc_set(struct btf_id_set8 *set)
+{
+ unsigned int i, j;
+
+ ASSERT_EQ(set->flags, BTF_SET8_KFUNCS, "kfunc_set_flags");
+ ASSERT_EQ(set->cnt, ARRAY_SIZE(kfunc_symbols), "kfunc_set_cnt");
+
+ for (i = 0; i < set->cnt; i++) {
+ for (j = 0; j < ARRAY_SIZE(kfunc_symbols); j++) {
+ if (kfunc_symbols[j].id == (s32)set->pairs[i].id) {
+ ASSERT_EQ(set->pairs[i].flags,
+ kfunc_symbols[j].flags, "kfunc_flags_check");
+ break;
+ }
+ }
+
+ ASSERT_TRUE(j < ARRAY_SIZE(kfunc_symbols), "kfunc_id_found");
+
+ if (i > 0) {
+ ASSERT_LE(set->pairs[i - 1].id,
+ set->pairs[i].id, "kfunc_sort_check");
+ }
+ }
+}
+
void test_resolve_btfids(void)
{
__u32 *test_list, *test_lists[] = { test_list_local, test_list_global };
unsigned int i, j;
- int ret = 0;
+ struct btf *btf;
- if (resolve_symbols())
+ btf = btf__parse_raw(BTF_DATA_FILE);
+ if (!ASSERT_OK_PTR(btf, "btf_parse"))
return;
+ if (resolve_symbols(btf))
+ goto out;
+
/* Check BTF_ID_LIST(test_list_local) and
* BTF_ID_LIST_GLOBAL(test_list_global) IDs
*/
for (j = 0; j < ARRAY_SIZE(test_lists); j++) {
test_list = test_lists[j];
- for (i = 0; i < ARRAY_SIZE(test_symbols); i++) {
- ret = CHECK(test_list[i] != test_symbols[i].id,
- "id_check",
- "wrong ID for %s (%d != %d)\n",
- test_symbols[i].name,
- test_list[i], test_symbols[i].id);
- if (ret)
- return;
- }
+ for (i = 0; i < ARRAY_SIZE(test_symbols); i++)
+ ASSERT_EQ(test_list[i], test_symbols[i].id, test_symbols[i].name);
}
/* Check BTF_SET_START(test_set) IDs */
@@ -153,15 +217,16 @@ void test_resolve_btfids(void)
break;
}
- ret = CHECK(!found, "id_check",
- "ID %d not found in test_symbols\n",
- test_set.ids[i]);
- if (ret)
+ if (!ASSERT_TRUE(found, "id_in_test_symbols"))
break;
- if (i > 0) {
- if (!ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], "sort_check"))
- return;
- }
+ if (i > 0)
+ ASSERT_LE(test_set.ids[i - 1], test_set.ids[i], "sort_check");
}
+
+ check_kfunc_set(&test_kfunc_set);
+ check_kfunc_set(&test_kfunc_set_rev);
+
+out:
+ btf__free(btf);
}
diff --git a/tools/testing/selftests/bpf/progs/btf_data.c b/tools/testing/selftests/bpf/progs/btf_data.c
index baa525275bde31..8587658012c3ee 100644
--- a/tools/testing/selftests/bpf/progs/btf_data.c
+++ b/tools/testing/selftests/bpf/progs/btf_data.c
@@ -48,3 +48,13 @@ int func(struct root_struct *root)
{
return 0;
}
+
+int kfunc_a(struct root_struct *root)
+{
+ return 0;
+}
+
+int kfunc_b(struct root_struct *root)
+{
+ return 0;
+}
|
| 3/2 | 2026/06/24 01:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6772 output: 29 thoughts: 720 Thoughts: **Analyzing a Patch: Tool-Side Changes for BTF ID Handling** Okay, so I'm looking at this patch and my initial thought is that it looks pretty straightforward. It seems to be modifying some BTF ID handling, specifically within the `tools/` directory. I see that `tools/include/linux/btf_ids.h` is being updated, along with some related tests in `tools/testing/selftests/bpf/`. The key here is the addition of macros – `BTF_SET8_KFUNCS`, `BTF_ID_FLAGS`, `BTF_SET8_START`, etc. – which seem like they are for managing and organizing BTF ID definitions. My first concern is to make sure these tool-side changes aren't inadvertently impacting the core kernel. I immediately think to check if the kernel's copy of `btf_ids.h` (`include/linux/btf_ids.h`) is also being modified, but it's not. Good, this is probably isolated to the build tools and self-tests. I quickly double-check the diff to be sure. Yep, it's just the `tools/` directory: `tools/include/linux/btf_ids.h`, `tools/testing/selftests/bpf/prog_tests/resolve_btfids.c`, and `tools/testing/selftests/bpf/progs/btf_data.c`. This confirms it's a "tools" change and not directly kernel-execution relevant. My next line of thought is whether these changes introduce any new fuzzing targets or if they are relevant to kernel execution. Since it's all within `tools/`, I don't think this patch itself is a direct candidate for syzkaller fuzzing, unless, and this is a big IF, the tools in question affect the generated kernel code in some way. But I don't think that's the case here. It looks like it's just adding macros and some tests for the BTF ID resolution process. I'm starting to think this is a code-hygiene type of patch; making things cleaner and easier to work with, rather than a functional change. If it were a functional change affecting kernel execution, it would need more scrutiny. I take another look and grep to verify that `tools/include/linux/btf_ids.h` is used by the `tools` and not the kernel itself. Confirmed. `include/linux/btf_ids.h` is used by the kernel while `tools/include/linux/btf_ids.h` is only used by tools like `resolve_btfids` and bpf selftests. |
| 4/2 | 2026/06/24 01:18 | tool | grepper |
0mArgs:{
"Expression": "BTF_SET8_KFUNCS",
"PathPrefix": ""
}Results: {
"Output": "include/linux/btf_ids.h=8=struct btf_id_set {\n--\ninclude/linux/btf_ids.h-13-/* This flag implies BTF_SET8 holds kfunc(s) */\ninclude/linux/btf_ids.h:14:#define BTF_SET8_KFUNCS\t\t(1 \u003c\u003c 0)\ninclude/linux/btf_ids.h-15-\n--\ninclude/linux/btf_ids.h=210=extern struct btf_id_set8 name;\n--\ninclude/linux/btf_ids.h-212-#define BTF_KFUNCS_START(name)\t\t\t\t\\\ninclude/linux/btf_ids.h:213:__BTF_SET8_START(name, local, BTF_SET8_KFUNCS)\ninclude/linux/btf_ids.h-214-\n--\ninclude/linux/btf_ids.h=216=BTF_SET8_END(name)\n--\ninclude/linux/btf_ids.h-231-#define BTF_SET8_END(name)\ninclude/linux/btf_ids.h:232:#define BTF_KFUNCS_START(name) static struct btf_id_set8 __maybe_unused name = { .flags = BTF_SET8_KFUNCS };\ninclude/linux/btf_ids.h-233-#define BTF_KFUNCS_END(name)\n--\nkernel/bpf/btf.c=9116=int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,\n--\nkernel/bpf/btf.c-9123-\t */\nkernel/bpf/btf.c:9124:\tif (!(kset-\u003eset-\u003eflags \u0026 BTF_SET8_KFUNCS)) {\nkernel/bpf/btf.c-9125-\t\tWARN_ON(!kset-\u003eowner);\n--\ntools/include/linux/btf_ids.h=8=struct btf_id_set {\n--\ntools/include/linux/btf_ids.h-13-/* This flag implies BTF_SET8 holds kfunc(s) */\ntools/include/linux/btf_ids.h:14:#define BTF_SET8_KFUNCS\t\t(1 \u003c\u003c 0)\ntools/include/linux/btf_ids.h-15-\n--\ntools/include/linux/btf_ids.h=209=extern struct btf_id_set8 name;\n--\ntools/include/linux/btf_ids.h-211-#define BTF_KFUNCS_START(name)\t\t\t\t\\\ntools/include/linux/btf_ids.h:212:__BTF_SET8_START(name, local, BTF_SET8_KFUNCS)\ntools/include/linux/btf_ids.h-213-\n--\ntools/include/linux/btf_ids.h=215=BTF_SET8_END(name)\n--\ntools/include/linux/btf_ids.h-230-#define BTF_SET8_END(name)\ntools/include/linux/btf_ids.h:231:#define BTF_KFUNCS_START(name) static struct btf_id_set8 __maybe_unused name = { .flags = BTF_SET8_KFUNCS };\ntools/include/linux/btf_ids.h-232-#define BTF_KFUNCS_END(name)\n--\ntools/testing/selftests/bpf/prog_tests/resolve_btfids.c=162=static void check_kfunc_set(struct btf_id_set8 *set)\n--\ntools/testing/selftests/bpf/prog_tests/resolve_btfids.c-165-\ntools/testing/selftests/bpf/prog_tests/resolve_btfids.c:166:\tASSERT_EQ(set-\u003eflags, BTF_SET8_KFUNCS, \"kfunc_set_flags\");\ntools/testing/selftests/bpf/prog_tests/resolve_btfids.c-167-\tASSERT_EQ(set-\u003ecnt, ARRAY_SIZE(kfunc_symbols), \"kfunc_set_cnt\");\n"
} |
| 5/2 | 2026/06/24 01:18 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9179 output: 80 thoughts: 100 Thoughts: **My Assessment of the Patch's Impact** Okay, so I've taken a look at this patch. It's pretty straightforward, thankfully. My initial scan shows the changes are isolated to the `tools/` directory, specifically `tools/include/linux/btf_ids.h` and the selftests within `tools/testing/selftests/bpf/`. Crucially, it's *not* touching the main kernel's include directory (`include/linux/btf_ids.h`) or any critical core kernel functionality directly. This is just a matter of keeping the tool's header file in sync with the kernel's definition, and adding a new test to the tooling. This isn't a functional change to the kernel itself, it's just about internal consistency and verification within the tools. With that in mind, I am going to flag this as not worth fuzzing for potential functional bugs. |
| 6/2 | 2026/06/24 01:18 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch only modifies userspace tools and selftests (tools/include/linux/btf_ids.h and tools/testing/selftests/bpf/). It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies userspace tools and selftests (tools/include/linux/btf_ids.h and tools/testing/selftests/bpf/). It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|