On Mon, 19 May 2025 09:02:40 +0200 Rafal Bilkowski <rafalbilkow...@gmail.com> wrote:
> Add a check in trace_iter_expand_format to prevent integer overflow when > calculating the new format buffer size, and to handle the case where krealloc > returns ZERO_SIZE_PTR. This improves robustness and prevents potential > memory corruption or kernel crashes. What exactly is this trying to protect? > > Signed-off-by: Rafal Bilkowski <rafalbilkow...@gmail.com> > --- > kernel/trace/trace.c | 4 ++++ > kernel/trace/trace_output.c | 2 ++ > 2 files changed, 6 insertions(+) > > diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c > index 5b8db27fb6ef..637bd1ff9325 100644 > --- a/kernel/trace/trace.c > +++ b/kernel/trace/trace.c > @@ -3596,6 +3596,10 @@ char *trace_iter_expand_format(struct trace_iterator > *iter) > if (!iter->tr || iter->fmt == static_fmt_buf) > return NULL; > > + /* Protection against overflow and ZERO_SIZE_PTR returned from krealloc > */ > + if (check_add_overflow(iter->fmt_size, STATIC_FMT_BUF_SIZE, > &iter->fmt_size)) > + return NULL; This will *NEVER* happen! The fmt_size is initialized as STATIC_FMT_BUF_SIZE, and this is the only function that increases it, and that happens *only* if the krealloc() succeeds. For this to happen, then the krealloc must have allocated something that would allow the format size to be INT_MAX, which krealloc would fail much earlier than that. Not to mention, the formats can't be more that the sub-buffer size, which is by default 4K and can be at most 64K. Way smaller than INT_MAX. > + > tmp = krealloc(iter->fmt, iter->fmt_size + STATIC_FMT_BUF_SIZE, > GFP_KERNEL); > if (tmp) { > diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c > index b9ab06c99543..42560027001a 100644 > --- a/kernel/trace/trace_output.c > +++ b/kernel/trace/trace_output.c > @@ -979,6 +979,8 @@ static void print_fields(struct trace_iterator *iter, > struct trace_event_call *c > iter->fmt_size); > if (ret < 0) > trace_seq_printf(&iter->seq, "(0x%px)", pos); > + else if (ret == 0) > + trace_seq_printf(&iter->seq, "(0x%px:<NULL>)", > pos); This part I'm OK with adding. -- Steve > else > trace_seq_printf(&iter->seq, "(0x%px:%s)", > pos, iter->fmt);