From: Steven Rostedt <rostedt@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Andrew Morton <akpm@linux-foundation.org>,
Vincent Donnefort <vdonnefort@google.com>
Subject: [for-linus][PATCH 10/12] ring-buffer: Prevent truncation of nr_pages / nr_subbufs
Date: Sat, 05 Sep 2026 21:45:41 -0400 [thread overview]
Message-ID: <20260906014656.654469185@kernel.org> (raw)
In-Reply-To: <20260906014531.720267751@kernel.org>
From: Vincent Donnefort <vdonnefort@google.com>
Although 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. Use `unsigned long` where appropriate and
prevent truncation of values using nr_pages (or nr_subbufs).
While at it, subbuf_size must be at least `unsigned int`.
Note that persistent, remote and user-mapped ring buffers are capping
the number of pages to 30 bits already, making "int" safe in many
places.
Link: https://patch.msgid.link/20260904164450.1345852-5-vdonnefort@google.com
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
kernel/trace/ring_buffer.c | 61 +++++++++++++++++++-------------------
1 file changed, 30 insertions(+), 31 deletions(-)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 76fed01f1c49..220b8405adfc 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1683,7 +1683,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;
@@ -1693,13 +1693,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)
@@ -1745,7 +1744,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;
@@ -1757,11 +1756,11 @@ static void *rb_subbufs_from_meta(struct ring_buffer_cpu_meta *meta)
/*
* Return a specific sub-buffer for a given @cpu defined by @idx.
*/
-static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx)
+static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, unsigned long 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)
@@ -1777,7 +1776,7 @@ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx)
ptr = (unsigned long)rb_subbufs_from_meta(meta);
- ptr += subbuf_size * idx;
+ ptr += (unsigned long)subbuf_size * idx;
if (ptr + subbuf_size > cpu_buffer->buffer->range_addr_end)
return NULL;
@@ -1854,13 +1853,12 @@ 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 long buffers_start;
unsigned long buffers_end;
- int i;
+ unsigned long i;
if (!subbuf_mask)
return false;
@@ -1876,7 +1874,7 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu,
}
buffers_start = meta->first_buffer;
- buffers_end = meta->first_buffer + (subbuf_size * meta->nr_subbufs);
+ buffers_end = meta->first_buffer + (meta->nr_subbufs * PAGE_SIZE);
/* Is the head and commit buffers within the range of buffers? */
if (meta->head_buffer < buffers_start ||
@@ -2114,8 +2112,8 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
struct buffer_page *head_page, *orig_head, *orig_reader;
struct rb_validation_state state = { 0 };
bool skip = false;
+ unsigned long i;
int ret;
- int i;
if (!meta || !meta->head_buffer)
return;
@@ -2166,7 +2164,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
rb_validate_buffer(head_page, cpu_buffer, meta, &state, 0, state.ts);
}
if (i)
- pr_info("Ring buffer [%d] rewound %d pages\n", cpu_buffer->cpu, i);
+ pr_info("Ring buffer [%d] rewound %lu pages\n", cpu_buffer->cpu, i);
/* The last rewound page must be skipped. */
if (head_page != orig_head)
@@ -2250,7 +2248,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;
@@ -2350,8 +2349,8 @@ static int rbm_show(struct seq_file *m, void *v)
rb_meta_subbuf_idx(meta, (void *)meta->head_buffer));
seq_printf(m, "commit_buffer: %d\n",
rb_meta_subbuf_idx(meta, (void *)meta->commit_buffer));
- seq_printf(m, "subbuf_size: %d\n", meta->subbuf_size);
- seq_printf(m, "nr_subbufs: %d\n", meta->nr_subbufs);
+ seq_printf(m, "subbuf_size: %u\n", meta->subbuf_size);
+ seq_printf(m, "nr_subbufs: %u\n", meta->nr_subbufs);
return 0;
}
@@ -2436,7 +2435,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;
@@ -2564,7 +2563,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);
@@ -2721,8 +2720,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;
@@ -2792,8 +2791,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;
@@ -5882,12 +5881,12 @@ __rb_get_reader_page_from_remote(struct ring_buffer_per_cpu *cpu_buffer)
static struct buffer_page *
__rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
{
- int max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
+ unsigned long max_loops = cpu_buffer->ring_meta ? cpu_buffer->nr_pages : 3;
struct buffer_page *reader = NULL;
+ unsigned long nr_loops = 0;
unsigned long overwrite;
unsigned long flags;
int missed_events = 0;
- int nr_loops = 0;
bool ret;
local_irq_save(flags);
@@ -6205,8 +6204,8 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
struct trace_buffer *buffer;
struct ring_buffer_per_cpu *cpu_buffer;
struct ring_buffer_event *event;
- int nr_loops = 0;
- int max_loops;
+ unsigned long nr_loops = 0;
+ unsigned long max_loops;
if (ts)
*ts = 0;
@@ -7446,8 +7445,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;
@@ -7629,10 +7628,10 @@ 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;
+ unsigned int cnt = 0;
+ unsigned int id = 0;
id = rb_page_id(cpu_buffer, cpu_buffer->reader_page, id);
subbuf_ids[id++] = cpu_buffer->reader_page;
--
2.53.0
next prev parent reply other threads:[~2026-09-06 1:45 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-06 1:45 [for-linus][PATCH 00/12] tracing: Fixes for v7.3 Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 01/12] tracing: Have show_event_filters/triggers files take trace array ref Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 02/12] ftrace: Take trace_array reference before accessing its ftrace_ops Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 03/12] ftrace: Synchronize the initialization of ftrace_ops Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 04/12] tracing: Take trace_array reference when opening options file Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 05/12] ring-buffer: Allow splice reads on static buffers Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 06/12] ring-buffer: Add checking nr_subbufs to persistent ring buffer validation Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 07/12] tracing: Fix to avoid creating trace instances with duplicate names Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 08/12] tracing: Fix subbuf resize races with trace_pipe_raw readers Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 09/12] ring-buffer: Cap static ring buffer nr_pages Steven Rostedt
2026-09-06 1:45 ` Steven Rostedt [this message]
2026-09-06 1:45 ` [for-linus][PATCH 11/12] tracing: Fix comment in tracing_buffers_splice_read() Steven Rostedt
2026-09-06 1:45 ` [for-linus][PATCH 12/12] ring-buffer: Use a macro for static buffer bits Steven Rostedt
2026-09-06 20:00 ` [for-linus][PATCH 00/12] tracing: Fixes for v7.3 Steven Rostedt
-- strict thread matches above, loose matches on Subject: below --
2026-09-05 20:08 Steven Rostedt
2026-09-05 20:08 ` [for-linus][PATCH 10/12] ring-buffer: Prevent truncation of nr_pages / nr_subbufs Steven Rostedt
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=20260906014656.654469185@kernel.org \
--to=rostedt@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=vdonnefort@google.com \
/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
all inboxes | Powered by JetHome®