Re: [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events
flat view
From: Steven Rostedt <rostedt@goodmis.org>
Date: 2026-08-24 18:43:18
Also in:
lkml
On Mon, 24 Aug 2026 15:10:11 +0800 Henry Martin [off-list ref] wrote:
Fields of a probe-based dynamic event (kprobe, uprobe and eprobe events) are created from the argument name and type strings of the trace_probe that first registers the event, as plain pointer references without copying. When several probes are appended to the same event, they share the trace_event_call and its field list, which stays the one defined by the primary probe. Deleting just the primary probe with
What do you mean by "appended to the same event"? Do you mean eprobes? Can you post a reproducer for this?
"-:group/event symbol" frees the trace_probe and its argument strings, while the event call is kept registered by the remaining sibling probes. field->name and field->type are left dangling, and any field lookup - e.g. writing to events/<grp>/<ev>/filter - reads freed memory: BUG: KASAN: slab-use-after-free in strcmp+0xa7/0xb0 Call trace: trace_find_event_field+0xd6/0x220 parse_pred process_preds create_filter apply_event_filter event_filter_write Make the field own its strings: duplicate name and type with kstrdup_const() in __trace_define_field() and release them with kfree_const() in trace_destroy_fields(). Fields of static trace events still reference their kernel/module rodata string literals directly, as kstrdup_const()/kfree_const() only touch memory that was actually allocated.
Wrong fix.
quoted hunk ↗ jump to hunk
The issue was found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab. Fixes: ca89bc071d5e4 ("tracing/kprobe: Add multi-probe per event support") Signed-off-by: Henry Martin <redacted> --- kernel/trace/trace_events.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index c01b10b99f67e..ee3b93fa09ee8 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c
This is a bug with trace_probes.c and not trace_events.c. This should be fixed without touching trace_events.c. That is, the trace_probes.c code (or trace_eprobes.c if it's only affects eprobes) should handle this issue. If you had an example, I could have figured out exactly where to place the fix. -- Steve
quoted hunk ↗ jump to hunk
@@ -123,8 +123,18 @@ static int __trace_define_field(struct list_head *head, const char *type, if (!field) return -ENOMEM; - field->name = name; - field->type = type; + field->name = kstrdup_const(name, GFP_TRACE); + if (!field->name) { + kmem_cache_free(field_cachep, field); + return -ENOMEM; + } + + field->type = kstrdup_const(type, GFP_TRACE); + if (!field->type) { + kfree_const(field->name); + kmem_cache_free(field_cachep, field); + return -ENOMEM; + } if (filter_type == FILTER_OTHER) field->filter_type = filter_assign_type(type);@@ -225,6 +235,8 @@ static void trace_destroy_fields(struct trace_event_call *call) head = trace_get_fields(call); list_for_each_entry_safe(field, next, head, link) { list_del(&field->link); + kfree_const(field->name); + kfree_const(field->type); kmem_cache_free(field_cachep, field); } }