public inbox for patches@lists.linux.dev
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Deepanshu Kartikey <kartikey406@gmail.com>,
	syzbot+28cea38c382fd15e751a@syzkaller.appspotmail.com,
	Deepanshu Kartikey <Kartikey406@gmail.com>,
	Sean Anderson <sean.anderson@linux.dev>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Sasha Levin <sashal@kernel.org>,
	jgg@ziepe.ca, leon@kernel.org, ptesarik@suse.com
Subject: [PATCH AUTOSEL 6.18-6.12] tracing/dma: Cap dma_map_sg tracepoint arrays to prevent buffer overflow
Date: Mon,  9 Feb 2026 07:26:48 -0500	[thread overview]
Message-ID: <20260209122714.1037915-9-sashal@kernel.org> (raw)
In-Reply-To: <20260209122714.1037915-1-sashal@kernel.org>

From: Deepanshu Kartikey <kartikey406@gmail.com>

[ Upstream commit daafcc0ef0b358d9d622b6e3b7c43767aa3814ee ]

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 128 entries using min() in the array
size calculation. This ensures arrays are only as large as needed
(up to the cap), avoiding unnecessary memory allocation for small
operations while preventing overflow for large ones.

The tracepoint now records the full nents/ents counts and a truncated
flag so users can see when data has been capped.

Changes in v2:
- Use min(nents, DMA_TRACE_MAX_ENTRIES) for dynamic array sizing
  instead of fixed DMA_TRACE_MAX_ENTRIES allocation (feedback from
  Steven Rostedt)
- This allocates only what's needed up to the cap, avoiding waste
  for small operations

Reported-by: syzbot+28cea38c382fd15e751a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=28cea38c382fd15e751a
Tested-by: syzbot+28cea38c382fd15e751a@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
Reviwed-by: Sean Anderson <sean.anderson@linux.dev>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20260130155215.69737-1-kartikey406@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

This confirms the bug. At line 405, `WARN_ONCE` fires when `size >
PERF_MAX_TRACE_SIZE` (8192 bytes), and the function returns NULL,
causing the tracepoint to fail. The original `dma_map_sg` tracepoint
uses unbounded dynamic arrays (`__dynamic_array(u64, phys_addrs,
nents)`) which with large scatter-gather lists (nents > ~340 for a
single array of u64, or combined arrays > 8192 bytes total) will exceed
this limit.

### 3. CLASSIFICATION

**This is a clear bug fix.** It fixes:
1. A **buffer overflow** (trace data exceeding `PERF_MAX_TRACE_SIZE`)
2. A **kernel WARNING** triggered at runtime
3. A **functional failure** — the tracepoint becomes non-functional when
   the warning fires (returns NULL)

The bug is **syzbot-reported and reproducible**, with a concrete trigger
(virtio-gpu creating large DRM buffers).

### 4. SCOPE AND RISK ASSESSMENT

**Scope:**
- Single file changed: `include/trace/events/dma.h`
- Only the `dma_map_sg` TRACE_EVENT definition is modified
- Changes are contained within the tracepoint macro infrastructure

**Changes made:**
1. Define `DMA_TRACE_MAX_ENTRIES` (128) — a reasonable cap
2. Cap `__dynamic_array` sizes with `min(nents, DMA_TRACE_MAX_ENTRIES)`
3. Cap the `for_each_sg` iteration to traced_nents/traced_ents
4. Add `full_nents`, `full_ents`, and `truncated` fields for
   observability
5. Update `TP_printk` to show actual vs capped counts and a
   `[TRUNCATED]` marker

**Risk:**
- LOW risk. The change only affects the tracing subsystem, not the DMA
  mapping itself.
- The DMA operations proceed identically — only the trace output
  changes.
- Worst case: trace data is truncated (by design), but users are clearly
  informed via the `[TRUNCATED]` flag.
- The new fields (`full_nents`, `full_ents`, `truncated`) do change the
  tracepoint ABI slightly, but tracepoint ABIs are explicitly not stable
  (they can change between kernel versions).

### 5. USER IMPACT

- **Who is affected**: Anyone tracing DMA operations with perf on
  systems that create large scatter-gather lists (virtio-gpu, any GPU
  driver with large DRM buffers, potentially NVMe or other high-
  throughput I/O drivers).
- **Severity without fix**: Kernel WARNING on every affected tracepoint
  hit, plus the trace data is lost entirely (perf_trace_buf_alloc
  returns NULL). The WARNING can also trigger panic-on-warn
  configurations.
- **With the fix**: Trace data is properly capped and recorded, no
  WARNING.

### 6. STABILITY INDICATORS

- Reported by syzbot with a reproducer
- Tested by syzbot (confirmed fix)
- Reviewed by Sean Anderson
- Accepted by DMA subsystem maintainer Marek Szyprowski
- Iterated based on Steven Rostedt (tracing maintainer) feedback
- V2 of the patch — showing refinement

### 7. DEPENDENCY CHECK

- The `dma_map_sg` tracepoint was introduced in v6.12 (commit
  038eb433dc147). This fix only applies to 6.12+ stable trees.
- The patch modifies only the existing tracepoint definition and is
  self-contained.
- No dependencies on other patches.

### 8. CONCERNS

- **Note about `dma_alloc_sgt` and `dma_free_sgt` and other similar
  tracepoints**: These also have unbounded `__dynamic_array` based on
  `sgt->orig_nents` but are NOT fixed in this commit. This could mean
  those are less commonly hit or a separate fix is needed. However, this
  doesn't diminish the value of fixing the `dma_map_sg` case.
- **ABI change to tracepoint format**: The tracepoint output format
  changes (new fields added, format modified). While tracepoint ABIs are
  not considered stable, any perf scripts parsing the exact format of
  `dma_map_sg` would need updating. This is minor since tracepoint
  formats are expected to change.
- The patch should apply cleanly to 6.12.y since the file hasn't had
  many changes in this area since v6.12.

### SUMMARY

This is a well-crafted, syzbot-reported, tested-and-reviewed fix for a
real buffer overflow in the DMA tracing subsystem. The bug causes kernel
WARNINGs and complete failure of DMA scatter-gather tracing with large
buffers. The fix is small, contained to a single file, affects only the
tracing path (not actual DMA operations), and is low-risk. It has strong
trust indicators: syzbot-tested, maintainer-reviewed, and iterated based
on subsystem maintainer feedback. The only limitation is that it applies
only to stable trees 6.12+ where the tracepoint exists.

**YES**

 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 b3fef140ae155..33e99e792f1aa 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,  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))
 		__field(enum dma_data_direction, dir)
 		__field(unsigned long, attrs)
 	),
@@ -292,11 +297,16 @@ TRACE_EVENT(dma_map_sg,
 	TP_fast_assign(
 		struct scatterlist *sg;
 		int i;
+		int traced_nents = min_t(int, nents, DMA_TRACE_MAX_ENTRIES);
+		int traced_ents = min_t(int, ents, DMA_TRACE_MAX_ENTRIES);
 
 		__assign_str(device);
-		for_each_sg(sgl, sg, nents, i)
+		__entry->full_nents = nents;
+		__entry->full_ents = ents;
+		__entry->truncated = (nents > DMA_TRACE_MAX_ENTRIES) || (ents > DMA_TRACE_MAX_ENTRIES);
+		for_each_sg(sgl, sg, traced_nents, i)
 			((u64 *)__get_dynamic_array(phys_addrs))[i] = sg_phys(sg);
-		for_each_sg(sgl, sg, ents, i) {
+		for_each_sg(sgl, sg, traced_ents, i) {
 			((u64 *)__get_dynamic_array(dma_addrs))[i] =
 				sg_dma_address(sg);
 			((unsigned int *)__get_dynamic_array(lengths))[i] =
@@ -306,9 +316,12 @@ TRACE_EVENT(dma_map_sg,
 		__entry->attrs = attrs;
 	),
 
-	TP_printk("%s dir=%s dma_addrs=%s sizes=%s phys_addrs=%s attrs=%s",
+	TP_printk("%s dir=%s nents=%d/%d ents=%d/%d%s dma_addrs=%s sizes=%s phys_addrs=%s attrs=%s",
 		__get_str(device),
 		decode_dma_data_direction(__entry->dir),
+		min_t(int, __entry->full_nents, DMA_TRACE_MAX_ENTRIES), __entry->full_nents,
+		min_t(int, __entry->full_ents, DMA_TRACE_MAX_ENTRIES), __entry->full_ents,
+		__entry->truncated ? " [TRUNCATED]" : "",
 		__print_array(__get_dynamic_array(dma_addrs),
 			      __get_dynamic_array_len(dma_addrs) /
 				sizeof(u64), sizeof(u64)),
-- 
2.51.0


  parent reply	other threads:[~2026-02-09 12:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-09 12:26 [PATCH AUTOSEL 6.18-6.12] drm/amd/display: extend delta clamping logic to CM3 LUT helper Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18] io_uring/fdinfo: be a bit nicer when looping a lot of SQEs/CQEs Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.12] ALSA: hda/realtek: Enable headset mic for Acer Nitro 5 Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-5.10] platform/x86: classmate-laptop: Add missing NULL pointer checks Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.6] platform/x86/amd/pmc: Add quirk for MECHREVO Wujie 15X Pro Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.6] ASoC: amd: yc: Add quirk for HP 200 G2a 16 Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-5.15] platform/x86: panasonic-laptop: Fix sysfs group leak in error path Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-5.15] ASoC: fsl_xcvr: fix missing lock in fsl_xcvr_mode_put() Sasha Levin
2026-02-09 12:26 ` Sasha Levin [this message]
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-5.10] drm/tegra: hdmi: sor: Fix error: variable ‘j’ set but not used Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.1] ASoC: Intel: sof_es8336: Add DMI quirk for Huawei BOD-WXX9 Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18] ASoC: sof_sdw: Add a quirk for Lenovo laptop using sidecar amps with cs42l43 Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-5.10] gpiolib: acpi: Fix gpio count with string references Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.6] ASoC: cs42l43: Correct handling of 3-pole jack load detection Sasha Levin
2026-02-09 12:26 ` [PATCH AUTOSEL 6.18-6.12] drm/amd/display: remove assert around dpp_base replacement Sasha Levin

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=20260209122714.1037915-9-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=kartikey406@gmail.com \
    --cc=leon@kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=patches@lists.linux.dev \
    --cc=ptesarik@suse.com \
    --cc=sean.anderson@linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=syzbot+28cea38c382fd15e751a@syzkaller.appspotmail.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