| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2024-38601: ring-buffer: Fix a race between readers and resize checks |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| ring-buffer: Fix a race between readers and resize checks |
| |
| The reader code in rb_get_reader_page() swaps a new reader page into the |
| ring buffer by doing cmpxchg on old->list.prev->next to point it to the |
| new page. Following that, if the operation is successful, |
| old->list.next->prev gets updated too. This means the underlying |
| doubly-linked list is temporarily inconsistent, page->prev->next or |
| page->next->prev might not be equal back to page for some page in the |
| ring buffer. |
| |
| The resize operation in ring_buffer_resize() can be invoked in parallel. |
| It calls rb_check_pages() which can detect the described inconsistency |
| and stop further tracing: |
| |
| [ 190.271762] ------------[ cut here ]------------ |
| [ 190.271771] WARNING: CPU: 1 PID: 6186 at kernel/trace/ring_buffer.c:1467 rb_check_pages.isra.0+0x6a/0xa0 |
| [ 190.271789] Modules linked in: [...] |
| [ 190.271991] Unloaded tainted modules: intel_uncore_frequency(E):1 skx_edac(E):1 |
| [ 190.272002] CPU: 1 PID: 6186 Comm: cmd.sh Kdump: loaded Tainted: G E 6.9.0-rc6-default #5 158d3e1e6d0b091c34c3b96bfd99a1c58306d79f |
| [ 190.272011] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.0-0-gd239552c-rebuilt.opensuse.org 04/01/2014 |
| [ 190.272015] RIP: 0010:rb_check_pages.isra.0+0x6a/0xa0 |
| [ 190.272023] Code: [...] |
| [ 190.272028] RSP: 0018:ffff9c37463abb70 EFLAGS: 00010206 |
| [ 190.272034] RAX: ffff8eba04b6cb80 RBX: 0000000000000007 RCX: ffff8eba01f13d80 |
| [ 190.272038] RDX: ffff8eba01f130c0 RSI: ffff8eba04b6cd00 RDI: ffff8eba0004c700 |
| [ 190.272042] RBP: ffff8eba0004c700 R08: 0000000000010002 R09: 0000000000000000 |
| [ 190.272045] R10: 00000000ffff7f52 R11: ffff8eba7f600000 R12: ffff8eba0004c720 |
| [ 190.272049] R13: ffff8eba00223a00 R14: 0000000000000008 R15: ffff8eba067a8000 |
| [ 190.272053] FS: 00007f1bd64752c0(0000) GS:ffff8eba7f680000(0000) knlGS:0000000000000000 |
| [ 190.272057] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 |
| [ 190.272061] CR2: 00007f1bd6662590 CR3: 000000010291e001 CR4: 0000000000370ef0 |
| [ 190.272070] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 |
| [ 190.272073] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 |
| [ 190.272077] Call Trace: |
| [ 190.272098] <TASK> |
| [ 190.272189] ring_buffer_resize+0x2ab/0x460 |
| [ 190.272199] __tracing_resize_ring_buffer.part.0+0x23/0xa0 |
| [ 190.272206] tracing_resize_ring_buffer+0x65/0x90 |
| [ 190.272216] tracing_entries_write+0x74/0xc0 |
| [ 190.272225] vfs_write+0xf5/0x420 |
| [ 190.272248] ksys_write+0x67/0xe0 |
| [ 190.272256] do_syscall_64+0x82/0x170 |
| [ 190.272363] entry_SYSCALL_64_after_hwframe+0x76/0x7e |
| [ 190.272373] RIP: 0033:0x7f1bd657d263 |
| [ 190.272381] Code: [...] |
| [ 190.272385] RSP: 002b:00007ffe72b643f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 |
| [ 190.272391] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f1bd657d263 |
| [ 190.272395] RDX: 0000000000000002 RSI: 0000555a6eb538e0 RDI: 0000000000000001 |
| [ 190.272398] RBP: 0000555a6eb538e0 R08: 000000000000000a R09: 0000000000000000 |
| [ 190.272401] R10: 0000555a6eb55190 R11: 0000000000000246 R12: 00007f1bd6662500 |
| [ 190.272404] R13: 0000000000000002 R14: 00007f1bd6667c00 R15: 0000000000000002 |
| [ 190.272412] </TASK> |
| [ 190.272414] ---[ end trace 0000000000000000 ]--- |
| |
| Note that ring_buffer_resize() calls rb_check_pages() only if the parent |
| trace_buffer has recording disabled. Recent commit d78ab792705c |
| ("tracing: Stop current tracer when resizing buffer") causes that it is |
| now always the case which makes it more likely to experience this issue. |
| |
| The window to hit this race is nonetheless very small. To help |
| reproducing it, one can add a delay loop in rb_get_reader_page(): |
| |
| ret = rb_head_page_replace(reader, cpu_buffer->reader_page); |
| if (!ret) |
| goto spin; |
| for (unsigned i = 0; i < 1U << 26; i++) /* inserted delay loop */ |
| __asm__ __volatile__ ("" : : : "memory"); |
| rb_list_head(reader->list.next)->prev = &cpu_buffer->reader_page->list; |
| |
| .. and then run the following commands on the target system: |
| |
| echo 1 > /sys/kernel/tracing/events/sched/sched_switch/enable |
| while true; do |
| echo 16 > /sys/kernel/tracing/buffer_size_kb; sleep 0.1 |
| echo 8 > /sys/kernel/tracing/buffer_size_kb; sleep 0.1 |
| done & |
| while true; do |
| for i in /sys/kernel/tracing/per_cpu/*; do |
| timeout 0.1 cat $i/trace_pipe; sleep 0.2 |
| done |
| done |
| |
| To fix the problem, make sure ring_buffer_resize() doesn't invoke |
| rb_check_pages() concurrently with a reader operating on the same |
| ring_buffer_per_cpu by taking its cpu_buffer->reader_lock. |
| |
| |
| [ Fixed whitespace ] |
| |
| The Linux kernel CVE team has assigned CVE-2024-38601 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 4.19.316 with commit b50932ea673b5a089a4bb570a8a868d95c72854e |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 5.4.278 with commit c68b7a442ee61d04ca58b2b5cb5ea7cb8230f84a |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 5.10.219 with commit 1e160196042cac946798ac192a0bc3398f1aa66b |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 5.15.161 with commit 595363182f28786d641666a09e674b852c83b4bb |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 6.1.93 with commit 54c64967ba5f8658ae7da76005024ebd3d9d8f6e |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 6.6.33 with commit af3274905b3143ea23142bbf77bd9b610c54e533 |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 6.8.12 with commit 5ef9e330406d3fb4f4b2c8bca2c6b8a93bae32d1 |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 6.9.3 with commit 79b52013429a42b8efdb0cda8bb0041386abab87 |
| Issue introduced in 3.5 with commit 659f451ff21315ebfeeb46b9adccee8ce1b52c25 and fixed in 6.10 with commit c2274b908db05529980ec056359fae916939fdaa |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2024-38601 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| kernel/trace/ring_buffer.c |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/b50932ea673b5a089a4bb570a8a868d95c72854e |
| https://git.kernel.org/stable/c/c68b7a442ee61d04ca58b2b5cb5ea7cb8230f84a |
| https://git.kernel.org/stable/c/1e160196042cac946798ac192a0bc3398f1aa66b |
| https://git.kernel.org/stable/c/595363182f28786d641666a09e674b852c83b4bb |
| https://git.kernel.org/stable/c/54c64967ba5f8658ae7da76005024ebd3d9d8f6e |
| https://git.kernel.org/stable/c/af3274905b3143ea23142bbf77bd9b610c54e533 |
| https://git.kernel.org/stable/c/5ef9e330406d3fb4f4b2c8bca2c6b8a93bae32d1 |
| https://git.kernel.org/stable/c/79b52013429a42b8efdb0cda8bb0041386abab87 |
| https://git.kernel.org/stable/c/c2274b908db05529980ec056359fae916939fdaa |