Re: [PATCH v3 2/5] iommu/dma: Catch scatterlist length overflows

Robin Murphy <[email protected]>
Newsgroups org.freedesktop.lists.intel-gfx,dev.linux.lists.iommu,org.freedesktop.lists.dri-devel
Message-ID <[email protected]>
On 13/07/2026 10:58 am, Krzysztof Karas wrote:
> It is possible, when a very large mapping uses only one
> scatterlist, that padding overflows scatterlist's length field.
> This results in:
>   1) silently wrapping the value
>   2) smaller than desired mappings produced by iommu_map_sg
>   3) leaving mapped bytes in memory (no iommu_unmap)
> 
> Address this issue by adding overflow detection for scatterlist
> length field.
> 
> Fixes: 809eac54cdd6 ("iommu/dma: Implement scatterlist segment merging")
> Signed-off-by: Krzysztof Karas <[email protected]>
> ---
> v3:
>   * Used check_add_overflow suggested by Jason.
> 
> I decided not to include previous r-bs due to the change in the
> core of this patch: overflows_type -> check_add_overflow and I
> obvserved some folks have heavy preference for one or the other.
> 
>   drivers/iommu/dma-iommu.c | 13 ++++++++++++-
>   1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 381b60d9e7ce..1a36fd9bf10b 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -1493,7 +1493,18 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
>   		 *   time through here (i.e. before it has a meaningful value).
>   		 */

Sorry to be a pain, but since we *have* now spent the time reasoning 
through the details, for completeness I think it would be worth also 
explicitly checking "s_length & UINT_MAX != 0" (or equivalent) after the 
the prior iova_align() - since that's only rounding up an unsigned int 
value to a power of 2 it can't arbitrarily overflow like the addition 
below, but it could still wrap to zero in the assignment to s->length, 
or indeed in the size_t itself on 32-bit.

>   		if (pad_len && pad_len < s_length - 1) {
> -			prev->length += pad_len;
> +			unsigned int new_pad_len;

Super-nit: "pad_len" is the amount of potential padding from the end of 
the previous segment up to the next segment boundary; the value we're 
calculating here is the updated *total* segment length, so 
"new_prev_len" would be more accurate and a bit clearer - the logic here 
is fiddly enough as it is, so every little helps :)

With those tweaks (since it sounds like there's still another respin or 
two to go for the rest of the series anyway),

Reviewed-by: Robin Murphy <[email protected]>

Cheers,
Robin.

> +			/*
> +			 * For large mappings spanning multiple GBs we
> +			 * may not be able to fit all needed padding into
> +			 * sg->length.
> +			 */
> +			if (check_add_overflow(prev->length, pad_len, &new_pad_len)) {
> +				ret = -EOVERFLOW;
> +				goto out_restore_sg;
> +			}
> +
> +			prev->length = new_pad_len;
>   			iova_len += pad_len;
>   		}
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.