From: Vincent Donnefort <vdonnefort@google.com>
To: sashiko-reviews@lists.linux.dev
Cc: linux-trace-kernel@vger.kernel.org
Subject: Re: [PATCH v4 2/9] ring-buffer: Hold cpu_buffer::lock when resizing a subbuf
Date: Wed, 12 Aug 2026 17:41:51 +0100 [thread overview]
Message-ID: <anyiT3KzVIm-4ZeD@google.com> (raw)
In-Reply-To: <20260812154659.3E3081F00A3F@smtp.kernel.org>
On Wed, Aug 12, 2026 at 03:46:58PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] The patch attempts to fix a race with `cpu_buffer->free_page` by adding an `arch_spin_lock(&cpu_buffer->lock)`, but it leaves a severe Time-Of-Check to Time-Of-Use (TOCTOU) race unaddressed. `buffer->subbuf_order` and `buffer->subbuf_size` are updated globally outside of any per-CPU lock. If a reader (like `tracing_buffers_splice_read`) calls `ring_buffer_alloc_read_page()` concurrently, it locklessly reads the NEW `buffer->subbuf_order` but then retrieves the OLD, incorrectly-sized `free_page` from the locked cache. When `ring_buffer_read_page()` uses this page, it copies data up to the NEW `buffer->subbuf_size`, leading to a heap buffer overflow if the new order is larger. Similarly, `ring_buffer_free_read_page()` validates `data_page->order` locklessly; if the global order changes just after the check, it inserts a new-order page into `free_page`, which `ring_buffer_subbuf_order_set()` will later free using the `old_order`, corrupting the page allocator.
> - [High] The patch adds an unconditional `arch_spin_lock(&cpu_buffer->lock)` to `ring_buffer_subbuf_order_set()`. This creates an NMI deadlock window. If an NMI (e.g., from a watchdog or an Oops triggering `ftrace_dump_on_oops`) fires on the same CPU while this lock is held, the NMI handler may attempt to read the ring buffer. The read path (via `ring_buffer_peek()` -> `rb_buffer_peek()` -> `__rb_get_reader_page()`) unconditionally acquires the same `cpu_buffer->lock` using `arch_spin_lock()` without an NMI-safe trylock fallback. Because the interrupted context holds the lock, the NMI handler will spin forever, causing a hard lockup.
> --
>
> --- Patch [2]: [PATCH v4 2/9] ring-buffer: Hold cpu_buffer::lock when resizing a subbuf ---
> commit 1db68f92346fd21f55d54529fb97b920f02a0136
> Author: Vincent Donnefort <vdonnefort@google.com>
>
> ring-buffer: Hold cpu_buffer::lock when resizing a subbuf
>
> This commit adds an arch_spin_lock() around the clearing of
> cpu_buffer->free_page in ring_buffer_subbuf_order_set(). This aims to
> prevent races with ring_buffer_alloc_read_page() and
> ring_buffer_free_read_page() during sub-buffer resizing.
>
> > diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> > index a3d28b2e2c94a..ec4f5a0c93e85 100644
> > --- a/kernel/trace/ring_buffer.c
> > +++ b/kernel/trace/ring_buffer.c
> > @@ -7431,8 +7431,10 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
> > cpu_buffer->nr_pages = cpu_buffer->nr_pages_to_update;
> > cpu_buffer->nr_pages_to_update = 0;
> >
> > + arch_spin_lock(&cpu_buffer->lock);
>
> [Severity: Critical]
> This is a pre-existing issue, but is there a Time-Of-Check to Time-Of-Use
> (TOCTOU) race between the global order updates and this per-CPU lock?
>
> Earlier in ring_buffer_subbuf_order_set(), buffer->subbuf_order and
> buffer->subbuf_size are updated globally outside of any per-CPU lock.
>
> If a reader like tracing_buffers_splice_read() calls
> ring_buffer_alloc_read_page() concurrently, can it locklessly read the new
> buffer->subbuf_order, but then retrieve the old, incorrectly-sized
> free_page from the locked cache?
>
> When ring_buffer_read_page() uses this page, wouldn't it copy data up to
> the new buffer->subbuf_size, leading to a heap buffer overflow if the new
> order is larger?
>
> Similarly, ring_buffer_free_read_page() validates data_page->order against
> buffer->subbuf_order locklessly. If the global order changes right after
> the check, could it insert a new-order page into free_page, which
> ring_buffer_subbuf_order_set() will later free using the old order,
> corrupting the page allocator?
This is hopefully fixed in one of the following patch of this series.
>
> [Severity: High]
> This is also a pre-existing issue, but does adding this unconditional
> arch_spin_lock() widen an NMI deadlock window?
>
> If an NMI (such as a watchdog or an Oops triggering ftrace_dump_on_oops)
> fires on the same CPU while this lock is held, the NMI handler may attempt
> to read the ring buffer.
>
> The read path via __rb_get_reader_page() unconditionally acquires the same
> cpu_buffer->lock using arch_spin_lock() without an NMI-safe trylock
> fallback.
This is under raw_spin_lock_irqsave(). I believe the panic path will first try
to issue normal IPIs.
--
Vincent
>
> Because the interrupted context holds the lock, will the NMI handler spin
> forever, causing a hard lockup?
>
> > old_free_data_page = cpu_buffer->free_page;
> > cpu_buffer->free_page = NULL;
> > + arch_spin_unlock(&cpu_buffer->lock);
> >
> > rb_head_page_activate(cpu_buffer);
> >
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260812153311.2328812-1-vdonnefort@google.com?part=2
next prev parent reply other threads:[~2026-08-12 16:41 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 15:33 [PATCH v4 0/9] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 1/9] ring-buffer: Free cpu_buffer->free_page with subbuf_order Vincent Donnefort
2026-08-12 15:50 ` sashiko-bot
2026-08-12 16:37 ` Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 2/9] ring-buffer: Hold cpu_buffer::lock when resizing a subbuf Vincent Donnefort
2026-08-12 15:46 ` sashiko-bot
2026-08-12 16:41 ` Vincent Donnefort [this message]
2026-08-12 15:33 ` [PATCH v4 3/9] ring-buffer: Fix subbuf resize race with ring buffer readers Vincent Donnefort
2026-08-12 15:53 ` sashiko-bot
2026-08-12 16:44 ` Vincent Donnefort
2026-08-12 17:24 ` Steven Rostedt
2026-08-12 15:33 ` [PATCH v4 4/9] ring-buffer: Fix subbuf resize race in ring_buffer_alloc_read_page() Vincent Donnefort
2026-08-12 15:46 ` sashiko-bot
2026-08-12 16:50 ` Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 5/9] tracing: Fix subbuf resize races in trace_pipe_raw readers Vincent Donnefort
2026-08-12 15:47 ` sashiko-bot
2026-08-12 16:57 ` Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 6/9] ring-buffer: Dynamically calculate max_data_size Vincent Donnefort
2026-08-12 15:56 ` sashiko-bot
2026-08-12 17:12 ` Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 7/9] ring-buffer: Remove trace_buffer::cpus Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 8/9] ring-buffer: Remove ring_buffer_per_cpu::mapped Vincent Donnefort
2026-08-12 15:33 ` [PATCH v4 9/9] ring-buffer: Make nr_pages unsigned int Vincent Donnefort
2026-08-12 15:47 ` sashiko-bot
2026-08-12 17:15 ` Vincent Donnefort
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=anyiT3KzVIm-4ZeD@google.com \
--to=vdonnefort@google.com \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox