From: Vincent Donnefort <vdonnefort@google.com>
To: rostedt@goodmis.org, mhiramat@kernel.org,
linux-trace-kernel@vger.kernel.org
Cc: mathieu.desnoyers@efficios.com, kernel-team@android.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v6 2/2] ring-buffer: Improve nr_pages type
Date: Mon, 17 Aug 2026 11:27:01 +0100 [thread overview]
Message-ID: <aoLh9djyr-3PFSvj@google.com> (raw)
In-Reply-To: <20260814154823.755406-3-vdonnefort@google.com>
On Fri, Aug 14, 2026 at 04:48:23PM +0100, Vincent Donnefort wrote:
> If ring_buffer_per_cpu::nr_pages is defined as unsigned long, it is
> capped to 32-bits in a few places, limiting the operations possible on a
> very large buffer.
>
> Make sure nr_pages is never capped to 32-bits (that includes nr_subbufs)
> and reject a value over 32-bits for the user-mapped, persistent buffer
> and remote buffer cases where the limiting factor is the shared
> meta-data member for the number of pages/subbufs.
>
> While at it, make sure subbuf_size is 'unsigned int'.
>
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> ---
> kernel/trace/ring_buffer.c | 46 ++++++++++++++++++++++++--------------
> 1 file changed, 29 insertions(+), 17 deletions(-)
>
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index ec13779922ff..ec127e2ad052 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -1669,7 +1669,7 @@ static void rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
> * This is used to help find the next per cpu subbuffer within a mapped range.
> */
> static unsigned long
> -rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs)
> +rb_range_align_subbuf(unsigned long addr, unsigned int subbuf_size, unsigned long nr_subbufs)
> {
> addr += sizeof(struct ring_buffer_cpu_meta) +
> sizeof(int) * nr_subbufs;
> @@ -1679,13 +1679,12 @@ rb_range_align_subbuf(unsigned long addr, int subbuf_size, int nr_subbufs)
> /*
> * Return the ring_buffer_meta for a given @cpu.
> */
> -static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu)
> +static void *rb_range_meta(struct trace_buffer *buffer, unsigned long nr_pages, int cpu)
> {
> - int subbuf_size = rb_subbuf_size(buffer);
> + unsigned int subbuf_size = rb_subbuf_size(buffer);
> struct ring_buffer_cpu_meta *meta;
> struct ring_buffer_meta *bmeta;
> - unsigned long ptr;
> - int nr_subbufs;
> + unsigned long ptr, nr_subbufs;
>
> bmeta = buffer->meta;
> if (!bmeta)
> @@ -1731,7 +1730,7 @@ static void *rb_range_meta(struct trace_buffer *buffer, int nr_pages, int cpu)
> /* Return the start of subbufs given the meta pointer */
> static void *rb_subbufs_from_meta(struct ring_buffer_cpu_meta *meta)
> {
> - int subbuf_size = meta->subbuf_size;
> + unsigned int subbuf_size = meta->subbuf_size;
> unsigned long ptr;
>
> ptr = (unsigned long)meta;
> @@ -1746,8 +1745,8 @@ static void *rb_subbufs_from_meta(struct ring_buffer_cpu_meta *meta)
> static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx)
> {
> struct ring_buffer_cpu_meta *meta;
> + unsigned int subbuf_size;
> unsigned long ptr;
> - int subbuf_size;
>
> meta = rb_range_meta(cpu_buffer->buffer, 0, cpu_buffer->cpu);
> if (!meta)
> @@ -1840,10 +1839,10 @@ static bool rb_meta_init(struct trace_buffer *buffer, int scratch_size)
> * must be the same.
> */
> static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu,
> - struct trace_buffer *buffer, int nr_pages,
> + struct trace_buffer *buffer, unsigned long nr_pages,
> unsigned long *subbuf_mask)
> {
> - int subbuf_size = PAGE_SIZE;
> + unsigned int subbuf_size = PAGE_SIZE;
> unsigned long buffers_start;
> unsigned long buffers_end;
> int i;
> @@ -2231,7 +2230,8 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
> }
> }
>
> -static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages, int scratch_size)
> +static void rb_range_meta_init(struct trace_buffer *buffer,
> + unsigned long nr_pages, int scratch_size)
> {
> struct ring_buffer_cpu_meta *meta;
> unsigned long *subbuf_mask;
> @@ -2417,7 +2417,7 @@ static void *ring_buffer_desc_page(struct ring_buffer_desc *desc, unsigned int p
> }
>
> static int __rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
> - long nr_pages, struct list_head *pages)
> + unsigned long nr_pages, struct list_head *pages)
> {
> struct trace_buffer *buffer = cpu_buffer->buffer;
> struct ring_buffer_cpu_meta *meta = NULL;
> @@ -2545,7 +2545,7 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
> }
>
> static struct ring_buffer_per_cpu *
> -rb_allocate_cpu_buffer(struct trace_buffer *buffer, long nr_pages, int cpu)
> +rb_allocate_cpu_buffer(struct trace_buffer *buffer, unsigned long nr_pages, int cpu)
> {
> struct ring_buffer_per_cpu *cpu_buffer __free(kfree) =
> alloc_cpu_buffer(cpu);
> @@ -2702,8 +2702,8 @@ static void rb_test_inject_invalid_pages(struct trace_buffer *buffer)
> struct ring_buffer_cpu_meta *meta;
> struct buffer_data_page *dpage;
> unsigned long entry_bytes = 0;
> + unsigned int subbuf_size;
> unsigned long ptr;
> - int subbuf_size;
> int invalid = 0;
> int cpu;
> int i;
> @@ -2773,8 +2773,8 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
> struct ring_buffer_remote *remote)
> {
> struct trace_buffer *buffer __free(kfree) = NULL;
> - long nr_pages;
> - int subbuf_size;
> + unsigned int subbuf_size;
> + unsigned long nr_pages;
> int bsize;
> int cpu;
> int ret;
> @@ -2837,6 +2837,10 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
> */
> nr_pages = (size - sizeof(struct ring_buffer_cpu_meta)) /
> (subbuf_size + sizeof(int));
> +
> + /* limited by ring_buffer_cpu_meta::nr_subbufs */
> + if (nr_pages > U32_MAX - 1)
> + goto fail_free_buffers;
> /* Need at least two pages plus the reader page */
> if (nr_pages < 3)
> goto fail_free_buffers;
> @@ -2869,6 +2873,10 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
> /* The writer is remote. This ring-buffer is read-only */
> atomic_inc(&buffer->record_disabled);
> nr_pages = desc->nr_page_va - 1;
> +
> + /* limited by ring_buffer_desc::nr_page_va */
> + if (nr_pages > U32_MAX - 1)
> + goto fail_free_buffers;
> if (nr_pages < 2)
> goto fail_free_buffers;
> } else {
> @@ -7421,8 +7429,8 @@ int ring_buffer_subbuf_order_set(struct trace_buffer *buffer, int order)
> struct ring_buffer_per_cpu *cpu_buffer;
> struct buffer_page *bpage, *tmp;
> unsigned int old_capacity;
> + unsigned long nr_pages;
> int old_order;
> - int nr_pages;
> int psize;
> int err;
> int cpu;
> @@ -7604,7 +7612,7 @@ static void rb_setup_ids_meta_page(struct ring_buffer_per_cpu *cpu_buffer,
> struct buffer_page **subbuf_ids)
> {
> struct trace_buffer_meta *meta = cpu_buffer->meta_page;
> - unsigned int nr_subbufs = cpu_buffer->nr_pages + 1;
> + unsigned long nr_subbufs = cpu_buffer->nr_pages + 1;
> struct buffer_page *first_subbuf, *subbuf;
> int cnt = 0;
> int id = 0;
> @@ -7834,6 +7842,10 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu,
> /* prevent another thread from changing buffer/sub-buffer sizes */
> guard(mutex)(&buffer->mutex);
>
> + /* limited by trace_buffer_meta::nr_subbufs */
And actually I have realised the limiting factor is bpage::id which is only
30-bits.
> + if (cpu_buffer->nr_pages > U32_MAX - 1)
> + return -E2BIG;
> +
> err = rb_alloc_meta_page(cpu_buffer);
> if (err)
> return err;
> --
> 2.55.0.691.gc56d675ccc-goog
>
--
Vincent
prev parent reply other threads:[~2026-08-17 10:27 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 15:48 [PATCH v6 0/2] ring-buffer: Fixes for subbuf resizing and persistent buffers Vincent Donnefort
2026-08-14 15:48 ` [PATCH v6 1/2] tracing: Fix subbuf resize races with trace_pipe_raw readers Vincent Donnefort
2026-08-14 16:01 ` sashiko-bot
2026-08-17 8:59 ` Vincent Donnefort
2026-08-14 15:48 ` [PATCH v6 2/2] ring-buffer: Improve nr_pages type Vincent Donnefort
2026-08-14 15:59 ` sashiko-bot
2026-08-17 10:14 ` Vincent Donnefort
2026-08-17 10:27 ` Vincent Donnefort [this message]
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=aoLh9djyr-3PFSvj@google.com \
--to=vdonnefort@google.com \
--cc=kernel-team@android.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.