Skip to content

Commit a11ad14

Browse files
sina-openaigregkh
authored andcommitted
iommufd: Fix a race with concurrent allocation and unmap
commit 8602018 upstream. iopt_unmap_iova_range() releases the lock on iova_rwsem inside the loop body when getting to the more expensive unmap operations. This is fine on its own, except the loop condition is based on the first area that matches the unmap address range. If a concurrent call to map picks an area that was unmapped in previous iterations, the loop mistakenly tries to unmap it. This is reproducible by having one userspace thread map buffers and pass them to another thread that unmaps them. The problem manifests as EBUSY errors with single page mappings. Fix this by advancing the start pointer after unmapping an area. This ensures each iteration only examines the IOVA range that remains mapped, which is guaranteed not to have overlaps. Cc: stable@vger.kernel.org Fixes: 51fe614 ("iommufd: Data structure to provide IOVA to PFN mapping") Link: https://patch.msgid.link/r/CAAJpGJSR4r_ds1JOjmkqHtsBPyxu8GntoeW08Sk5RNQPmgi+tg@mail.gmail.com Signed-off-by: Sina Hassani <sina@openai.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5b8d6a9 commit a11ad14

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

drivers/iommu/iommufd/io_pagetable.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,16 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start,
724724
unmapped_bytes += area_last - area_first + 1;
725725

726726
down_write(&iopt->iova_rwsem);
727+
728+
/*
729+
* After releasing the iova_rwsem concurrent allocation could
730+
* place new areas at IOVAs we have already unmapped. Keep
731+
* moving the start of the search forward to ignore the area
732+
* already unmapped.
733+
*/
734+
if (area_last >= last)
735+
break;
736+
start = area_last + 1;
727737
}
728738

729739
out_unlock_iova:

0 commit comments

Comments
 (0)