Re: [PATCH] vfio: fix VFIO_IOMMU_UNMAP_DMA when end of range would overflow u64

Jason Gunthorpe
2025-10-06T12:16:21Z

On Sun, Oct 05, 2025 at 08:38:42PM -0700, Alex Mastro wrote:
> vfio_find_dma_first_node is called to find the first dma node to unmap
> given an unmap range of [iova..iova+size). The check at the end of the
> function intends to test if the dma result lies beyond the end of the
> unmap range. The condition is incorrectly satisfied when iova+size
> overflows to zero, causing the function to return NULL.
>
> The same issue happens inside vfio_dma_do_unmap's while loop.
>
> Fix by comparing to the inclusive range end, which can be expressed
> by u64.
>
> This bug was discovered after querying for vfio_iova_range's via
> VFIO_IOMMU_GET_INFO, making a VFIO_IOMMU_MAP_DMA inside the last range,
> and then attempting to unmap the entirety of the last range i.e.
> VFIO_IOMMU_UNMAP_DMA(iova=r.start, size=r.end-r.start+1).
>
> ---
> I don't think iommufd is susceptible to the same issue since
> iopt_unmap_iova computes the inclusive end using checked addition, and
> iopt_unmap_iova_range acts on an inclusive range.

Yeah, iommufd was careful to use inclusive ranges so that ULONG_MAX
can be a valid IOVA.

This doesn't seem complete though, if the range ends at the ULONG_MAX
then these are not working either:

if (start < dma->iova + dma->size) {

?

And I see a few more instances like that eg in
vfio_iova_dirty_bitmap(), vfio_dma_do_unmap(), vfio_iommu_replay()

Jason