* [PATCH] tracing: Reject incomplete event filter expressions
@ 2026-10-23 17:46 Kyle Zeng
2026-10-23 23:05 ` Masami Hiramatsu
0 siblings, 1 reply; 2+ messages in thread
From: Kyle Zeng @ 2026-10-23 17:46 UTC (permalink / raw)
To: linux-trace-kernel
Cc: linux-kernel, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Kyle Zeng, stable
A non-empty expression normally finishes in predicate_parse()'s inner
loop, which resolves the pending logical operators before jumping to
finalization. If the input ends after an operator, possibly followed by
unary '!' tokens, the outer loop instead falls through with unresolved
operator state.
For example, "common_pid == 1 || common_pid == 2 &&" leaves
prog[0].target equal to -1. The second pass then reads prog[-1] before
the forward-jump check can reject it. Depending on adjacent slab
contents, it can also copy an out-of-bounds word into a branch target
that passes the forward-only check. A self-targeted perf tracepoint
counting event can reach this path through PERF_EVENT_IOC_SET_FILTER.
Reject the outer-loop fallthrough when a predicate has already been
parsed. This ensures that non-empty expressions only reach finalization
after the inner loop has resolved their operators. Keep the existing
no-filter error for input that has no predicates. Add a regression test
for trailing logical operators and unary negations.
Fixes: 80765597bc587 ("tracing: Rewrite filter logic to be simpler and faster")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-6-astra
Signed-off-by: Kyle Zeng <kylebot@openai.com>
---
kernel/trace/trace_events_filter.c | 6 +++++
.../test.d/filter/event-filter-incomplete.tc | 24 +++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 2b46ca536045..405651be9c93 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -596,6 +596,12 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
top--; /* #12 */
}
}
+ /* Only the inner loop can complete a non-empty expression. */
+ if (N) {
+ ret = -EINVAL;
+ parse_error(pe, FILT_ERR_INVALID_FILTER, ptr - str);
+ goto out_free;
+ }
out:
if (top != op_stack) {
/* Too many '(' */
diff --git a/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc b/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
new file mode 100644
index 000000000000..cc6df762845f
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
@@ -0,0 +1,24 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: event filter - reject incomplete logical expressions
+# requires: events/sched/sched_switch/filter
+# flags: instance
+
+filter=events/sched/sched_switch/filter
+
+for base in \
+ 'common_pid == 1' \
+ 'common_pid == 1 || common_pid == 2' \
+ 'common_pid == 1 && common_pid == 2' \
+ '!(common_pid == 1 || common_pid == 2)'
+do
+ printf '%s' "$base" > "$filter"
+ for tail in '&&' '||' '&& !' '|| !' '&& !! ' '|| !! '; do
+ if printf '%s' "$base $tail" > "$filter" 2>/dev/null; then
+ echo "Accepted incomplete filter: $base $tail"
+ exit_fail
+ fi
+ done
+done
+
+echo 0 > "$filter"
base-commit: fd179f8a05be3ccae366b9b96e176b51fbe54aab
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] tracing: Reject incomplete event filter expressions
2026-10-23 17:46 [PATCH] tracing: Reject incomplete event filter expressions Kyle Zeng
@ 2026-10-23 23:05 ` Masami Hiramatsu
0 siblings, 0 replies; 2+ messages in thread
From: Masami Hiramatsu @ 2026-10-23 23:05 UTC (permalink / raw)
To: Kyle Zeng
Cc: linux-trace-kernel, linux-kernel, Steven Rostedt, Mathieu Desnoyers
On Fri, 23 Oct 2026 10:46:20 -0700, Kyle Zeng <kylebot@openai.com> wrote:
> A non-empty expression normally finishes in predicate_parse()'s inner
> loop, which resolves the pending logical operators before jumping to
> finalization. If the input ends after an operator, possibly followed by
> unary '!' tokens, the outer loop instead falls through with unresolved
> operator state.
>
> For example, "common_pid == 1 || common_pid == 2 &&" leaves
> prog[0].target equal to -1. The second pass then reads prog[-1] before
> the forward-jump check can reject it. Depending on adjacent slab
> contents, it can also copy an out-of-bounds word into a branch target
> that passes the forward-only check. A self-targeted perf tracepoint
> counting event can reach this path through PERF_EVENT_IOC_SET_FILTER.
>
> Reject the outer-loop fallthrough when a predicate has already been
> parsed. This ensures that non-empty expressions only reach finalization
> after the inner loop has resolved their operators. Keep the existing
> no-filter error for input that has no predicates. Add a regression test
> for trailing logical operators and unary negations.
>
Looks good to me.
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Thanks!
> Fixes: 80765597bc587 ("tracing: Rewrite filter logic to be simpler and faster")
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-6-astra
> Signed-off-by: Kyle Zeng <kylebot@openai.com>
> ---
> kernel/trace/trace_events_filter.c | 6 +++++
> .../test.d/filter/event-filter-incomplete.tc | 24 +++++++++++++++++++
> 2 files changed, 30 insertions(+)
> create mode 100644 tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
>
> diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
> index 2b46ca536045..405651be9c93 100644
> --- a/kernel/trace/trace_events_filter.c
> +++ b/kernel/trace/trace_events_filter.c
> @@ -596,6 +596,12 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
> top--; /* #12 */
> }
> }
> + /* Only the inner loop can complete a non-empty expression. */
> + if (N) {
> + ret = -EINVAL;
> + parse_error(pe, FILT_ERR_INVALID_FILTER, ptr - str);
> + goto out_free;
> + }
> out:
> if (top != op_stack) {
> /* Too many '(' */
> diff --git a/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc b/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
> new file mode 100644
> index 000000000000..cc6df762845f
> --- /dev/null
> +++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
> @@ -0,0 +1,24 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +# description: event filter - reject incomplete logical expressions
> +# requires: events/sched/sched_switch/filter
> +# flags: instance
> +
> +filter=events/sched/sched_switch/filter
> +
> +for base in \
> + 'common_pid == 1' \
> + 'common_pid == 1 || common_pid == 2' \
> + 'common_pid == 1 && common_pid == 2' \
> + '!(common_pid == 1 || common_pid == 2)'
> +do
> + printf '%s' "$base" > "$filter"
> + for tail in '&&' '||' '&& !' '|| !' '&& !! ' '|| !! '; do
> + if printf '%s' "$base $tail" > "$filter" 2>/dev/null; then
> + echo "Accepted incomplete filter: $base $tail"
> + exit_fail
> + fi
> + done
> +done
> +
> +echo 0 > "$filter"
>
> base-commit: fd179f8a05be3ccae366b9b96e176b51fbe54aab
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-23 23:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 17:46 [PATCH] tracing: Reject incomplete event filter expressions Kyle Zeng
2026-10-23 23:05 ` Masami Hiramatsu
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®