From 6ceaa397b6040e7563e50b87737904189acf68a3 Mon Sep 17 00:00:00 2001 From: ardnew Date: Sun, 29 Mar 2026 15:43:15 -0500 Subject: [PATCH 1/2] fix: use CO-RE reads in fork tracepoint for kernel 6.12+ compat Kernel 6.12+ changed the sched_process_fork tracepoint's parent_comm and child_comm fields from fixed char[16] arrays to __data_loc char[] (4 bytes each) due to configurable TASK_COMM_LEN. The old struct layout caused the BPF program to declare context accesses up to byte 48, but the tracepoint data area is only 24 bytes. The kernel rejects this in __perf_event_set_bpf_prog() where max_ctx_offset > trace_event_get_offsets() returns EACCES. Replace the manual tp_fork_ctx struct with CO-RE reads (BPF_CORE_READ) against trace_event_raw_sched_process_fork from vmlinux.h. The CO-RE loader relocates the parent_pid and child_pid field offsets at load time based on the running kernel's BTF, so the same compiled program works on both pre-6.12 and 6.12+ kernels. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- bpf/sensor.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/bpf/sensor.c b/bpf/sensor.c index e23c979..dba10ce 100644 --- a/bpf/sensor.c +++ b/bpf/sensor.c @@ -53,14 +53,10 @@ struct chmod_event { // tracepoint infrastructure — we skip them by starting our struct at the // first tracepoint-specific field. -struct tp_fork_ctx { - // common fields (8 bytes) — not accessed directly - u64 __pad; - char parent_comm[16]; - s32 parent_pid; - char child_comm[16]; - s32 child_pid; -}; +// No manual tp_fork_ctx struct — kernel 6.12+ changed parent_comm/child_comm +// from char[16] to __data_loc char[], shifting field offsets. We use CO-RE +// (BPF_CORE_READ on trace_event_raw_sched_process_fork from vmlinux.h) so the +// loader relocates parent_pid/child_pid offsets for the running kernel. struct tp_exit_ctx { u64 __pad; @@ -140,10 +136,15 @@ struct { // Tracepoint: sched/sched_process_fork // If parent is in a tracked subtree, add child to the same subtree. +// Uses CO-RE reads for parent_pid/child_pid because kernel 6.12+ changed +// the tracepoint layout (parent_comm/child_comm went from char[16] to +// __data_loc char[]), shifting field offsets. BPF_CORE_READ lets the +// loader resolve the correct offsets for the running kernel. SEC("tracepoint/sched/sched_process_fork") -int tp_sched_process_fork(struct tp_fork_ctx *ctx) { - u32 parent_pid = ctx->parent_pid; - u32 child_pid = ctx->child_pid; +int tp_sched_process_fork(void *ctx) { + struct trace_event_raw_sched_process_fork *raw = ctx; + u32 parent_pid = BPF_CORE_READ(raw, parent_pid); + u32 child_pid = BPF_CORE_READ(raw, child_pid); u32 *root = bpf_map_lookup_elem(&pid_to_root, &parent_pid); if (root) { From 0d7cc814d71862fbedaa734130fc5bd863cc2919 Mon Sep 17 00:00:00 2001 From: ardnew Date: Sun, 29 Mar 2026 16:06:29 -0500 Subject: [PATCH 2/2] bpf: remove redundant comment per PR comment --- bpf/sensor.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bpf/sensor.c b/bpf/sensor.c index dba10ce..038a0cf 100644 --- a/bpf/sensor.c +++ b/bpf/sensor.c @@ -53,11 +53,6 @@ struct chmod_event { // tracepoint infrastructure — we skip them by starting our struct at the // first tracepoint-specific field. -// No manual tp_fork_ctx struct — kernel 6.12+ changed parent_comm/child_comm -// from char[16] to __data_loc char[], shifting field offsets. We use CO-RE -// (BPF_CORE_READ on trace_event_raw_sched_process_fork from vmlinux.h) so the -// loader relocates parent_pid/child_pid offsets for the running kernel. - struct tp_exit_ctx { u64 __pad; char comm[16];