Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2023-53368

Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
17/09/2025
Última modificación:
18/09/2025

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> tracing: Fix race issue between cpu buffer write and swap<br /> <br /> Warning happened in rb_end_commit() at code:<br /> if (RB_WARN_ON(cpu_buffer, !local_read(&amp;cpu_buffer-&gt;committing)))<br /> <br /> WARNING: CPU: 0 PID: 139 at kernel/trace/ring_buffer.c:3142<br /> rb_commit+0x402/0x4a0<br /> Call Trace:<br /> ring_buffer_unlock_commit+0x42/0x250<br /> trace_buffer_unlock_commit_regs+0x3b/0x250<br /> trace_event_buffer_commit+0xe5/0x440<br /> trace_event_buffer_reserve+0x11c/0x150<br /> trace_event_raw_event_sched_switch+0x23c/0x2c0<br /> __traceiter_sched_switch+0x59/0x80<br /> __schedule+0x72b/0x1580<br /> schedule+0x92/0x120<br /> worker_thread+0xa0/0x6f0<br /> <br /> It is because the race between writing event into cpu buffer and swapping<br /> cpu buffer through file per_cpu/cpu0/snapshot:<br /> <br /> Write on CPU 0 Swap buffer by per_cpu/cpu0/snapshot on CPU 1<br /> -------- --------<br /> tracing_snapshot_write()<br /> [...]<br /> <br /> ring_buffer_lock_reserve()<br /> cpu_buffer = buffer-&gt;buffers[cpu]; // 1. Suppose find &amp;#39;cpu_buffer_a&amp;#39;;<br /> [...]<br /> rb_reserve_next_event()<br /> [...]<br /> <br /> ring_buffer_swap_cpu()<br /> if (local_read(&amp;cpu_buffer_a-&gt;committing))<br /> goto out_dec;<br /> if (local_read(&amp;cpu_buffer_b-&gt;committing))<br /> goto out_dec;<br /> buffer_a-&gt;buffers[cpu] = cpu_buffer_b;<br /> buffer_b-&gt;buffers[cpu] = cpu_buffer_a;<br /> // 2. cpu_buffer has swapped here.<br /> <br /> rb_start_commit(cpu_buffer);<br /> if (unlikely(READ_ONCE(cpu_buffer-&gt;buffer)<br /> != buffer)) { // 3. This check passed due to &amp;#39;cpu_buffer-&gt;buffer&amp;#39;<br /> [...] // has not changed here.<br /> return NULL;<br /> }<br /> cpu_buffer_b-&gt;buffer = buffer_a;<br /> cpu_buffer_a-&gt;buffer = buffer_b;<br /> [...]<br /> <br /> // 4. Reserve event from &amp;#39;cpu_buffer_a&amp;#39;.<br /> <br /> ring_buffer_unlock_commit()<br /> [...]<br /> cpu_buffer = buffer-&gt;buffers[cpu]; // 5. Now find &amp;#39;cpu_buffer_b&amp;#39; !!!<br /> rb_commit(cpu_buffer)<br /> rb_end_commit() // 6. WARN for the wrong &amp;#39;committing&amp;#39; state !!!<br /> <br /> Based on above analysis, we can easily reproduce by following testcase:<br /> ``` bash<br /> #!/bin/bash<br /> <br /> dmesg -n 7<br /> sysctl -w kernel.panic_on_warn=1<br /> TR=/sys/kernel/tracing<br /> echo 7 &gt; ${TR}/buffer_size_kb<br /> echo "sched:sched_switch" &gt; ${TR}/set_event<br /> while [ true ]; do<br /> echo 1 &gt; ${TR}/per_cpu/cpu0/snapshot<br /> done &amp;<br /> while [ true ]; do<br /> echo 1 &gt; ${TR}/per_cpu/cpu0/snapshot<br /> done &amp;<br /> while [ true ]; do<br /> echo 1 &gt; ${TR}/per_cpu/cpu0/snapshot<br /> done &amp;<br /> ```<br /> <br /> To fix it, IIUC, we can use smp_call_function_single() to do the swap on<br /> the target cpu where the buffer is located, so that above race would be<br /> avoided.

Impacto