Re: [GIT PULL] tracing: Prevent trace_marker being bigger than unsigned short

From: Steven Rostedt
Date: Sun Mar 03 2024 - 07:59:50 EST


On Sat, 2 Mar 2024 12:55:10 -0800
Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:

> On Sat, 2 Mar 2024 at 12:47, Steven Rostedt <rostedt@xxxxxxxxxxx> wrote:
> >
> > I'm fine with just making it 4K with a comment saying that "4K is the
> > minimum page size on most archs, and to keep this consistent for crazy
> > architectures like PowerPC and it's 64K pages, we hard code 4K to keep
> > all architectures acting the same".
>
> 4k is at least a somewhat sane limit, and yes, being hw-independent is
> a good idea.
>
> We have other strings that have that limit for similar reasons (ie PATH_MAX).
>

I believe I was trying to solve this wrong. The vsprintf() is called on
reading of the ring buffer, and I was trying to fix it on the write
side. I believe that the fix should be on the read side where the
vsprintf() is called.

Sachin, can you try this patch.

diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 3e7fa44dc2b2..5c7962d612de 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -1588,11 +1588,20 @@ static enum print_line_t trace_print_print(struct trace_iterator *iter,
struct print_entry *field;
struct trace_seq *s = &iter->seq;
int max = iter->ent_size - offsetof(struct print_entry, buf);
+ const char *p;

trace_assign_type(field, iter->ent);

seq_print_ip_sym(s, field->ip, flags);
- trace_seq_printf(s, ": %.*s", max, field->buf);
+ trace_seq_puts(s, ": ");
+ /* Write 1K chunks at a time */
+ p = field->buf;
+ do {
+ int pre = max > 1024 ? 1024 : max;
+ trace_seq_printf(s, "%.*s", pre, p);
+ max -= pre;
+ p += pre;
+ } while (max > 0);

return trace_handle_return(s);
}
@@ -1602,10 +1611,19 @@ static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
{
struct print_entry *field;
int max = iter->ent_size - offsetof(struct print_entry, buf);
+ const char *p;

trace_assign_type(field, iter->ent);

- trace_seq_printf(&iter->seq, "# %lx %.*s", field->ip, max, field->buf);
+ trace_seq_printf(&iter->seq, "# %lx", field->ip);
+ /* Write 1K chunks at a time */
+ p = field->buf;
+ do {
+ int pre = max > 1024 ? 1024 : max;
+ trace_seq_printf(&iter->seq, "%.*s", pre, p);
+ max -= pre;
+ p += pre;
+ } while (max > 0);

return trace_handle_return(&iter->seq);
}