* [PATCH v2 0/2] tracing/user_events: validate dynamic field bounds @ 2026-11-03 2:45 Yifan Zhang 2026-11-03 2:45 ` [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size Yifan Zhang 2026-11-03 2:45 ` [PATCH v2 2/2] tracing/user_events: reject overflowing field offsets Yifan Zhang 0 siblings, 2 replies; 4+ messages in thread From: Yifan Zhang @ 2026-11-03 2:45 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu, linux-trace-kernel Cc: Mathieu Desnoyers, Beau Belgrave, linux-kernel These patches validate the size assumptions used by dynamic cpumask fields and prevent explicit structure sizes from wrapping field offsets. Changes in v2: - parse explicit structure sizes into a u32 and reject values above INT_MAX before assigning them to the signed size variable Patch 1 is unchanged. Yifan Zhang (2): tracing/user_events: validate dynamic cpumask size tracing/user_events: reject overflowing field offsets kernel/trace/trace_events_user.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) -- 2.39.5 (Apple Git-154) ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size 2026-11-03 2:45 [PATCH v2 0/2] tracing/user_events: validate dynamic field bounds Yifan Zhang @ 2026-11-03 2:45 ` Yifan Zhang 2026-11-04 21:39 ` Beau Belgrave 2026-11-03 2:45 ` [PATCH v2 2/2] tracing/user_events: reject overflowing field offsets Yifan Zhang 1 sibling, 1 reply; 4+ messages in thread From: Yifan Zhang @ 2026-11-03 2:45 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu, linux-trace-kernel Cc: Mathieu Desnoyers, Beau Belgrave, linux-kernel 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@stu.pku.edu.cn> --- 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 @@ static int user_event_add_field(struct user_event *user, const char *type, 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) ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size 2026-11-03 2:45 ` [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size Yifan Zhang @ 2026-11-04 21:39 ` Beau Belgrave 0 siblings, 0 replies; 4+ messages in thread From: Beau Belgrave @ 2026-11-04 21:39 UTC (permalink / raw) To: Yifan Zhang Cc: Steven Rostedt, Masami Hiramatsu, linux-trace-kernel, Mathieu Desnoyers, linux-kernel On Tue, Nov 03, 2026 at 10:45:19AM +0800, Yifan Zhang wrote: > 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 Hey Yifan, In the V1 there was a repro case where this value was a __data_loc, which defines where the actual data (and it's size) is in the payload. There isn't a type min-size requirement when __data_loc is used, this seems like the bug resides possibly in filter_match_preds for __data_loc cases? See comments futher down. Steve, do you think this is the case? If not, then I guess we would have to validate min-size requirements of all types in the dynamic case, and I hope we could do that centrally to avoid fixing these in various spots. > 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@stu.pku.edu.cn> > --- > 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 @@ static int user_event_add_field(struct user_event *user, const char *type, > if (strstr(type, "char") != NULL) > validator_flags |= VALIDATOR_ENSURE_NULL; > > + if (strstr(type, "cpumask_t")) > + validator_flags |= VALIDATOR_CPUMASK; > + You can only get to this case if you put struct, __rel_loc, or __data_loc. Those have their own size requirements and are dynamic in nature, IE: Each write describes the actual size in the __rel_loc and __data_loc cases, and statically for the struct case. user_field_size() checks if a type name has a known size, if not, it gets rejected. The only time this isn't the case is if you put struct in front and then have to give a size that's expected. The other case is if you put __data_loc or __rel_loc, both require the payload to dynamically have a size associated. In the dynamic case, the filter should be ensuring these values are minimally sized. > 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) Thanks, -Beau ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] tracing/user_events: reject overflowing field offsets 2026-11-03 2:45 [PATCH v2 0/2] tracing/user_events: validate dynamic field bounds Yifan Zhang 2026-11-03 2:45 ` [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size Yifan Zhang @ 2026-11-03 2:45 ` Yifan Zhang 1 sibling, 0 replies; 4+ messages in thread From: Yifan Zhang @ 2026-11-03 2:45 UTC (permalink / raw) To: Steven Rostedt, Masami Hiramatsu, linux-trace-kernel Cc: Mathieu Desnoyers, Beau Belgrave, linux-kernel user_event_parse_field() accepts large structure sizes but accumulates field offsets in a u32 before storing them in signed int fields. A declaration can wrap the recorded minimum event size while a fixed-width field retains an offset outside the accepted record. A short write is then accepted and a field filter reads 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 Parse an explicit structure size into a u32, reject values greater than INT_MAX before converting them to int, and use checked addition for the resulting field offset. This prevents both signed conversion and offset overflow from bypassing the downstream bounds checks. Fixes: 7f5a08c79df3 ("user_events: Add minimal support for trace_event into ftrace") Signed-off-by: Yifan Zhang <yfzhang23@stu.pku.edu.cn> --- kernel/trace/trace_events_user.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index 85938b45b7618..04eef4865490b 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -1207,6 +1207,7 @@ static int user_event_parse_field(char *field, struct user_event *user, { char *part, *type, *name; u32 depth = 0, saved_offset = *offset; + u32 new_offset, struct_size; int len, size = -EINVAL; bool is_struct = false; @@ -1267,8 +1268,11 @@ static int user_event_parse_field(char *field, struct user_event *user, if (!is_struct) return -EINVAL; - if (kstrtou32(part, 10, &size)) + if (kstrtou32(part, 10, &struct_size)) return -EINVAL; + if (struct_size > INT_MAX) + return -E2BIG; + size = struct_size; break; default: return -EINVAL; @@ -1287,7 +1291,11 @@ static int user_event_parse_field(char *field, struct user_event *user, if (size < 0) return size; - *offset = saved_offset + size; + if (check_add_overflow(saved_offset, (u32)size, &new_offset) || + new_offset > INT_MAX) + return -E2BIG; + + *offset = new_offset; return user_event_add_field(user, type, name, saved_offset, size, type[0] != 'u', FILTER_OTHER); -- 2.39.5 (Apple Git-154) ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-04 21:39 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-03 2:45 [PATCH v2 0/2] tracing/user_events: validate dynamic field bounds Yifan Zhang 2026-11-03 2:45 ` [PATCH v2 1/2] tracing/user_events: validate dynamic cpumask size Yifan Zhang 2026-11-04 21:39 ` Beau Belgrave 2026-11-03 2:45 ` [PATCH v2 2/2] tracing/user_events: reject overflowing field offsets Yifan Zhang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox