[PATCH 1/2] tracing/user_events: validate dynamic cpumask size

From: Yifan Zhang

Date: Mon Nov 02 2026 - 07:48:32 EST


user_event_validate() checks that a dynamic field lies inside the event but
does not verify the minimum size required by its filter type. A one-byte
dynamic cpumask can therefore reach filter_pred_cpumask(), which consumes
cpumask_size() bytes beyond the event buffer.

KASAN reports:

BUG: KASAN: slab-use-after-free in filter_match_preds
Read of size 8
filter_match_preds
trace_event_buffer_commit
user_event_ftrace
user_events_write_core

Mark dynamic cpumask fields and reject locations shorter than
cpumask_size().

The patched kernel rejects the short event and accepts a full-size control
event without a KASAN report.

Fixes: 2467cda1b5c9 ("user_events: Validate user payloads for size and null termination")
Signed-off-by: Yifan Zhang <yfzhang23@xxxxxxxxxxxxxx>
---
kernel/trace/trace_events_user.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index f658c3a77aa7a..85938b45b7618 100644
--- a/kernel/trace/trace_events_user.c
+++ b/kernel/trace/trace_events_user.c
@@ -170,6 +170,7 @@ struct user_event_file_info {

#define VALIDATOR_ENSURE_NULL (1 << 0)
#define VALIDATOR_REL (1 << 1)
+#define VALIDATOR_CPUMASK BIT(2)

struct user_event_validator {
struct list_head user_event_link;
@@ -1159,6 +1160,9 @@ add_validator:
if (strstr(type, "char") != NULL)
validator_flags |= VALIDATOR_ENSURE_NULL;

+ if (strstr(type, "cpumask_t"))
+ validator_flags |= VALIDATOR_CPUMASK;
+
validator = kmalloc_obj(*validator, GFP_KERNEL_ACCOUNT);

if (!validator) {
@@ -1598,6 +1602,10 @@ static int user_event_validate(struct user_event *user, void *data, int len)
offset = loc & 0xffff;
size = loc >> 16;

+ if (unlikely((validator->flags & VALIDATOR_CPUMASK) &&
+ size < cpumask_size()))
+ return -EFAULT;
+
if (likely(validator->flags & VALIDATOR_REL))
pos += offset + sizeof(loc);
else
--
2.39.5 (Apple Git-154)