[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20260130095749.491f4152@gandalf.local.home>
Date: Fri, 30 Jan 2026 09:57:49 -0500
From: Steven Rostedt <rostedt@...dmis.org>
To: Deepanshu Kartikey <kartikey406@...il.com>
Cc: mhiramat@...nel.org, mathieu.desnoyers@...icios.com,
m.szyprowski@...sung.com, leon@...nel.org, jgg@...pe.ca, ptesarik@...e.com,
kbusch@...nel.org, linux-kernel@...r.kernel.org,
linux-trace-kernel@...r.kernel.org,
syzbot+28cea38c382fd15e751a@...kaller.appspotmail.com
Subject: Re: [PATCH] tracing/dma: Cap dma_map_sg tracepoint arrays to
prevent buffer overflow
On Fri, 30 Jan 2026 11:33:17 +0530
Deepanshu Kartikey <kartikey406@...il.com> wrote:
> The dma_map_sg tracepoint can trigger a perf buffer overflow when
> tracing large scatter-gather lists. With devices like virtio-gpu
> creating large DRM buffers, nents can exceed 1000 entries, resulting
> in:
>
> phys_addrs: 1000 * 8 bytes = 8,000 bytes
> dma_addrs: 1000 * 8 bytes = 8,000 bytes
> lengths: 1000 * 4 bytes = 4,000 bytes
> Total: ~20,000 bytes
>
> This exceeds PERF_MAX_TRACE_SIZE (8192 bytes), causing:
>
> WARNING: CPU: 0 PID: 5497 at kernel/trace/trace_event_perf.c:405
> perf buffer not large enough, wanted 24620, have 8192
>
> Cap all three dynamic arrays at a fixed size of 128 entries. This limits
> the total event size to approximately 2,760 bytes, safely under the 8KB
> limit while still providing sufficient debugging information for typical
> cases.
>
> The tracepoint now records the full nents/ents counts and a truncated
> flag so users can see when data has been capped.
>
> Reported-by: syzbot+28cea38c382fd15e751a@...kaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=28cea38c382fd15e751a
> Signed-off-by: Deepanshu Kartikey <Kartikey406@...il.com>
> ---
> include/trace/events/dma.h | 25 +++++++++++++++++++------
> 1 file changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/include/trace/events/dma.h b/include/trace/events/dma.h
> index b3fef140ae15..c4e1a9f0c9c4 100644
> --- a/include/trace/events/dma.h
> +++ b/include/trace/events/dma.h
> @@ -275,6 +275,8 @@ TRACE_EVENT(dma_free_sgt,
> sizeof(u64), sizeof(u64)))
> );
>
> +#define DMA_TRACE_MAX_ENTRIES 128
> +
> TRACE_EVENT(dma_map_sg,
> TP_PROTO(struct device *dev, struct scatterlist *sgl, int nents,
> int ents, enum dma_data_direction dir, unsigned long attrs),
> @@ -282,9 +284,12 @@ TRACE_EVENT(dma_map_sg,
>
> TP_STRUCT__entry(
> __string(device, dev_name(dev))
> - __dynamic_array(u64, phys_addrs, nents)
> - __dynamic_array(u64, dma_addrs, ents)
> - __dynamic_array(unsigned int, lengths, ents)
> + __field(int, full_nents)
> + __field(int, full_ents)
> + __field(bool, truncated)
> + __dynamic_array(u64, phys_addrs, DMA_TRACE_MAX_ENTRIES)
> + __dynamic_array(u64, dma_addrs, DMA_TRACE_MAX_ENTRIES)
> + __dynamic_array(unsigned int, lengths, DMA_TRACE_MAX_ENTRIES)
This isn't doing what you want. You just used a dynamic array and allocated
a fixed size for it, regardless of if you use all of it or not. What you
want to do is:
__dynamic_array(u64, phys_addrs, min(nents, DMA_TRACE_MAX_ENTRIES))
__dynamic_array(u64, dma_addrs, min(ents, DMA_TRACE_MAX_ENTRIES))
__dynamic_array(unsigned int, lengths, min(ents, DMA_TRACE_MAX_ENTRIES))
And the same for the rest.
-- Steve
> __field(enum dma_data_direction, dir)
> __field(unsigned long, attrs)
> ),
Powered by blists - more mailing lists