From: Mykyta Yatsenko <[email protected]>
DECLARE_EVENT_CLASS emitted __bpf_trace_btf_ids_<call> through
BTF_ID_LIST_GLOBAL, i.e. a global symbol named after the event class.
The class name is not unique across the kernel, so the symbol
multiply-defines whenever two translation units instantiate the same
class.
Switch to the file-local BTF_ID_LIST: the list is reached
only through the event_class_<call>.btf_ids pointer, initialised in the
same unit, so tracefs readers never reference the symbol by name and
resolve_btfids still fills the now-local .BTF_ids entries.
The handcrafted syscall classes are the one cross-unit consumer: give
them their own local BTF_ID_LIST rather than importing the generated
sys_{enter,exit} lists, which are now file-local.
Fixes: eadc0725ab8d3 ("tracing: Expose tracepoint BTF ids via tracefs")
Reported-by: Mark Brown <[email protected]>
Closes:
https://lore.kernel.org/all/[email protected]/
Signed-off-by: Mykyta Yatsenko <[email protected]>
---
include/trace/trace_events.h | 6 ++++--
kernel/trace/trace_syscalls.c | 22 ++++++++++++++--------
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
index 09ad57ac4b73..45ffbe04b580 100644
--- a/include/trace/trace_events.h
+++ b/include/trace/trace_events.h
@@ -404,10 +404,12 @@ static inline notrace int trace_event_get_offsets_##call(
\
* [0] FUNC __bpf_trace_<call> (the BPF dispatcher)
* [1] STRUCT trace_event_raw_<call> (the ring-buffer record)
* Exposed via the events/<sys>/<name>/btf_ids tracefs file.
+ *
+ * File-local: the class name is not unique, so a global symbol would
+ * clash across translation units.
*/
#define _TRACE_BTF_IDS_DECLARE(call) \
- extern u32 __bpf_trace_btf_ids_##call[]; \
- BTF_ID_LIST_GLOBAL(__bpf_trace_btf_ids_##call, 2) \
+ BTF_ID_LIST(__bpf_trace_btf_ids_##call) \
BTF_ID(func, __bpf_trace_##call) \
BTF_ID(struct, trace_event_raw_##call)
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 48ef1a93e576..9b5931f2f280 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -9,6 +9,7 @@
#include <linux/ftrace.h>
#include <linux/perf_event.h>
#include <linux/xarray.h>
+#include <linux/btf_ids.h>
#include <asm/syscall.h>
#include "trace_output.h"
@@ -1305,13 +1306,18 @@ struct trace_event_functions exit_syscall_print_funcs =
{
#ifdef CONFIG_BPF_EVENTS
/*
- * BTF id lists generated by DECLARE_EVENT_CLASS for the sys_enter and
- * sys_exit tracepoints. The auto-generated event_class_sys_{enter,exit}
- * is unused (per-syscall events share the handcrafted classes below),
- * but the id lists themselves are global and reusable.
+ * BTF id lists for the shared sys_enter/sys_exit dispatcher tracepoints,
+ * resolved by resolve_btfids. Defined locally rather than importing the
+ * DECLARE_EVENT_CLASS-generated lists, which are now file-local to the
+ * translation unit that instantiates the tracepoint.
*/
-extern u32 __bpf_trace_btf_ids_sys_enter[];
-extern u32 __bpf_trace_btf_ids_sys_exit[];
+BTF_ID_LIST(syscall_enter_btf_ids)
+BTF_ID(func, __bpf_trace_sys_enter)
+BTF_ID(struct, trace_event_raw_sys_enter)
+
+BTF_ID_LIST(syscall_exit_btf_ids)
+BTF_ID(func, __bpf_trace_sys_exit)
+BTF_ID(struct, trace_event_raw_sys_exit)
#endif
struct trace_event_class __refdata event_class_syscall_enter = {
@@ -1321,7 +1327,7 @@ struct trace_event_class __refdata
event_class_syscall_enter = {
.get_fields = syscall_get_enter_fields,
.raw_init = init_syscall_trace,
#ifdef CONFIG_BPF_EVENTS
- .btf_ids = __bpf_trace_btf_ids_sys_enter,
+ .btf_ids = syscall_enter_btf_ids,
#endif
};
@@ -1336,7 +1342,7 @@ struct trace_event_class __refdata
event_class_syscall_exit = {
.fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
.raw_init = init_syscall_trace,
#ifdef CONFIG_BPF_EVENTS
- .btf_ids = __bpf_trace_btf_ids_sys_exit,
+ .btf_ids = syscall_exit_btf_ids,
#endif
};
---
base-commit: eadc0725ab8d38c05148fce49f8d5c6a0e01f062
change-id: 20260730-b4-fix_btf_tracefs-fdafda5fdb5b
Best regards,
--
Mykyta Yatsenko <[email protected]>