tracing: Fixes for v7.2
cover tracing: Fixes for v7.2
tracing fixes for 7.2:
- Reset dropped_count in mmio_reset_data()
When mmio_reset_data() is called, it does not reset the dropped_count so that subsequent runs will have incorrect reporting.
- Add NULL check for mmio_trace_array in logging functions
The functions __trace_mmiotrace_rw() and __trace_mmiotrace_map() may have the 'tr' variable passed to it as NULL. But they both dereference it without checking if it is NULL first.
- Check return value of __register_event() in trace_module_add_events()
If __register_event() fails, the call after it (__add_event_to_tracers()) will create a file for it. If the module fails to load and its memory is freed, the file will still point to it and it will not be removed as the registering of the event did not complete. Only call __add_event_to_tracers() if the __register_event() was successful.
- Fix false positive match in regex_match_full()
The regex full matching uses a strncmp() to test against the match string and the value. It should not match if value is a prefix of the string to match. Check to make sure the length of the strings match before comparing.
- 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.
git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
trace/fixes
Head SHA1: 78cd56c2a9d2e8da763cea3b06b636266ca66911
Masami Hiramatsu (Google) (4):
tracing/mmiotrace: Reset dropped_count in mmio_reset_data() tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
tracing: Check return value of __register_event() in trace_module_add_events() tracing/filters: Fix false positive match in regex_match_full()
Vincent Donnefort (1):
ring-buffer: Fix reader page read offset for remote buffers
----
kernel/trace/ring_buffer.c | 1 + kernel/trace/trace_events.c | 4 ++-- kernel/trace/trace_events_filter.c | 3 +++ kernel/trace/trace_mmiotrace.c | 13 +++++++++++-- 4 files changed, 17 insertions(+), 4 deletions(-)
PATCH 1/5 tracing/mmiotrace: Reset dropped_count in mmio_reset_data()
From: "Masami Hiramatsu (Google)" <[email protected]>
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().
--- kernel/trace/trace_mmiotrace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace_mmiotrace.c +1 -0
@@ -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); }
Signature · 1 line
2.53.0
PATCH 2/5 tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
In reply to Steven RostedtFrom: "Masami Hiramatsu (Google)" <[email protected]>
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().
--- kernel/trace/trace_mmiotrace.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
kernel/trace/trace_mmiotrace.c +10 -2
@@ -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);
Signature · 1 line
2.53.0
PATCH 3/5 tracing: Check return value of __register_event() in trace_module_add_events()
In reply to Steven RostedtFrom: "Masami Hiramatsu (Google)" <[email protected]>
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.
--- kernel/trace/trace_events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/trace_events.c +2 -2
@@ -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);
Signature · 1 line
2.53.0
PATCH 4/5 tracing/filters: Fix false positive match in regex_match_full()
In reply to Steven RostedtFrom: "Masami Hiramatsu (Google)" <[email protected]>
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.
--- kernel/trace/trace_events_filter.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/trace/trace_events_filter.c +3 -0
@@ -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 ; }
Signature · 1 line
2.53.0
PATCH 5/5 ring-buffer: Fix reader page read offset for remote buffers
In reply to Steven RostedtFrom: Vincent Donnefort <[email protected]>
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.
--- kernel/trace/ring_buffer.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/ring_buffer.c +1 -0
@@ -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;
Signature · 1 line
2.53.0