]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tracing: Fix union collision of module and refcnt for dynamic events
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Fri, 17 Jul 2026 02:51:49 +0000 (11:51 +0900)
committerSteven Rostedt <rostedt@goodmis.org>
Fri, 24 Jul 2026 17:43:17 +0000 (13:43 -0400)
In 'struct trace_event_call', the 'module' pointer and the 'refcnt'
atomic variable share the same memory space in a union. For dynamic
events, the union member is 'refcnt', which acts as an active
reference counter.

When a dynamic event (such as kprobe, uprobe, fprobe, eprobe, or
wprobe) has a non-zero reference count (e.g. due to active event
triggers or perf attachments), its 'call->module' evaluates to a
small non-zero integer instead of NULL.

When filtering or setting events for a specific module (e.g., writing
':mod:<module>' to 'set_event'), the code in
'__ftrace_set_clr_event_nolock()' and 'update_event_fields()' reads
'call->module' directly without checking whether the event is dynamic.
This causes the kernel to treat the small integer (refcnt) as a
'struct module' pointer, leading to a NULL/invalid pointer dereference
(Oops) when dereferencing the module name.

Fix this by ensuring that the 'TRACE_EVENT_FL_DYNAMIC' flag is checked
before treating 'call->module' as a valid pointer in these code paths.

Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/178425670947.84440.11344393611899824907.stgit@devnote2
Fixes: 4c86bc531e60 ("tracing: Add :mod: command to enabled module events")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/trace_events.c

index c46e623e7e0de0ee40dd3f9af698757c9215b9f2..956692856fa822e1e29857d43a6ea1a8b5be6f17 100644 (file)
@@ -1350,7 +1350,9 @@ __ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match,
                call = file->event_call;
 
                /* If a module is specified, skip events that are not that module */
-               if (module && (!call->module || strcmp(module_name(call->module), module)))
+               if (module &&
+                   ((call->flags & TRACE_EVENT_FL_DYNAMIC) ||
+                    !call->module || strcmp(module_name(call->module), module)))
                        continue;
 
                name = trace_event_name(call);