tracing: Fixes for 6.16
Subsystems (3)
cover tracing: Fixes for 6.16
git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
trace/fixes
Head SHA1: b5e8acc14dcb314a9b61ff19dcd9fdd0d88f70df
Steven Rostedt (1):
tracing: Add down_write(trace_event_sem) when adding trace event
Tomas Glozar (1):
tracing/osnoise: Fix crash in timerlat_dump_stack()
----
kernel/trace/trace_events.c | 5 +++++ kernel/trace/trace_osnoise.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
PATCH 1/2 tracing/osnoise: Fix crash in timerlat_dump_stack()
From: Tomas Glozar <[email protected]>
We have observed kernel panics when using timerlat with stack saving, with the following dmesg output:
memcpy: detected buffer overflow: 88 byte write of buffer size 0
WARNING: CPU: 2 PID: 8153 at lib/string_helpers.c:1032 __fortify_report+0x55/0xa0 CPU: 2 UID: 0 PID: 8153 Comm: timerlatu/2 Kdump: loaded Not tainted 6.15.3-200.fc42.x86_64 #1 PREEMPT(lazy) Call Trace: <TASK> ? trace_buffer_lock_reserve+0x2a/0x60 __fortify_panic+0xd/0xf __timerlat_dump_stack.cold+0xd/0xd timerlat_dump_stack.part.0+0x47/0x80 timerlat_fd_read+0x36d/0x390 vfs_read+0xe2/0x390 ? syscall_exit_to_user_mode+0x1d5/0x210 ksys_read+0x73/0xe0 do_syscall_64+0x7b/0x160 ? exc_page_fault+0x7e/0x1a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e
__timerlat_dump_stack() constructs the ftrace stack entry like this:
struct stack_entry *entry;
...memcpy(&entry->caller, fstack->calls, size);entry->size = fstack->nr_entries;
Since commit e7186af7fb26 ("tracing: Add back FORTIFY_SOURCE logic to kernel_stack event structure"), struct stack_entry marks its caller field with __counted_by(size). At the time of the memcpy, entry->size contains garbage from the ringbuffer, which under some circumstances is zero, triggering a kernel panic by buffer overflow.
Populate the size field before the memcpy so that the out-of-bounds check knows the correct size. This is analogous to __ftrace_trace_stack().
--- kernel/trace/trace_osnoise.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_osnoise.c +1 -1
@@ -637,8 +637,8 @@ __timerlat_dump_stack(struct trace_buffer *buffer, struct trace_stack *fstack, u entry =ring_buffer_event_data (event); -memcpy (&entry->caller, fstack->calls, size); entry->size = fstack->nr_entries; +memcpy (&entry->caller, fstack->calls, size);trace_buffer_unlock_commit_nostack (buffer, event); }
Signature · 1 line
2.47.2
PATCH 2/2 tracing: Add down_write(trace_event_sem) when adding trace event
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
When a module is loaded, it adds trace events defined by the module. It may also need to modify the modules trace printk formats to replace enum names with their values.
If two modules are loaded at the same time, the adding of the event to the ftrace_events list can corrupt the walking of the list in the code that is modifying the printk format strings and crash the kernel.
The addition of the event should take the trace_event_sem for write while it adds the new event.
Also add a lockdep_assert_held() on that semaphore in __trace_add_event_dirs() as it iterates the list.
--- kernel/trace/trace_events.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/trace/trace_events.c +5 -0
@@ -3136,7 +3136,10 @@ __register_event(struct trace_event_call *call, struct module *mod)if (ret <0 )return ret; +down_write (&trace_event_sem);list_add (&call->list, &ftrace_events); +up_write (&trace_event_sem); +if (call->flags &TRACE_EVENT_FL_DYNAMIC )atomic_set (&call->refcnt,0 );else
@@ -3750,6 +3753,8 @@ __trace_add_event_dirs(struct trace_array *tr)struct trace_event_call *call;int ret; +lockdep_assert_held (&trace_event_sem); +list_for_each_entry (call, &ftrace_events, list) { ret =__trace_add_new_event (call, tr);if (ret <0 )
Signature · 1 line
2.47.2