From: Kyle Zeng <kylebot@openai.com>
To: linux-trace-kernel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, rostedt@goodmis.org,
mhiramat@kernel.org, outbounddisclosures@openai.com,
Kyle Zeng <kylebot@openai.com>,
stable@vger.kernel.org
Subject: [PATCH] tracing/filters: Treat zero-length dynamic strings as empty
Date: Tue, 6 Oct 2026 15:56:42 -0700 [thread overview]
Message-ID: <20261006225642.58778-1-kylebot@openai.com> (raw)
The regex callbacks use a length of zero for NUL-terminated strings of
unknown size, such as the trailing buffer in a trace_marker record.
However, filter_pred_strloc() and filter_pred_strrelloc() pass the length
from a data locator directly to those callbacks. A zero-length locator
has no data and need not point at a NUL byte.
In particular, syscall entry events can contain an empty captured array
or a failed user-string copy. Matching such a field with an equality,
prefix, or substring filter can read beyond the record. The per-CPU perf
trace buffer is reused, so an unprivileged counting syscall event can
disclose bytes left by a previous kernel tracepoint even when raw
sampling is denied and exclude_kernel prevents counting that tracepoint.
Handle both locator formats through a common helper. For a zero-length
field, pass an empty string and its actual size to the regex callback.
This gives all matching modes the empty-string semantics without reading
the locator's target. Keep nonzero fields and the legacy trace_marker
unknown-length convention unchanged.
Fixes: 10f20e9f9da9 ("tracing: Have zero size length in filter logic be full string")
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 | 38 +++++++++++++++++++-----------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 2b46ca536045..02aaa92e0361 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -884,6 +884,25 @@ static int filter_pred_pchar_user(struct filter_pred *pred, void *event)
return filter_pchar(pred, str);
}
+static __always_inline int filter_dyn_string(struct filter_pred *pred,
+ char *str, int len)
+{
+ int cmp;
+
+ /*
+ * The regex callbacks use zero for an unknown-length, NUL-terminated
+ * string. A zero-length data_loc or rel_loc field has no bytes at all.
+ * Match an empty string instead of reading past the end of the field.
+ */
+ if (!len) {
+ str = "";
+ len = 1;
+ }
+
+ cmp = pred->regex->match(str, pred->regex, len);
+ return cmp ^ pred->not;
+}
+
/*
* Filter predicate for dynamic sized arrays of characters.
* These are implemented through a list of strings at the end
@@ -900,13 +919,8 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event)
int str_loc = str_item & 0xffff;
int str_len = str_item >> 16;
char *addr = (char *)(event + str_loc);
- int cmp, match;
-
- cmp = pred->regex->match(addr, pred->regex, str_len);
- match = cmp ^ pred->not;
-
- return match;
+ return filter_dyn_string(pred, addr, str_len);
}
/*
@@ -923,13 +937,8 @@ static int filter_pred_strrelloc(struct filter_pred *pred, void *event)
int str_loc = str_item & 0xffff;
int str_len = str_item >> 16;
char *addr = (char *)(&item[1]) + str_loc;
- int cmp, match;
-
- cmp = pred->regex->match(addr, pred->regex, str_len);
- match = cmp ^ pred->not;
-
- return match;
+ return filter_dyn_string(pred, addr, str_len);
}
/* Filter predicate for CPUs. */
@@ -1014,7 +1023,8 @@ static int filter_pred_function(struct filter_pred *pred, void *event)
*
* @str: the string to be searched
* @r: the regex structure containing the pattern string
- * @len: the length of the string to be searched (including '\0')
+ * @len: the length of the string to be searched (including '\0'), or zero
+ * for a NUL-terminated string of unknown length
*
* Note:
* - @str might not be NULL-terminated if it's of type DYN_STRING
@@ -1023,7 +1033,7 @@ static int filter_pred_function(struct filter_pred *pred, void *event)
static int regex_match_full(char *str, struct regex *r, int len)
{
- /* len of zero means str is dynamic and ends with '\0' */
+ /* Zero is reserved for a NUL-terminated string of unknown length. */
if (!len)
return strcmp(str, r->pattern) == 0;
next reply other threads:[~2026-10-06 22:56 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 22:56 Kyle Zeng [this message]
2026-10-07 4:19 ` [PATCH] tracing/filters: Treat zero-length dynamic strings as empty Masami Hiramatsu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261006225642.58778-1-kylebot@openai.com \
--to=kylebot@openai.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=outbounddisclosures@openai.com \
--cc=rostedt@goodmis.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.