From 00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419 Mon Sep 17 00:00:00 2001 From: Raushan Patel Date: Fri, 24 Jul 2026 11:14:35 +0530 Subject: tracing/probes: Reject $arg0 in meta argument expansion traceprobe_expand_meta_args() parses $argN with simple_strtoul() and calls sprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is -1. Because ctx->nr_params is signed, the "idx >= nr_params" guard in sprint_nth_btf_arg() does not catch the negative index, and ctx->params[-1].name_off is read out of bounds. The normal per-argument path (parse_probe_vars()) already rejects $arg0 via its argument-number check, but meta-argument expansion runs before per-argument parsing and substitutes the value first, bypassing that check. Reject $arg0 explicitly during expansion. Link: https://lore.kernel.org/all/20260724054435.146279-1-raushan.jhon@gmail.com/ Fixes: 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args") Cc: stable@vger.kernel.org Signed-off-by: Raushan Patel Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index 506e6037e163..c8fd9b946f44 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c @@ -1901,7 +1901,11 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[], trace_probe_log_err(0, BAD_VAR); return ERR_PTR(-ENOENT); } - /* Note: $argN starts from $arg1 */ + /* Note: $argN starts from $arg1, so $arg0 is invalid. */ + if (n == 0) { + trace_probe_log_err(0, BAD_ARG_NUM); + return ERR_PTR(-EINVAL); + } ret = sprint_nth_btf_arg(n - 1, type, buf + used, bufsize - used, ctx); if (ret < 0) -- cgit v1.2.3 From aca0cd1bf16574327ef64f3178e5f5e37a61ef0b Mon Sep 17 00:00:00 2001 From: Raushan Patel Date: Fri, 24 Jul 2026 12:12:08 +0530 Subject: tracing/fprobe: Roll back on enable_trace_fprobe() failure enable_trace_fprobe() sets the file link or the TP_FLAG_PROFILE flag and then registers each trace_fprobe in the probe list. If __register_trace_fprobe() fails partway through, the function returns immediately without unregistering the trace_fprobes it already registered or undoing the file link / flag it set, leaving the event half-enabled and leaking the registered fprobe(s). enable_trace_kprobe() already handles this with a rollback path. Do the same for fprobe: on failure, unregister all probes and clear the file link or profile flag. Link: https://lore.kernel.org/all/20260724064208.480030-1-raushan.jhon@gmail.com/ Fixes: 334e5519c375 ("tracing/probes: Add fprobe events for tracing function entry and exit.") Cc: stable@vger.kernel.org Signed-off-by: Raushan Patel Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_fprobe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c index 9f5f08c0e7c2..3120403a5b60 100644 --- a/kernel/trace/trace_fprobe.c +++ b/kernel/trace/trace_fprobe.c @@ -1481,11 +1481,21 @@ static int enable_trace_fprobe(struct trace_event_call *call, list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) { ret = __register_trace_fprobe(tf); if (ret < 0) - return ret; + goto err; } } return 0; + +err: + /* Failed to enable one of them. Roll back all */ + list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) + __unregister_trace_fprobe(tf); + if (file) + trace_probe_remove_file(tp, file); + else + trace_probe_clear_flag(tp, TP_FLAG_PROFILE); + return ret; } /* -- cgit v1.2.3 From 8cf2f40ceb85047ad8a84dffae3bebc9fed18216 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 29 Jul 2026 08:27:33 +0900 Subject: fprobe: Fix module reference count leak on error in register_fprobe() In register_fprobe(), get_ips_from_filter() resolves target function addresses and increments module reference counts via try_module_get() for symbols in kernel modules. If get_ips_from_filter() fails on the second pass and returns an error, register_fprobe() returned directly without releasing module references acquired up to that point. Fix this by ensuring the cleanup loop executing module_put() runs even when get_ips_from_filter() returns a negative error. Link: https://lore.kernel.org/all/178528125360.101985.4144133640239273153.stgit@devnote2/ Fixes: d24fa977eec5 ("tracing: fprobe: Fix to lock module while registering fprobe") Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/fprobe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index f215990b9061..f681015413b8 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -961,10 +961,8 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter return -ENOMEM; ret = get_ips_from_filter(filter, notfilter, addrs, mods, num); - if (ret < 0) - return ret; - - ret = register_fprobe_ips(fp, addrs, ret); + if (ret >= 0) + ret = register_fprobe_ips(fp, addrs, ret); for (int i = 0; i < num; i++) { if (mods[i]) -- cgit v1.2.3 From c786d2bdf1f3964deee192ad942dee2a741c1e2c Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Tue, 28 Jul 2026 21:49:51 +0900 Subject: tracing/mmiotrace: Reset dropped_count in mmio_reset_data() mmio_reset_data() is called during tracer initialization, reset, and start. While it resets overrun_detected and prev_overruns, it neglects to reset dropped_count. Consequently, dropped event counts from prior tracing sessions persist in dropped_count and corrupt overrun reports in subsequent runs. Fix this by explicitly calling atomic_set(&dropped_count, 0) in mmio_reset_data(). Link: https://patch.msgid.link/178524299122.56416.16277704230639425172.stgit@devnote2 Fixes: 173ed24ee2d6 ("mmiotrace: count events lost due to not recording") Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_mmiotrace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index b88b8d9923ad..e064ba3f28cb 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c @@ -29,6 +29,7 @@ static void mmio_reset_data(struct trace_array *tr) { overrun_detected = false; prev_overruns = 0; + atomic_set(&dropped_count, 0); tracing_reset_online_cpus(&tr->array_buffer); } -- cgit v1.2.3 From 12b80cdbc54cf615b4717a4e8180063408091ea2 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Tue, 28 Jul 2026 21:50:00 +0900 Subject: tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions mmio_trace_rw() and mmio_trace_mapping() retrieve mmio_trace_array into tr and pass it to __trace_mmiotrace_rw() and __trace_mmiotrace_map(). If these functions are invoked while mmio_trace_array is NULL (e.g. before initialization or after disabled), accessing tr->array_buffer.buffer will result in a NULL pointer dereference crash. Fix this by adding an explicit NULL check for tr at the beginning of __trace_mmiotrace_rw() and __trace_mmiotrace_map(). Link: https://patch.msgid.link/178524300062.56416.8362487250709962380.stgit@devnote2 Fixes: f984b51e0779 ("ftrace: add mmiotrace plugin") Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_mmiotrace.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index e064ba3f28cb..df8692c2dea8 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c @@ -294,11 +294,15 @@ device_initcall(init_mmio_trace); static void __trace_mmiotrace_rw(struct trace_array *tr, struct mmiotrace_rw *rw) { - struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_buffer *buffer; struct ring_buffer_event *event; struct trace_mmiotrace_rw *entry; unsigned int trace_ctx; + if (!tr) + return; + + buffer = tr->array_buffer.buffer; trace_ctx = tracing_gen_ctx_flags(0); event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_RW, sizeof(*entry), trace_ctx); @@ -321,11 +325,15 @@ void mmio_trace_rw(struct mmiotrace_rw *rw) static void __trace_mmiotrace_map(struct trace_array *tr, struct mmiotrace_map *map) { - struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_buffer *buffer; struct ring_buffer_event *event; struct trace_mmiotrace_map *entry; unsigned int trace_ctx; + if (!tr) + return; + + buffer = tr->array_buffer.buffer; trace_ctx = tracing_gen_ctx_flags(0); event = trace_buffer_lock_reserve(buffer, TRACE_MMIO_MAP, sizeof(*entry), trace_ctx); -- cgit v1.2.3 From ac8719969e6c3c54e939834df812bc41f25453cf Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 29 Jul 2026 09:27:58 +0900 Subject: tracing: Check return value of __register_event() in trace_module_add_events() trace_module_add_events() ignores the return value of __register_event() and unconditionally calls __add_event_to_tracers() for each event. If __register_event() fails (for example, if event_init() fails), the trace_event_call is not added to ftrace_events list, but __add_event_to_tracers() still creates a trace_event_file pointing to it. If module loading subsequently fails and module memory is freed, tracing state retains a stale trace_event_call pointer in trace_event_file, leading to a use-after-free when tracefs or tracing subsystem operations are later executed. Fix this by checking the return value of __register_event() and only calling __add_event_to_tracers() if event registration succeeded. Fixes: ae63b31e4d0e ("tracing: Separate out trace events from global variables") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/178528487878.124250.14170824576025743236.stgit@devnote2 Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 956692856fa8..c01b10b99f67 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -3933,8 +3933,8 @@ static void trace_module_add_events(struct module *mod) end = mod->trace_events + mod->num_trace_events; for_each_event(call, start, end) { - __register_event(*call, mod); - __add_event_to_tracers(*call); + if (!__register_event(*call, mod)) + __add_event_to_tracers(*call); } update_cache_events(mod); -- cgit v1.2.3 From c22c7b735f9810ad276014f788f9aa5c879ec238 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Wed, 29 Jul 2026 09:28:07 +0900 Subject: tracing/filters: Fix false positive match in regex_match_full() regex_match_full() calls strncmp(str, r->pattern, len) where len is the target field buffer size. When len is smaller than r->len (the filter pattern length), strncmp() checks only len bytes of r->pattern against str. If those len bytes match, strncmp() returns 0, resulting in a false-positive match where a shorter string in a fixed-size field matches a longer filter pattern. For example, a 4-byte static string field containing "abcd" matched the filter pattern "abcdefgh" because strncmp("abcd", "abcdefgh", 4) returned 0. In this case, @len does NOT include '\0' because it is fixed-size array. Fix this by returning 0 (no match) early when len < r->len. Fixes: 1889d20922d1 ("tracing/filters: Provide basic regex support") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/178528488779.124250.5571741156199253769.stgit@devnote2 Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_filter.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 6385cd662d8d..2b46ca536045 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1027,6 +1027,9 @@ static int regex_match_full(char *str, struct regex *r, int len) if (!len) return strcmp(str, r->pattern) == 0; + if (len < r->len) + return 0; + return strncmp(str, r->pattern, len) == 0; } -- cgit v1.2.3 From 78cd56c2a9d2e8da763cea3b06b636266ca66911 Mon Sep 17 00:00:00 2001 From: Vincent Donnefort Date: Wed, 29 Jul 2026 14:36:09 +0100 Subject: ring-buffer: Fix reader page read offset for remote buffers A page swapped in by __rb_get_reader_page_from_remote() retains its stale read offset, causing subsequent reads to skip events or read past valid data. Fix it. Link: https://patch.msgid.link/20260729133609.4022734-1-vdonnefort@google.com Fixes: fbd1743ecba1 ("ring-buffer: Add non-consuming read for ring-buffer remotes") Signed-off-by: Vincent Donnefort Reviewed-by: Keir Fraser Tested-by: Keir Fraser Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/trace') diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 804ccae694d2..78d3875a47a5 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -5783,6 +5783,7 @@ __rb_get_reader_page_from_remote(struct ring_buffer_per_cpu *cpu_buffer) cpu_buffer->head_page = new_head; cpu_buffer->reader_page = new_reader; + cpu_buffer->reader_page->read = 0; cpu_buffer->pages = &new_head->list; cpu_buffer->read_stamp = new_reader->page->time_stamp; cpu_buffer->lost_events = cpu_buffer->meta_page->reader.lost_events; -- cgit v1.2.3 From 260b20d9b78bf002f89088fb62d60e8dee98f6f8 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 31 Jul 2026 23:16:46 +0900 Subject: ring-buffer: Fix subbuf_ids memory leak in rb_allocate_cpu_buffer() error path In rb_allocate_cpu_buffer(), cpu_buffer->subbuf_ids is allocated using kcalloc() when buffer->remote is non-NULL. If a subsequent page allocation fails (e.g., ring_buffer_desc_page() returns NULL or rb_allocate_pages() fails), execution jumps to fail_free_reader. While __free(kfree) automatically frees the outer cpu_buffer structure at scope exit, kfree(cpu_buffer) does not recursively free nested heap pointers such as cpu_buffer->subbuf_ids, resulting in a memory leak. Fix this by explicitly freeing cpu_buffer->subbuf_ids in the fail_free_reader error unwinding path when cpu_buffer->remote is set. Link: https://patch.msgid.link/178550740672.380917.6067449683620196150.stgit@devnote2 Fixes: 2e67fabd8b77 ("ring-buffer: Introduce ring-buffer remotes") Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Masami Hiramatsu (Google) Reviewed-by: Vincent Donnefort Signed-off-by: Steven Rostedt --- kernel/trace/ring_buffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/trace') diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 78d3875a47a5..8e2485bb3aa8 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2599,6 +2599,7 @@ rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu) return_ptr(cpu_buffer); fail_free_reader: + kfree(cpu_buffer->subbuf_ids); free_buffer_page(cpu_buffer->reader_page); return NULL; -- cgit v1.2.3