Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events
@ 2026-08-24  7:10 Henry Martin
  2026-08-24  7:27 ` sashiko-bot
  2026-08-24 18:43 ` Steven Rostedt
  0 siblings, 2 replies; 3+ messages in thread
From: Henry Martin @ 2026-08-24  7:10 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu
  Cc: Mathieu Desnoyers, linux-trace-kernel, linux-kernel, Henry Martin

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
"-: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.

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 <bsdhenrymartin@gmail.com>
---
 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
@@ -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);
 	}
 }
-- 
2.43.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events
  2026-08-24  7:10 [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events Henry Martin
@ 2026-08-24  7:27 ` sashiko-bot
  2026-08-24 18:43 ` Steven Rostedt
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-08-24  7:27 UTC (permalink / raw)
  To: Henry Martin; +Cc: linux-trace-kernel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] The commit message claims that fields of static trace events reference their kernel or module rodata string literals directly without allocation, but module strings are unconditionally duplicated.

Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but if a user_event's destruction fails because the trace event is busy, its fields are irreversibly destroyed, leaving the active event in a corrupted state.
--

--- Patch [1]: [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events ---
commit cf6ec74d4b06c238fc3f0cc0f2463ea2e1435590
Author: Henry Martin <bsdhenrymartin@gmail.com>

tracing: Fix use-after-free on field name/type of dynamic probe events

This commit modifies dynamic event trace field registration to duplicate
field name and type strings using kstrdup_const(). This ensures the field
owns its strings and prevents use-after-free bugs when primary probes are
deleted but event calls remain active.

> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index 0356cae0cf74e..13d7675bc5132 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -122,8 +122,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);

[Severity: Medium]
The commit message states that fields of static trace events reference their
kernel or module rodata string literals directly, as kstrdup_const() only
touches allocated memory.

Does kstrdup_const() actually handle module rodata this way? Looking at
kstrdup_const(), it delegates to is_kernel_rodata(), which only checks core
kernel boundaries. 

Won't this cause module trace events to unconditionally duplicate their name
and type strings instead of referencing the module rodata?

> +	if (!field->type) {
> +		kfree_const(field->name);
> +		kmem_cache_free(field_cachep, field);
> +		return -ENOMEM;
> +	}
>  
>  	if (filter_type == FILTER_OTHER)

[ ... ]

While reviewing the string lifecycle in trace events, a related preexisting
issue in user events was identified:

kernel/trace/trace_events_user.c:destroy_user_event() {
        ...
        /* Must destroy fields before call removal */
        user_event_destroy_fields(user);

        ret = user_event_set_call_visible(user, false);

        if (ret)
                return ret;
        ...
}

[Severity: High]
This isn't a bug introduced by this patch, but if a user_event's destruction
fails because the trace event is busy (user_event_set_call_visible() returns
-EBUSY), the event's fields are already irreversibly destroyed.

Will this leave the active event in a corrupted state, where any subsequent
interactions with this event operate on an empty field list?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260824071011.3507735-1-bsdhenrymartin@gmail.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events
  2026-08-24  7:10 [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events Henry Martin
  2026-08-24  7:27 ` sashiko-bot
@ 2026-08-24 18:43 ` Steven Rostedt
  1 sibling, 0 replies; 3+ messages in thread
From: Steven Rostedt @ 2026-08-24 18:43 UTC (permalink / raw)
  To: Henry Martin
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-trace-kernel,
	linux-kernel

On Mon, 24 Aug 2026 15:10:11 +0800
Henry Martin <bsdhenrymartin@gmail.com> 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.

> 
> 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 <bsdhenrymartin@gmail.com>
> ---
>  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

> @@ -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);
>  	}
>  }


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-24 18:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24  7:10 [PATCH] tracing: Fix use-after-free on field name/type of dynamic probe events Henry Martin
2026-08-24  7:27 ` sashiko-bot
2026-08-24 18:43 ` Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox