[PATCH v2 1/9] tracing/filters: Fix MATCH_END_ONLY regex matching for fixed-size strings

From: Masami Hiramatsu (Google)

Date: Sun Oct 25 2026 - 04:37:45 EST


From: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>

regex_match_end() calculated string length as "len - 1", assuming @len is
the string length including trailing '\0'. However, for fixed-size string
fields, filter_pred_string() passes field->size as @len, and for "comm",
filter_pred_comm() passes TASK_COMM_LEN as @len.

Because @len in these cases represents the buffer capacity rather than the
actual length of the string, regex_match_end() tests against the tail of
the buffer (typically trailing '\0' padding) rather than the end of the
string. Furthermore, if @len is 0 (denoting an empty dynamic array without
trailing '\0'), "len - 1" underflows to -1.

First check "len < r->len" and return 0, which safely rejects negative
lengths and cases where the buffer capacity is smaller than the pattern.
Then compute the actual string length using strnlen(str, len), which
bounds the scan by @len (stopping at the first '\0') without dereferencing
past the buffer.

Fixes: a3291c14ecf0 ("tracing/filters: Fix MATCH_END_ONLY filter matching")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@xxxxxxxxxx>
---
Changes in v2:
- Check "len < r->len" to guard against negative lengths and avoid
calling strnlen() when the buffer capacity is smaller than the pattern.
- Use strnlen(str, len) directly instead of calling strlen(str) when
len is 0, avoiding an out-of-bounds read on 0-length dynamic arrays.
---
kernel/trace/trace_events_filter.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 5e74d2dae40a..fac51a2953dd 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1075,10 +1075,14 @@ static int regex_match_middle(char *str, struct regex *r, int len)

static int regex_match_end(char *str, struct regex *r, int len)
{
- int strlen = len - 1;
+ int slen;

- if (strlen >= r->len &&
- memcmp(str + strlen - r->len, r->pattern, r->len) == 0)
+ if (len < r->len)
+ return 0;
+
+ slen = strnlen(str, len);
+ if (slen >= r->len &&
+ memcmp(str + slen - r->len, r->pattern, r->len) == 0)
return 1;
return 0;
}