* [for-linus][PATCH 0/3] tracing: More fixes for v7.3
@ 2026-10-16 13:32 Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 1/3] tracing: Fix crash in print_graph_function_event() Steven Rostedt
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Steven Rostedt @ 2026-10-16 13:32 UTC (permalink / raw)
To: linux-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Hao Ge, Taeyang Lee
tracing fixes for v7.3:
- Fix a crash in print_graph_function_event()
When a tracer does not define static or default flags the
tr->current_trace_flags is set to NULL. If the ring buffer is
not cleared when switching tracers, the previous tracers events
could be read. The function_graph entries will dereference the
tr->current_trace_flags and cause a crash.
Set the tr->current_trace_flags to a empty set of flags to prevent
it from being NULL.
- Separate tracing filter predicate count from allocation
The amount allocated for the predicate program is the number of predicates
defined plus two for adding "true" and "false" at the end. The nr_preds is
incremented by two to accommodate the booleans but is then used as the
limit check for number of predicates. This is incorrect as it is now two
higher than what is expected.
Use a separate variable for the size of the predicate array.
- Fix the filter operator stack check
The operator stack increments the pointer and then writes the content onto
the stack. The check for overflow compared the current pointer to see if
it was greater than the stack size before doing so. This is an off by 2
error as the write will be at the size - 1 and the compare is done before
the increment. Adjust the check accordingly.
git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
trace/fixes
Head SHA1: c47a7b11bcb3d45e29723afcf6336866476b1d08
Hao Ge (1):
tracing: Fix crash in print_graph_function_event()
Taeyang Lee (2):
tracing: Keep the predicate limit separate from program capacity
tracing: Check operator stack capacity before pushing
----
kernel/trace/trace.c | 20 ++++++++++++++++++--
kernel/trace/trace_events_filter.c | 9 ++++-----
2 files changed, 22 insertions(+), 7 deletions(-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* [for-linus][PATCH 1/3] tracing: Fix crash in print_graph_function_event()
2026-10-16 13:32 [for-linus][PATCH 0/3] tracing: More fixes for v7.3 Steven Rostedt
@ 2026-10-16 13:32 ` Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 2/3] tracing: Keep the predicate limit separate from program capacity Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 3/3] tracing: Check operator stack capacity before pushing Steven Rostedt
2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2026-10-16 13:32 UTC (permalink / raw)
To: linux-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
stable, Hao Ge
From: Hao Ge <hao.ge@linux.dev>
tracing_set_tracer() assigns the flags of the newly selected tracer
with:
tr->current_trace_flags = t->flags ? : t->tracer->flags;
If the new tracer defines neither static flags nor default flags, like
hwlat, irqsoff or wakeup, add_tracer() has no per instance flags copy
for it, and both operands are NULL, so tr->current_trace_flags ends up
being NULL as well.
The ring buffer is not cleared when switching tracers: it is reset
inside tracer_init(), after current_trace_flags was already assigned.
If the buffer still holds function_graph entries of the previous
tracer, printing one of them dereferences the NULL pointer. This was
hit by cat trace during an ftrace stress test:
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor read access in kernel mode
RIP: 0010:print_graph_function_event+0xe/0x20
Call Trace:
s_show+0x4d/0x110
seq_read_iter+0x2d4/0x490
seq_read+0x130/0x170
vfs_read+0xb5/0x370
ksys_read+0x6d/0xe0
do_syscall_64+0xbc/0x450
The snapshot buffer is not reset at all, so this can be reproduced
without a race:
echo function_graph > /sys/kernel/tracing/current_tracer
echo 1 > /sys/kernel/tracing/snapshot
echo hwlat > /sys/kernel/tracing/current_tracer
cat /sys/kernel/tracing/snapshot
Rather than teaching every user of tr->current_trace_flags about this
corner case, make sure it is never NULL: when the newly selected
tracer has no flags at all, tracing_set_tracer() falls back to a
static empty no_tracer_flags. run_tracer_selftest() can hit the same
case, so the same fallback is added there too. The existing users
already handle opts == NULL, so these tracers keep behaving as before.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261015130658.221198-1-hao.ge@linux.dev
Fixes: e29aa918a928 ("tracing: Have function graph tracer define options per instance")
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Hao Ge <hao.ge@linux.dev>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
kernel/trace/trace.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3b22e70c6016..97a058623f94 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -99,6 +99,12 @@ struct tracers {
struct tracer_flags *flags;
};
+/*
+ * Tracers that do not define their own flags use these empty flags,
+ * as tr->current_trace_flags must never be NULL.
+ */
+static struct tracer_flags no_tracer_flags;
+
/*
* To prevent the comm cache from being overwritten when no
* tracing is active, only save the comm when a trace event
@@ -1318,7 +1324,12 @@ static int run_tracer_selftest(struct tracer *type)
tracing_reset_online_cpus(&tr->array_buffer);
tr->current_trace = type;
- tr->current_trace_flags = type->flags ? : type->default_flags;
+ if (type->flags)
+ tr->current_trace_flags = type->flags;
+ else if (type->default_flags)
+ tr->current_trace_flags = type->default_flags;
+ else
+ tr->current_trace_flags = &no_tracer_flags;
#ifdef CONFIG_TRACER_MAX_TRACE
if (tracer_uses_snapshot(type)) {
@@ -5089,7 +5100,12 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf)
return ret;
}
- tr->current_trace_flags = t->flags ? : t->tracer->flags;
+ if (t->flags)
+ tr->current_trace_flags = t->flags;
+ else if (t->tracer->flags)
+ tr->current_trace_flags = t->tracer->flags;
+ else
+ tr->current_trace_flags = &no_tracer_flags;
if (trace->init) {
ret = tracer_init(trace, tr);
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [for-linus][PATCH 2/3] tracing: Keep the predicate limit separate from program capacity
2026-10-16 13:32 [for-linus][PATCH 0/3] tracing: More fixes for v7.3 Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 1/3] tracing: Fix crash in print_graph_function_event() Steven Rostedt
@ 2026-10-16 13:32 ` Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 3/3] tracing: Check operator stack capacity before pushing Steven Rostedt
2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2026-10-16 13:32 UTC (permalink / raw)
To: linux-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
stable, Taeyang Lee
From: Taeyang Lee <0wn@theori.io>
predicate_parse() adds two to nr_preds to reserve the terminal TRUE
and FALSE entries. It also uses that increased value as the limit for
parsed predicates. If the initial count is smaller than the number
actually parsed, the program can fill the allocation and subsequent
accesses can go past its end.
Keep nr_preds as the predicate limit and use a separate value for the
allocation size. This leaves space for both terminal entries and a
zeroed entry when parsing stops at the limit.
Cc: stable@vger.kernel.org
Fixes: 39f7c41c908b ("tracing/filters: Enable filtering a cpumask field by another cpumask")
Link: https://patch.msgid.link/atELCd1XjKVhrkFL@Taeyangs-MacBook-Pro.local
Signed-off-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
kernel/trace/trace_events_filter.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 2b46ca536045..781416ba6bdf 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -482,18 +482,17 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
int len;
int N = 0;
int i;
-
- nr_preds += 2; /* For TRUE and FALSE */
+ int nr_preds_alloc = nr_preds + 2; /* For TRUE and FALSE */
op_stack = kmalloc_objs(*op_stack, nr_parens);
if (!op_stack)
return ERR_PTR(-ENOMEM);
- prog_stack = kzalloc_objs(*prog_stack, nr_preds);
+ prog_stack = kzalloc_objs(*prog_stack, nr_preds_alloc);
if (!prog_stack) {
parse_error(pe, -ENOMEM, 0);
goto out_free;
}
- inverts = kmalloc_array(nr_preds, sizeof(*inverts), GFP_KERNEL);
+ inverts = kmalloc_array(nr_preds_alloc, sizeof(*inverts), GFP_KERNEL);
if (!inverts) {
parse_error(pe, -ENOMEM, 0);
goto out_free;
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [for-linus][PATCH 3/3] tracing: Check operator stack capacity before pushing
2026-10-16 13:32 [for-linus][PATCH 0/3] tracing: More fixes for v7.3 Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 1/3] tracing: Fix crash in print_graph_function_event() Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 2/3] tracing: Keep the predicate limit separate from program capacity Steven Rostedt
@ 2026-10-16 13:32 ` Steven Rostedt
2 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2026-10-16 13:32 UTC (permalink / raw)
To: linux-kernel
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
stable, Taeyang Lee
From: Taeyang Lee <0wn@theori.io>
predicate_parse() uses the first operator stack entry before processing
any opening parentheses. A push then increments top before writing.
The existing check still permits that write when top already points to
the last allocated entry, which can access beyond the operator stack.
Reject the push when top reaches the last allocated entry.
Cc: stable@vger.kernel.org
Fixes: 39f7c41c908b ("tracing/filters: Enable filtering a cpumask field by another cpumask")
Link: https://patch.msgid.link/atELO9L0I9kg5CpC@Taeyangs-MacBook-Pro.local
Signed-off-by: Taeyang Lee <0wn@theori.io>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
kernel/trace/trace_events_filter.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 781416ba6bdf..127880ebe83f 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -511,7 +511,7 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
switch (*next) {
case '(': /* #2 */
- if (top - op_stack > nr_parens) {
+ if (top - op_stack >= nr_parens - 1) {
ret = -EINVAL;
goto out_free;
}
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-16 13:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-16 13:32 [for-linus][PATCH 0/3] tracing: More fixes for v7.3 Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 1/3] tracing: Fix crash in print_graph_function_event() Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 2/3] tracing: Keep the predicate limit separate from program capacity Steven Rostedt
2026-10-16 13:32 ` [for-linus][PATCH 3/3] tracing: Check operator stack capacity before pushing Steven Rostedt
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®