| From b049525855fdd0024881c9b14b8fbec61c3f53d3 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (Google)" <rostedt@goodmis.org> |
| Date: Tue, 12 Dec 2023 07:25:58 -0500 |
| Subject: ring-buffer: Have saved event hold the entire event |
| |
| From: Steven Rostedt (Google) <rostedt@goodmis.org> |
| |
| commit b049525855fdd0024881c9b14b8fbec61c3f53d3 upstream. |
| |
| For the ring buffer iterator (non-consuming read), the event needs to be |
| copied into the iterator buffer to make sure that a writer does not |
| overwrite it while the user is reading it. If a write happens during the |
| copy, the buffer is simply discarded. |
| |
| But the temp buffer itself was not big enough. The allocation of the |
| buffer was only BUF_MAX_DATA_SIZE, which is the maximum data size that can |
| be passed into the ring buffer and saved. But the temp buffer needs to |
| hold the meta data as well. That would be BUF_PAGE_SIZE and not |
| BUF_MAX_DATA_SIZE. |
| |
| Link: https://lore.kernel.org/linux-trace-kernel/20231212072558.61f76493@gandalf.local.home |
| |
| Cc: stable@vger.kernel.org |
| Cc: Masami Hiramatsu <mhiramat@kernel.org> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| Fixes: 785888c544e04 ("ring-buffer: Have rb_iter_head_event() handle concurrent writer") |
| Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| kernel/trace/ring_buffer.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/kernel/trace/ring_buffer.c |
| +++ b/kernel/trace/ring_buffer.c |
| @@ -2403,7 +2403,7 @@ rb_iter_head_event(struct ring_buffer_it |
| */ |
| barrier(); |
| |
| - if ((iter->head + length) > commit || length > BUF_MAX_DATA_SIZE) |
| + if ((iter->head + length) > commit || length > BUF_PAGE_SIZE) |
| /* Writer corrupted the read? */ |
| goto reset; |
| |
| @@ -5113,7 +5113,8 @@ ring_buffer_read_prepare(struct trace_bu |
| if (!iter) |
| return NULL; |
| |
| - iter->event = kmalloc(BUF_MAX_DATA_SIZE, flags); |
| + /* Holds the entire event: data and meta data */ |
| + iter->event = kmalloc(BUF_PAGE_SIZE, flags); |
| if (!iter->event) { |
| kfree(iter); |
| return NULL; |