From: sashiko-bot@kernel.org
To: "David Hu" <dhu@x6u.co>
Cc: dri-devel@lists.freedesktop.org, media-ci@linuxtv.org
Subject: Re: [PATCH v8 1/2] dma-buf: Fix silent overflow for phys vec to sgt
Date: Tue, 01 Sep 2026 17:30:15 +0000 [thread overview]
Message-ID: <20260901173015.D9F081F00A3E@smtp.kernel.org> (raw)
In-Reply-To: <20260901170849.4052816-2-dhu@x6u.co>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Incorrect offset parameter passed to dma_iova_link() causes all physical vectors to overwrite each other at the same IOVA address.
- [Critical] Partial unmapping of DMA mappings via segmented scatterlist entries violates the DMA API.
- [High] DIV_ROUND_UP macro wraps around on 32-bit platforms, causing calc_sg_nents to evaluate to 0 and failing the mapping.
- [High] Setting sgt.orig_nents = 0 breaks sg_free_table, causing a silent memory leak of the scatterlist.
- [High] Error path unmaps all uninitialized scatterlist entries due to an incorrect loop iterator macro shadowing the index.
- [High] IOVA space allocated by dma_iova_try_alloc() is leaked on multiple error paths.
--
commit 3ea75e22b2b7ea7287fcbeb0fa39a0b99a722743
Author: David Hu <xuehaohu@google.com>
dma-buf: Fix silent overflow for phys vec to sgt
This commit changes mapped_len to a 64-bit size_t to prevent silent wrap-around
during length accumulation for MMIO greater than 4G. It also introduces
check_add_overflow() in calc_sg_nents() for safer scatterlist entry
accumulation.
> diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
> index 794acff2546a3..80f6ab2f4809d 100644
> --- a/drivers/dma-buf/dma-buf-mapping.c
> +++ b/drivers/dma-buf/dma-buf-mapping.c
[ ... ]
> @@ -40,8 +41,12 @@ static unsigned int calc_sg_nents(struct dma_iova_state *state,
> size_t i;
>
> if (!state || !dma_use_iova(state)) {
> - for (i = 0; i < nr_ranges; i++)
> - nents += DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
> + for (i = 0; i < nr_ranges; i++) {
> + unsigned int added = DIV_ROUND_UP(phys_vec[i].len, UINT_MAX);
[Severity: High]
This is a pre-existing issue, but could DIV_ROUND_UP wrap around on 32-bit
platforms here?
Since size_t is 32-bit on those architectures, phys_vec[i].len + UINT_MAX - 1
wraps around the maximum 32-bit value. For any chunk length larger than a page,
added will evaluate to 0, completely failing the DMA mapping.
> +
> + if (check_add_overflow(nents, added, &nents))
> + return 0;
> + }
[ ... ]
> @@ -133,6 +139,8 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
> }
>
> nents = calc_sg_nents(dma->state, phys_vec, nr_ranges, size);
> +
> + /* sg_alloc_table will cleanly fail and return -EINVAL if nents == 0 */
> ret = sg_alloc_table(&dma->sgt, nents, GFP_KERNEL | __GFP_ZERO);
> if (ret)
> goto err_free_state;
[Severity: High]
This is a pre-existing issue, but is it possible this jump leaks the allocated
IOVA space?
If sg_alloc_table fails, the jump to err_free_state frees dma->state, but
doesn't call dma_iova_destroy().
Also, since this patch updates this function, I noticed a few other
pre-existing issues further down in dma_buf_phys_vec_to_sgt():
[Severity: Critical]
This is a pre-existing issue, but will the hardcoded zero offset overwrite
mappings at the start of the IOVA space?
In the loop later in this function:
} else if (dma_use_iova(dma->state)) {
ret = dma_iova_link(attach->dev, dma->state,
phys_vec[i].paddr, 0,
phys_vec[i].len, dir,
DMA_ATTR_MMIO);
Passing the literal 0 as the offset for every vector causes all physical
vectors to be mapped to the exact same starting IOVA address. Should this use
the accumulated mapped_len instead?
[Severity: Critical]
This is a pre-existing issue, but does this chunk-by-chunk unmap violate the
DMA API?
The code maps contiguous physical memory as a single chunk:
addr = dma_map_phys(attach->dev, phys_vec[i].paddr,
phys_vec[i].len, dir, DMA_ATTR_MMIO);
But then in fill_sg_entry(), it splits this mapping into multiple scatterlist
entries. During teardown in dma_buf_free_sgt() and err_unmap_dma, it unmaps
these segmented pieces:
for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
dma_unmap_phys(attach->dev, sg_dma_address(sgl),
sg_dma_len(sgl), dir, DMA_ATTR_MMIO);
Can this partial unmapping of a single mapped region corrupt IOMMU state
or cause undefined behavior?
[Severity: High]
This is a pre-existing issue, but does the error path iterate over
uninitialized scatterlist entries and leak IOVA space?
Looking at err_unmap_dma:
err_unmap_dma:
if (!i || !dma->state) {
; /* Do nothing */
If an error occurs on the first loop iteration, the !i check safely returns but
skips dma_iova_destroy(), leaking the IOVA space here as well.
Furthermore, the loop down in that error path shadows the index variable:
} else {
for_each_sgtable_dma_sg(&dma->sgt, sgl, i)
dma_unmap_phys(...)
}
Because for_each_sgtable_dma_sg uses i as its internal iterator (iterating
up to dma->sgt.nents), it resets i to 0 and processes all entries, including
uninitialized zero-elements, rather than stopping at the count of successfully
mapped segments.
[Severity: High]
This is a pre-existing issue, but would clearing orig_nents cause a silent
memory leak?
At the end of dma_buf_phys_vec_to_sgt():
/*
* No CPU list included — set orig_nents = 0 so others can detect
* this via SG table (use nents only).
*/
dma->sgt.orig_nents = 0;
When dma_buf_free_sgt() eventually calls sg_free_table(), the underlying
__sg_free_table() uses table->orig_nents to determine how many chunks to free.
Since it is 0, won't the free loop terminate immediately and silently leak the
entire scatterlist memory allocation?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260901170849.4052816-1-dhu@x6u.co?part=1
next prev parent reply other threads:[~2026-09-01 17:30 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 17:08 [PATCH v8 0/2] dma-buf: Fix silent overflow and alignment David Hu
2026-09-01 17:08 ` [PATCH v8 1/2] dma-buf: Fix silent overflow for phys vec to sgt David Hu
2026-09-01 17:30 ` sashiko-bot [this message]
2026-09-01 17:08 ` [PATCH v8 2/2] dma-buf: Split sgl by largest page-aligned chunk David Hu
2026-09-01 17:30 ` sashiko-bot
2026-09-02 12:08 ` Jason Gunthorpe
2026-09-02 23:07 ` David Hu
2026-09-03 13:49 ` Jason Gunthorpe
2026-09-03 16:36 ` Leon Romanovsky
2026-09-02 7:00 ` [PATCH v8 0/2] dma-buf: Fix silent overflow and alignment Christian König
2026-09-02 7:39 ` Leon Romanovsky
2026-09-02 7:56 ` Christian König
2026-09-02 8:32 ` Leon Romanovsky
2026-09-02 8:44 ` Christian König
2026-09-02 9:53 ` Leon Romanovsky
2026-09-02 10:00 ` Christian König
2026-09-02 10:59 ` Leon Romanovsky
2026-09-02 13:34 ` Christian König
2026-09-02 17:46 ` Jason Gunthorpe
2026-09-02 13:42 ` Pranjal Shrivastava
2026-09-02 12:03 ` Jason Gunthorpe
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=20260901173015.D9F081F00A3E@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.