Skip to content

Commit f7ec68c

Browse files
Luo Gengkungregkh
authored andcommitted
tracing: Fix tracing_marker may trigger page fault during preempt_disable
[ Upstream commit 3d62ab3 ] Both tracing_mark_write and tracing_mark_raw_write call __copy_from_user_inatomic during preempt_disable. But in some case, __copy_from_user_inatomic may trigger page fault, and will call schedule() subtly. And if a task is migrated to other cpu, the following warning will be trigger: if (RB_WARN_ON(cpu_buffer, !local_read(&cpu_buffer->committing))) An example can illustrate this issue: process flow CPU --------------------------------------------------------------------- tracing_mark_raw_write(): cpu:0 ... ring_buffer_lock_reserve(): cpu:0 ... cpu = raw_smp_processor_id() cpu:0 cpu_buffer = buffer->buffers[cpu] cpu:0 ... ... __copy_from_user_inatomic(): cpu:0 ... # page fault do_mem_abort(): cpu:0 ... # Call schedule schedule() cpu:0 ... # the task schedule to cpu1 __buffer_unlock_commit(): cpu:1 ... ring_buffer_unlock_commit(): cpu:1 ... cpu = raw_smp_processor_id() cpu:1 cpu_buffer = buffer->buffers[cpu] cpu:1 As shown above, the process will acquire cpuid twice and the return values are not the same. To fix this problem using copy_from_user_nofault instead of __copy_from_user_inatomic, as the former performs 'access_ok' before copying. Link: https://lore.kernel.org/20250819105152.2766363-1-luogengkun@huaweicloud.com Fixes: 656c7f0 ("tracing: Replace kmap with copy_from_user() in trace_marker writing") Signed-off-by: Luo Gengkun <luogengkun@huaweicloud.com> Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 781ec30 commit f7ec68c

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

kernel/trace/trace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7226,7 +7226,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
72267226
entry = ring_buffer_event_data(event);
72277227
entry->ip = _THIS_IP_;
72287228

7229-
len = __copy_from_user_inatomic(&entry->buf, ubuf, cnt);
7229+
len = copy_from_user_nofault(&entry->buf, ubuf, cnt);
72307230
if (len) {
72317231
memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);
72327232
cnt = FAULTED_SIZE;
@@ -7301,7 +7301,7 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf,
73017301

73027302
entry = ring_buffer_event_data(event);
73037303

7304-
len = __copy_from_user_inatomic(&entry->id, ubuf, cnt);
7304+
len = copy_from_user_nofault(&entry->id, ubuf, cnt);
73057305
if (len) {
73067306
entry->id = -1;
73077307
memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE);

0 commit comments

Comments
 (0)