From: sashiko-bot@kernel.org
To: dhu@x6u.co
Cc: dri-devel@lists.freedesktop.org, media-ci@linuxtv.org
Subject: Re: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk
Date: Wed, 22 Jul 2026 23:59:43 +0000 [thread overview]
Message-ID: <20260722235943.E7EFC1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260722233932.3997681-1-dhu@x6u.co>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Integer Overflow / NULL Pointer Dereference in sg mapping calculation
Pre-existing issues:
- [High] 32-bit Integer Overflow causing incomplete DMA mappings
- [High] DMA API Violation (Mismatched Map/Unmap Size)
- [High] IOVA Resource Leak on Error Paths
--
--- Patch [1]: [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk ---
commit 6c6b736bcfe57779f8dd4452cee1c6738c03f76d
Author: David Hu <xuehaohu@google.com>
dma-buf: Split sgl by largest page-aligned chunk
This commit updates scatterlist chunking in dma-buf to use
ALIGN_DOWN(UINT_MAX, PAGE_SIZE) instead of UINT_MAX. This ensures that
scatterlist DMA addresses and lengths remain strictly page-aligned, which
avoids truncation on hardware engines and fixes a fallback issue in
ib_umem_find_best_pgsz().
Closes: https://lore.kernel.org/all/20260609165431.778061F00893@smtp.kernel.org/
Fixes: 3aa31a8bb11e ("dma-buf: provide phys_vec to scatter-gather mapping routine")
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..50ded9daf5fb3 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
[ ... ]
> @@ -24,8 +25,10 @@ static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
> * does not require the CPU list for mapping or unmapping.
> */
> sg_set_page(sgl, NULL, 0, 0);
[Severity: High]
Does this new while loop correctly handle an undersized scatterlist?
If calc_sg_nents() returns 0 due to the 32-bit overflow mentioned below,
this while loop still processes the full length. It will exhaust the
SGL entries, receive a NULL from sg_next(), and dereference it during
the next call to sg_set_page().
> - sg_dma_address(sgl) = addr + (dma_addr_t)i * UINT_MAX;
> + sg_dma_address(sgl) = addr;
> sg_dma_len(sgl) = len;
> + addr += len;
> + /* Unconditionally advance. On last segment, this becomes NULL */
> sgl = sg_next(sgl);
> }
>
> @@ -41,14 +44,14 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
>
> if (!state || !dma_use_iova(state)) {
> for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + nents += DIV_ROUND_UP(phys_vec[i].len, MAX_SG_ENT_SZ);
^^^^
[Severity: High]
Can this DIV_ROUND_UP() overflow on 32-bit platforms?
MAX_SG_ENT_SZ is ALIGN_DOWN(0xFFFFFFFF, PAGE_SIZE), which is 0xFFFFF000.
The DIV_ROUND_UP(len, MAX_SG_ENT_SZ) expands to
(len + 0xFFFFF000 - 1) / 0xFFFFF000. If len is 4097 or greater, this
addition overflows a 32-bit integer and wraps around, yielding 0. This
allocates 0 scatterlist entries for that chunk.
> } else {
> /*
> * In IOVA case, there is only one SG entry which spans
> * for whole IOVA address space, but we need to make sure
> * that it fits sg->length, maybe we need more.
> */
> - nents = DIV_ROUND_UP(size, UINT_MAX);
> + nents = DIV_ROUND_UP(size, MAX_SG_ENT_SZ);
[Severity: High]
Similarly, can this calculation overflow in the IOVA case when processing
sizes >= 4097 bytes on a 32-bit platform?
> }
>
> return nents;
[ ... ]
While reviewing this code, I noticed a few pre-existing issues in the same
file that you might want to address:
[Severity: High]
This isn't a bug introduced by this patch, but does mapped_len silently wrap
around on 64-bit platforms?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
unsigned int nents, mapped_len = 0;
[ ... ]
for (i = 0; i < nr_ranges; i++) {
[ ... ]
mapped_len += phys_vec[i].len;
}
}
Because mapped_len is a 32-bit unsigned int and phys_vec[i].len is a 64-bit
size_t, calculating a total mapping size larger than 4GB overflows mapped_len.
[Severity: High]
This isn't a bug introduced by this patch, but does the error path leak the
IOVA allocation?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
[ ... ]
dma_iova_try_alloc(attach->dev, dma->state, 0, size);
[ ... ]
ret = sg_alloc_table(&dma->sgt, nents, GFP_KERNEL | __GFP_ZERO);
if (ret)
goto err_free_state;
[ ... ]
err_unmap_dma:
if (!i || !dma->state) {
; /* Do nothing */
} else if (dma_use_iova(dma->state)) {
dma_iova_destroy(attach->dev, dma->state, mapped_len, dir,
DMA_ATTR_MMIO);
[ ... ]
}
If sg_alloc_table() fails, the code branches to err_free_state, returning
without calling dma_iova_destroy(). Additionally, if mapping the first range
fails (i == 0), the err_unmap_dma path executes the empty if-block and skips
cleanup.
[Severity: High]
This isn't a bug introduced by this patch, but does this unmap sequence
violate the requirement to match map and unmap sizes?
drivers/dma-buf/dma-buf-mapping.c:dma_buf_phys_vec_to_sgt() {
[ ... ]
addr = dma_map_phys(attach->dev, phys_vec[i].paddr,
phys_vec[i].len, dir, DMA_ATTR_MMIO);
[ ... ]
}
drivers/dma-buf/dma-buf-mapping.c:dma_buf_free_sgt() {
[ ... ]
for_each_sgtable_dma_sg(sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
[ ... ]
}
The physical memory regions are mapped as single, contiguous blocks using
phys_vec[i].len, but the teardown path unmaps them in smaller chunks
iterating over the split scatterlist.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260722233932.3997681-1-dhu@x6u.co?part=1
next prev parent reply other threads:[~2026-07-22 23:59 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-21 22:21 [PATCH] dma-buf: Split sgl by largest page-aligned chunk David Hu
2026-06-21 22:34 ` sashiko-bot
2026-06-22 8:13 ` David Laight
2026-06-22 21:26 ` David Hu
2026-06-23 8:25 ` David Laight
2026-06-23 21:03 ` David Hu
2026-06-23 1:54 ` [PATCH v2] dma-buf: Split sgl into page-aligned 2G chunks David Hu
2026-06-23 2:08 ` sashiko-bot
2026-06-23 8:44 ` David Laight
2026-06-23 20:55 ` Pranjal Shrivastava
2026-06-23 22:53 ` David Laight
2026-06-24 14:31 ` Leon Romanovsky
2026-06-30 12:42 ` Jason Gunthorpe
2026-07-02 4:56 ` David Hu
2026-07-02 8:10 ` David Laight
2026-07-03 4:11 ` David Hu
2026-06-30 12:38 ` Jason Gunthorpe
2026-07-22 23:38 ` [PATCH v3] dma-buf: Split sgl by largest page-aligned chunk dhu
2026-07-23 0:02 ` sashiko-bot
2026-07-22 23:39 ` dhu
2026-07-22 23:59 ` sashiko-bot [this message]
[not found] ` <20260723094625.GE110966@unreal>
2026-07-23 16:07 ` David Hu
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=20260722235943.E7EFC1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dhu@x6u.co \
--cc=dri-devel@lists.freedesktop.org \
--cc=media-ci@linuxtv.org \
--cc=sashiko-reviews@lists.linux.dev \
/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