* [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger
@ 2026-09-07 12:44 Donggeun Yoo
2026-09-07 12:44 ` [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger Donggeun Yoo
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Donggeun Yoo @ 2026-09-07 12:44 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, Tom Zanussi, linux-trace-kernel, linux-kernel,
donggeunyoo.kernel
Both of these were pointed out on the list against an unrelated hist
patch [1], and both are the same shape as commit 6f86bdeab633 ("tracing:
Fix bad hist from corrupting named_triggers list"): a trigger that is on
the global named_triggers list gets freed without being taken off it, and
the next lookup by name reads the freed object.
Link: https://lore.kernel.org/linux-trace-kernel/20260907092944.3950E1F00A3D@smtp.kernel.org/ [1]
Patch 1 is the init path. event_hist_trigger_named_init() saves the
trigger under the name before it takes the reference that can fail, and
does not undo the save.
Patch 2 is the enable path, the one case that fix did not reach.
hist_trigger_enable() removes the trigger from file->triggers on
failure, which is the only handle hist_unregister_trigger() has, so the
->free() that unlinks it never runs. Leaving it on the list lets the
existing unregister do the whole unwind, which also stops out_free from
touching a hist_data that hist_register_trigger() already destroyed.
The two are independent and can be taken separately.
Reproduced on x86_64 under KASAN_INLINE by making the two failures fire
from a debug knob, since neither is reachable without an allocation
failure or an event that refuses to register. Same kernel and initramfs
either way, one boot per case:
v7.3-rc2 patched
control, no injected failure clean clean
1) nested init fails KASAN clean
2) enable fails, new named trigger KASAN clean
3) enable fails, shared histogram KASAN + panic clean
Case 3 reports in remove_hist_vars() rather than find_named_trigger(),
from the out_free fall-through described in patch 2.
After each injected failure the same name is written again and is
accepted on the patched kernel, so the trigger really did leave the list;
on v7.3-rc2 case 2 rejects it.
selftests/ftrace test.d/trigger before and after: 45 results, identical
item by item (32 passed, 3 failed, 2 unresolved, 8 unsupported). The
failures and the unresolved results are there without the patches too.
Donggeun Yoo (2):
tracing: hist: take the reference before publishing the named trigger
tracing: hist: undo the registration when enabling the trigger fails
kernel/trace/trace_events_hist.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
base-commit: df2908090cda368b01ff43709f51890076c56157
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger 2026-09-07 12:44 [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo @ 2026-09-07 12:44 ` Donggeun Yoo [not found] ` <20260907125934.5C6261F00A3E@smtp.kernel.org> 2026-09-07 21:01 ` Tom Zanussi 2026-09-07 12:44 ` [PATCH 2/2] tracing: hist: undo the registration when enabling the trigger fails Donggeun Yoo 2026-09-10 1:10 ` [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo 2 siblings, 2 replies; 7+ messages in thread From: Donggeun Yoo @ 2026-09-07 12:44 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu Cc: Mathieu Desnoyers, Tom Zanussi, linux-trace-kernel, linux-kernel, donggeunyoo.kernel event_hist_trigger_named_init() puts the trigger on the global named_triggers list and only then takes the reference on the trigger it shares its histogram with: data->ref++; save_named_trigger(data->named_data->name, data); ret = event_hist_trigger_init(data->named_data); if (ret < 0) { kfree(data->cmd_ops); data->cmd_ops = &trigger_hist_cmd; } return ret; event_hist_trigger_init() fails when alloc_hist_pad() cannot allocate, and nothing takes the trigger back off the list on the way out. event_hist_trigger_parse() frees it, and the next lookup by name reads the freed object: BUG: KASAN: slab-use-after-free in find_named_trigger+0xac/0xc0 Read of size 8 at addr ffff888009346860 by task init/1 find_named_trigger+0xac/0xc0 hist_register_trigger+0xc1/0xa00 event_hist_trigger_parse+0x3146/0x6af0 event_trigger_write+0xce/0x160 Freed by task 67: kfree+0x154/0x420 trigger_kthread_fn+0xfd/0x160 Do the reference first and publish once it has succeeded, so that nothing which can fail runs after the trigger becomes findable. Reported-by: Sashiko AI <sashiko-bot@kernel.org> Closes: https://lore.kernel.org/linux-trace-kernel/20260907092944.3950E1F00A3D@smtp.kernel.org/ Fixes: 7ab0fc61ce73 ("tracing: Move histogram trigger variables from stack to per CPU structure") Cc: stable@vger.kernel.org Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com> --- kernel/trace/trace_events_hist.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 963e0d6b61fd..c6c04926bdf0 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -6383,17 +6383,18 @@ static int event_hist_trigger_named_init(struct event_trigger_data *data) { int ret; - data->ref++; - - save_named_trigger(data->named_data->name, data); - ret = event_hist_trigger_init(data->named_data); if (ret < 0) { kfree(data->cmd_ops); data->cmd_ops = &trigger_hist_cmd; + return ret; } - return ret; + data->ref++; + + save_named_trigger(data->named_data->name, data); + + return 0; } static void event_hist_trigger_named_free(struct event_trigger_data *data) base-commit: df2908090cda368b01ff43709f51890076c56157 -- 2.53.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <20260907125934.5C6261F00A3E@smtp.kernel.org>]
* Re: [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger [not found] ` <20260907125934.5C6261F00A3E@smtp.kernel.org> @ 2026-09-07 13:13 ` Donggeun Yoo 0 siblings, 0 replies; 7+ messages in thread From: Donggeun Yoo @ 2026-09-07 13:13 UTC (permalink / raw) To: sashiko-reviews Cc: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, linux-trace-kernel, linux-kernel, donggeunyoo.kernel On Mon, Sep 07, 2026 at 12:59:33PM +0000, sashiko-bot@kernel.org wrote: > [Severity: High] > This isn't a bug introduced by this patch, but does this fix leave another > identical use-after-free and memory leak reachable from tracefs? > > If trigger registration fails in hist_register_trigger() after this .init() > function succeeds, the error propagates up without undoing it: Yes, and that one is already fixed. tracing_set_clock() is the only step in hist_register_trigger() that can fail after cmd_ops->init(), and this: https://lore.kernel.org/linux-trace-kernel/20260907091415.554535-1-donggeunyoo.kernel@gmail.com/ moves it above the init, so nothing which can fail runs after the trigger is published. This series is based on v7.3-rc2, without that patch. > [Severity: Medium] > This is a pre-existing issue, but does ignoring the return value of > save_named_trigger() break histogram sharing? Yes. On a kstrdup() failure the trigger keeps running with data->name NULL and off the list, so find_named_trigger() cannot see it, a later trigger of the same name builds its own map instead of sharing, and pause_named_trigger() misses it. Memory safety is not affected. trigger_data_alloc() runs INIT_LIST_HEAD(&trigger_data->named_list), so the unconditional del_named_trigger() in event_hist_trigger_named_free() deletes a self-linked entry and kfree()s a NULL name. Not addressed by this series. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger 2026-09-07 12:44 ` [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger Donggeun Yoo [not found] ` <20260907125934.5C6261F00A3E@smtp.kernel.org> @ 2026-09-07 21:01 ` Tom Zanussi 1 sibling, 0 replies; 7+ messages in thread From: Tom Zanussi @ 2026-09-07 21:01 UTC (permalink / raw) To: Donggeun Yoo, Steven Rostedt, Masami Hiramatsu Cc: Mathieu Desnoyers, linux-trace-kernel, linux-kernel On Mon, 2026-09-07 at 21:44 +0900, Donggeun Yoo wrote: > event_hist_trigger_named_init() puts the trigger on the global > named_triggers list and only then takes the reference on the trigger it > shares its histogram with: > > data->ref++; > > save_named_trigger(data->named_data->name, data); > > ret = event_hist_trigger_init(data->named_data); > if (ret < 0) { > kfree(data->cmd_ops); > data->cmd_ops = &trigger_hist_cmd; > } > > return ret; > > event_hist_trigger_init() fails when alloc_hist_pad() cannot allocate, and > nothing takes the trigger back off the list on the way out. > event_hist_trigger_parse() frees it, and the next lookup by name reads the > freed object: > > BUG: KASAN: slab-use-after-free in find_named_trigger+0xac/0xc0 > Read of size 8 at addr ffff888009346860 by task init/1 > find_named_trigger+0xac/0xc0 > hist_register_trigger+0xc1/0xa00 > event_hist_trigger_parse+0x3146/0x6af0 > event_trigger_write+0xce/0x160 > Freed by task 67: > kfree+0x154/0x420 > trigger_kthread_fn+0xfd/0x160 > > Do the reference first and publish once it has succeeded, so that nothing > which can fail runs after the trigger becomes findable. > > Reported-by: Sashiko AI <sashiko-bot@kernel.org> > Closes: https://lore.kernel.org/linux-trace-kernel/20260907092944.3950E1F00A3D@smtp.kernel.org/ > Fixes: 7ab0fc61ce73 ("tracing: Move histogram trigger variables from stack to per CPU structure") > Cc: stable@vger.kernel.org > Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com> > --- > kernel/trace/trace_events_hist.c | 11 ++++++----- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c > index 963e0d6b61fd..c6c04926bdf0 100644 > --- a/kernel/trace/trace_events_hist.c > +++ b/kernel/trace/trace_events_hist.c > @@ -6383,17 +6383,18 @@ static int event_hist_trigger_named_init(struct event_trigger_data *data) > { > int ret; > > - data->ref++; > - > - save_named_trigger(data->named_data->name, data); > - > ret = event_hist_trigger_init(data->named_data); > if (ret < 0) { > kfree(data->cmd_ops); > data->cmd_ops = &trigger_hist_cmd; > + return ret; > } > > - return ret; > + data->ref++; > + > + save_named_trigger(data->named_data->name, data); > + > + return 0; > } > Makes sense. Note that save_named_trigger() can also fail with -ENOMEM, but maybe that's a separate patch.. Acked-by: Tom Zanussi <zanussi@kernel.org> > static void event_hist_trigger_named_free(struct event_trigger_data *data) > > base-commit: df2908090cda368b01ff43709f51890076c56157 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] tracing: hist: undo the registration when enabling the trigger fails 2026-09-07 12:44 [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo 2026-09-07 12:44 ` [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger Donggeun Yoo @ 2026-09-07 12:44 ` Donggeun Yoo [not found] ` <20260907130105.94DD51F00A3D@smtp.kernel.org> 2026-09-10 1:10 ` [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo 2 siblings, 1 reply; 7+ messages in thread From: Donggeun Yoo @ 2026-09-07 12:44 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu Cc: Mathieu Desnoyers, Tom Zanussi, linux-trace-kernel, linux-kernel, donggeunyoo.kernel Commit 6f86bdeab633 ("tracing: Fix bad hist from corrupting named_triggers list") described how a trigger that is registered but not on file->triggers ends up freed while still on the global named_triggers list, and moved the registration down so that hist_trigger_enable() follows it immediately. One path still gets there. hist_trigger_enable() adds the trigger and takes it straight back out when the event cannot be enabled: list_add_tail_rcu(&data->list, &file->triggers); update_cond_flag(file); if (trace_event_trigger_enable_disable(file, 1) < 0) { list_del_rcu(&data->list); update_cond_flag(file); ret--; } so the list walk in hist_unregister_trigger() matches nothing, test stays NULL, and the ->free() that would call del_named_trigger() is skipped. out_unreg falls through to out_free, which frees the trigger anyway: BUG: KASAN: slab-use-after-free in find_named_trigger+0xac/0xc0 Read of size 8 at addr ffff8880091d3160 by task init/1 find_named_trigger+0xac/0xc0 hist_register_trigger+0xc1/0xa00 event_hist_trigger_parse+0x3146/0x6af0 event_trigger_write+0xce/0x160 Freed by task 69: kfree+0x154/0x420 trigger_kthread_fn+0xfd/0x160 Leave the trigger where hist_unregister_trigger() can find it and let that undo the registration, which is the only code that knows all of what cmd_ops->init() took: the named list entry, the hist_pad reference, the reference on the trigger a named histogram is shared with, and the copied cmd_ops. It also pairs the failed trace_event_trigger_enable_disable(), whose sm_ref and buffered event reference are otherwise left behind. Since ->free() releases trigger_data and, for a trigger that does not share its histogram, hist_data with it, out_unreg can no longer fall through to out_free. For a trigger that does share, hist_register_trigger() has already destroyed the caller's hist_data, so the fall-through was reading freed memory there as well. Move the enable_timestamps check in hist_unregister_trigger() above the ->free() call for the same reason: hist_data does not outlive it once the trigger being removed is the one that owns it. Reported-by: Sashiko AI <sashiko-bot@kernel.org> Closes: https://lore.kernel.org/linux-trace-kernel/20260907092944.3950E1F00A3D@smtp.kernel.org/ Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers") Cc: stable@vger.kernel.org Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com> --- kernel/trace/trace_events_hist.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index c6c04926bdf0..1de224a5a2bb 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -6679,11 +6679,12 @@ static int hist_trigger_enable(struct event_trigger_data *data, update_cond_flag(file); - if (trace_event_trigger_enable_disable(file, 1) < 0) { - list_del_rcu(&data->list); - update_cond_flag(file); + /* + * On failure the caller undoes the registration, and + * hist_unregister_trigger() can only find the trigger here. + */ + if (trace_event_trigger_enable_disable(file, 1) < 0) ret--; - } return ret; } @@ -6761,13 +6762,13 @@ static void hist_unregister_trigger(char *glob, } } - if (test && test->cmd_ops->free) - test->cmd_ops->free(test); - if (hist_data->enable_timestamps) { if (!hist_data->remove || test) tracing_set_filter_buffering(file->tr, false); } + + if (test && test->cmd_ops->free) + test->cmd_ops->free(test); } static bool hist_file_check_refs(struct trace_event_file *file) @@ -6972,6 +6973,8 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops, return ret; out_unreg: event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); + /* The unregister frees trigger_data, skip out_free */ + goto out; out_free: remove_hist_vars(hist_data); -- 2.53.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <20260907130105.94DD51F00A3D@smtp.kernel.org>]
* Re: [PATCH 2/2] tracing: hist: undo the registration when enabling the trigger fails [not found] ` <20260907130105.94DD51F00A3D@smtp.kernel.org> @ 2026-09-07 13:13 ` Donggeun Yoo 0 siblings, 0 replies; 7+ messages in thread From: Donggeun Yoo @ 2026-09-07 13:13 UTC (permalink / raw) To: sashiko-reviews Cc: Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, linux-trace-kernel, linux-kernel, donggeunyoo.kernel On Mon, Sep 07, 2026 at 01:01:05PM +0000, sashiko-bot@kernel.org wrote: > [Severity: High] > This is a pre-existing issue, but missing cleanup in the error path before > this label can lead to a use-after-free on the global named_triggers list. > > When hist_register_trigger() fails after successfully executing > data->cmd_ops->init(data), it returns a negative error code without undoing > the initialization. For instance, if tracing_set_clock() fails due to an > invalid clock name: Same one as on patch 1, answered there: https://lore.kernel.org/linux-trace-kernel/20260907125934.5C6261F00A3E@smtp.kernel.org/ It is fixed by a separate patch that moves tracing_set_clock() above the init, which this series is not based on. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger 2026-09-07 12:44 [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo 2026-09-07 12:44 ` [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger Donggeun Yoo 2026-09-07 12:44 ` [PATCH 2/2] tracing: hist: undo the registration when enabling the trigger fails Donggeun Yoo @ 2026-09-10 1:10 ` Donggeun Yoo 2 siblings, 0 replies; 7+ messages in thread From: Donggeun Yoo @ 2026-09-10 1:10 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu Cc: Mathieu Desnoyers, Tom Zanussi, linux-trace-kernel, linux-kernel, sashiko-reviews, donggeunyoo.kernel The Sashiko AI reviewer reported these bugs before I sent the patches, in its review of "tracing: hist: set the trace clock before registering the trigger". Both patches should carry: Reported-by: sashiko-bot@kernel.org Closes: https://lore.kernel.org/linux-trace-kernel/20260907092944.3950E1F00A3D@smtp.kernel.org/ No change to the patches themselves. Thanks, Donggeun ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-10 1:10 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-07 12:44 [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo
2026-09-07 12:44 ` [PATCH 1/2] tracing: hist: take the reference before publishing the named trigger Donggeun Yoo
[not found] ` <20260907125934.5C6261F00A3E@smtp.kernel.org>
2026-09-07 13:13 ` Donggeun Yoo
2026-09-07 21:01 ` Tom Zanussi
2026-09-07 12:44 ` [PATCH 2/2] tracing: hist: undo the registration when enabling the trigger fails Donggeun Yoo
[not found] ` <20260907130105.94DD51F00A3D@smtp.kernel.org>
2026-09-07 13:13 ` Donggeun Yoo
2026-09-10 1:10 ` [PATCH 0/2] tracing: hist: two named trigger error paths that free a published trigger Donggeun Yoo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®