* [PATCH v2] dma-buf: Fix silent overflow for phys vec to sgt
@ 2026-05-27 20:50 David Hu
2026-05-28 2:05 ` Claude review: " Claude Code Review Bot
2026-05-28 2:05 ` Claude Code Review Bot
0 siblings, 2 replies; 5+ messages in thread
From: David Hu @ 2026-05-27 20:50 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Kevin Tian, Ankit Agrawal, Jason Gunthorpe, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, jmoroni,
praan, leonro, David Hu, stable, iommu
In case MMIO size is bigger than 4G and peer2peer DMA goes
through host bridge, we trigger a code path that assigns the
total linked IOVA (which is greater than 4G) to mapped_len.
Previously, `mapped_len` was declared as 32-bit `unsigned int`.
When accumulating `size_t` lengths, this leads to a silent wrap-around.
This truncation causes truncated lengths to be passed to functions
like `fill_sg_entry()`.
Fix this by changing `mapped_len` to `size_t` (64-bit). While
at it, fix similar potential overflow issues in `calc_sg_nents`
by using `size_t` for `nents` and checking against `UINT_MAX`
and using `unsigned int` for the loop iterator in `fill_sg_entry`
to match.
to mapped_len, and leading to a silent overflow
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Cc: stable@vger.kernel.org
Cc: iommu@lists.linux.dev
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: David Hu <xuehaohu@google.com>
---
Changes in v2:
Fixed 'IVOA' -> 'IOVA' typo and expanded commit message (Claude Bot).
Added Reverse Xmas tree formatting (Pranjal).
Folded in extra bounds checking for calc_sg_nents() (Pranjal).
Folded in type consistency fix for fill_sg_entry() (Pranjal).
Droped unnecessary `nents = 0` initialization (Claude Bot).
drivers/dma-buf/dma-buf-mapping.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..5bc769fc42ea 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -10,7 +10,7 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
dma_addr_t addr)
{
unsigned int len, nents;
- int i;
+ unsigned int i;
nents = DIV_ROUND_UP(length, UINT_MAX);
for (i = 0; i < nents; i++) {
@@ -36,7 +36,7 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
struct phys_vec *phys_vec, size_t nr_ranges,
size_t size)
{
- unsigned int nents = 0;
+ size_t nents = 0;
size_t i;
if (!state || !dma_use_iova(state)) {
@@ -51,6 +51,9 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
nents = DIV_ROUND_UP(size, UINT_MAX);
}
+ if (nents > UINT_MAX)
+ return 0;
+
return nents;
}
@@ -95,9 +98,10 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
size_t nr_ranges, size_t size,
enum dma_data_direction dir)
{
- unsigned int nents, mapped_len = 0;
struct dma_buf_dma *dma;
struct scatterlist *sgl;
+ size_t mapped_len = 0;
+ unsigned int nents;
dma_addr_t addr;
size_t i;
int ret;
--
2.54.0.794.g4f17f83d09-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* Claude review: dma-buf: Fix silent overflow for phys vec to sgt
2026-05-27 20:50 [PATCH v2] dma-buf: Fix silent overflow for phys vec to sgt David Hu
@ 2026-05-28 2:05 ` Claude Code Review Bot
2026-05-28 2:05 ` Claude Code Review Bot
1 sibling, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-05-28 2:05 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: dma-buf: Fix silent overflow for phys vec to sgt
Author: David Hu <xuehaohu@google.com>
Patches: 1
Reviewed: 2026-05-28T12:05:55.710402
---
This is a single-patch fix for a real overflow bug in `dma_buf_phys_vec_to_sgt()` where MMIO regions larger than 4GB cause `mapped_len` (declared as `unsigned int`) to silently wrap around when accumulating `size_t` lengths. The fix is straightforward and correct: promote `mapped_len` to `size_t`. The secondary changes (loop iterator signedness in `fill_sg_entry`, overflow guard in `calc_sg_nents`) are reasonable hardening.
The patch is **mostly good** but has a couple of issues worth addressing.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: dma-buf: Fix silent overflow for phys vec to sgt
2026-05-27 20:50 [PATCH v2] dma-buf: Fix silent overflow for phys vec to sgt David Hu
2026-05-28 2:05 ` Claude review: " Claude Code Review Bot
@ 2026-05-28 2:05 ` Claude Code Review Bot
1 sibling, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-05-28 2:05 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Commit message nit:** There's a dangling fragment in the commit message body:
```
to mapped_len, and leading to a silent overflow
```
This line (line 103 of the mbox) looks like leftover text from an earlier draft that wasn't cleaned up. It should be removed before merging.
**`mapped_len` promotion (main fix) — correct:**
```c
- unsigned int nents, mapped_len = 0;
...
+ size_t mapped_len = 0;
+ unsigned int nents;
```
This is the core fix. `mapped_len` accumulates `phys_vec[i].len` values (which are `size_t`) at line 154 of the source:
```c
mapped_len += phys_vec[i].len;
```
With >4GB total MMIO, the old `unsigned int` wraps silently. Then `dma_iova_sync()` and `fill_sg_entry()` receive a truncated length, which is a data-corruption-grade bug. The fix is correct and minimal.
**`fill_sg_entry` loop iterator — correct but cosmetic:**
```c
- int i;
+ unsigned int i;
```
The loop compares `i < nents` where `nents` is `unsigned int`. Using a signed `int` for the iterator means the comparison is well-defined (the signed value gets implicitly converted), so this is not a functional bug, but matching signedness is cleaner and avoids compiler warnings with `-Wsign-compare`. Fine to include.
**`calc_sg_nents` overflow guard — needs attention:**
```c
- unsigned int nents = 0;
+ size_t nents = 0;
...
+ if (nents > UINT_MAX)
+ return 0;
```
The function signature still returns `unsigned int`:
```c
static unsigned int calc_sg_nents(struct dma_iova_state *state, ...)
```
Promoting `nents` to `size_t` locally and clamping to `UINT_MAX` before returning is logically correct — it prevents the intermediate accumulation from overflowing before the check. However, there are concerns:
1. **Returning 0 on overflow is a silent failure.** The caller at line 135-137 does:
```c
nents = calc_sg_nents(dma->state, phys_vec, nr_ranges, size);
ret = sg_alloc_table(&dma->sgt, nents, GFP_KERNEL | __GFP_ZERO);
```
Passing `nents = 0` to `sg_alloc_table()` — which takes `unsigned int nents` — will cause `sg_alloc_table` to fail (it returns `-EINVAL` for 0 entries per the kernel implementation). So the error *will* propagate, but through `sg_alloc_table` failing rather than `calc_sg_nents` explicitly signaling the problem. This works but is fragile — it relies on `sg_alloc_table`'s behavior for a degenerate input rather than the caller explicitly handling the overflow. A `WARN_ON_ONCE` or explicit error return (e.g., returning `UINT_MAX` with a warning, or having the caller check for 0) would make the failure mode more obvious and debuggable.
2. **The non-IOVA path can also overflow.** In the loop:
```c
for (i = 0; i < nr_ranges; i++)
nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
```
Each `phys_vec[i].len` produces at least 1 entry, and `nr_ranges` is `size_t`. If `nr_ranges` is extremely large (though unlikely in practice for MMIO regions), `nents` could still overflow even as `size_t` on 64-bit. The `> UINT_MAX` check after the loop catches this, so it's fine. But the IOVA path with `DIV_ROUND_UP(size, UINT_MAX)` will never exceed `UINT_MAX` on 64-bit since `size` is `size_t` (at most 2^64-1 / (2^32-1) ≈ 2^32), so the check is mostly relevant for the non-IOVA accumulation path.
**Reverse Christmas tree ordering — correct:**
The variable declarations in `dma_buf_phys_vec_to_sgt` are properly reordered by line length:
```c
struct dma_buf_dma *dma;
struct scatterlist *sgl;
size_t mapped_len = 0;
unsigned int nents;
dma_addr_t addr;
size_t i;
int ret;
```
This follows the kernel coding style convention.
**Summary:** The core `mapped_len` overflow fix is correct and important. The `calc_sg_nents` overflow guard works but returning 0 silently is not ideal — consider adding a `WARN_ON_ONCE(nents > UINT_MAX)` before the return so the failure is visible in dmesg rather than silently propagating through `sg_alloc_table`. The dangling text fragment in the commit message ("to mapped_len, and leading to a silent overflow") must be removed.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] dma-buf: Fix silent overflow for phys vec to sgt
@ 2026-05-11 21:42 David Hu
2026-05-16 4:37 ` Claude review: " Claude Code Review Bot
2026-05-16 4:37 ` Claude Code Review Bot
0 siblings, 2 replies; 5+ messages in thread
From: David Hu @ 2026-05-11 21:42 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Kevin Tian, Ankit Agrawal, Jason Gunthorpe, Alex Williamson,
linux-media, dri-devel, linaro-mm-sig, linux-kernel, jmoroni,
David Hu
In case MMIO size is bigger than 4G, and peer2peer
dma goes through host bridge, we trigger the code
path to assign total linked IVOA, greater than 4G
to mapped_len, and leading to a silent overflow
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
Signed-off-by: David Hu <xuehaohu@google.com>
---
drivers/dma-buf/dma-buf-mapping.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..658064140357 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -95,7 +95,8 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
size_t nr_ranges, size_t size,
enum dma_data_direction dir)
{
- unsigned int nents, mapped_len = 0;
+ unsigned int nents = 0;
+ size_t mapped_len = 0;
struct dma_buf_dma *dma;
struct scatterlist *sgl;
dma_addr_t addr;
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread* Claude review: dma-buf: Fix silent overflow for phys vec to sgt
2026-05-11 21:42 [PATCH] " David Hu
@ 2026-05-16 4:37 ` Claude Code Review Bot
2026-05-16 4:37 ` Claude Code Review Bot
1 sibling, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-05-16 4:37 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: dma-buf: Fix silent overflow for phys vec to sgt
Author: David Hu <xuehaohu@google.com>
Patches: 1
Reviewed: 2026-05-16T14:37:12.053368
---
This is a single-patch fix for an integer overflow bug in `dma_buf_phys_vec_to_sgt()`. The variable `mapped_len` was declared as `unsigned int` (32-bit), but it accumulates `phys_vec[i].len` values which are `size_t` (64-bit on 64-bit platforms). When the total MMIO mapping exceeds 4 GiB (e.g., peer-to-peer DMA through a host bridge), `mapped_len` silently wraps, leading to a truncated value being passed to `dma_iova_sync()` and `fill_sg_entry()`.
The fix is correct and minimal — changing `mapped_len` from `unsigned int` to `size_t` matches both the type of `phys_vec[].len` and the `size` parameter signatures of `dma_iova_sync()`, `dma_iova_destroy()`, and `fill_sg_entry()`.
**Verdict: The fix is correct and should be accepted**, with minor commit message nits noted below.
---
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
* Claude review: dma-buf: Fix silent overflow for phys vec to sgt
2026-05-11 21:42 [PATCH] " David Hu
2026-05-16 4:37 ` Claude review: " Claude Code Review Bot
@ 2026-05-16 4:37 ` Claude Code Review Bot
1 sibling, 0 replies; 5+ messages in thread
From: Claude Code Review Bot @ 2026-05-16 4:37 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**The bug:** In `drivers/dma-buf/dma-buf-mapping.c:97-98` (pre-patch), both `nents` and `mapped_len` were declared together as `unsigned int`. The accumulation at line 155:
```c
mapped_len += phys_vec[i].len;
```
adds `size_t` values (since `struct phys_vec` in `include/linux/types.h:173-176` defines `len` as `size_t`) into a 32-bit variable. When total MMIO size exceeds 4 GiB this wraps silently, causing the subsequent `WARN_ON_ONCE(mapped_len != size)` check at line 170 to fire, and more critically, `dma_iova_sync()` and `fill_sg_entry()` to receive a truncated length.
**The fix is correct:**
```c
- unsigned int nents, mapped_len = 0;
+ unsigned int nents = 0;
+ size_t mapped_len = 0;
```
- `size_t` for `mapped_len` matches the types it interacts with: `phys_vec[i].len` (`size_t`), the `size` function parameter (`size_t`), `dma_iova_sync()` size argument (`size_t`), `dma_iova_destroy()` size argument, and `fill_sg_entry()` length argument (`size_t`).
- `nents` correctly remains `unsigned int`, matching the return type of `calc_sg_nents()` and the `sg_alloc_table()` nents parameter.
- Separating the declarations onto two lines is the right call since the types now differ.
**Minor observations:**
1. **Commit message quality:** The commit message is a bit terse and could be clearer. "total linked IVOA" appears to be a typo for "total linked IOVA". The description would benefit from explicitly stating that `mapped_len` was `unsigned int` (32 bits) and is being changed to `size_t` (64 bits), and clarifying the specific consequence (truncated length passed to `dma_iova_sync`/`dma_iova_destroy`).
2. **The `nents = 0` initialization change:** The original code had `nents` implicitly initialized alongside `mapped_len` in the combined declaration `unsigned int nents, mapped_len = 0;` — but note that **only** `mapped_len` was initialized to 0 in the original code; `nents` was left uninitialized. The patch adds `= 0` to `nents`, which is a minor improvement for safety, though `nents` is always assigned from `calc_sg_nents()` before use at line 136, so the initialization is technically unnecessary. This is fine but could be mentioned as a separate cleanup.
3. **No Cc: stable tag:** Given this is a `Fixes:` patch for a potential data corruption / incorrect DMA mapping on >4 GiB MMIO BARs, a `Cc: stable@vger.kernel.org` tag would be appropriate if the fix should be backported.
**No functional issues found.** The patch is minimal, correct, and addresses a real overflow bug on large MMIO regions.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-28 2:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-27 20:50 [PATCH v2] dma-buf: Fix silent overflow for phys vec to sgt David Hu
2026-05-28 2:05 ` Claude review: " Claude Code Review Bot
2026-05-28 2:05 ` Claude Code Review Bot
-- strict thread matches above, loose matches on Subject: below --
2026-05-11 21:42 [PATCH] " David Hu
2026-05-16 4:37 ` Claude review: " Claude Code Review Bot
2026-05-16 4:37 ` Claude Code Review Bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox