* [PATCH] iommufd/iova_bitmap: fail GET_DIRTY_BITMAP when a bitmap page cannot be pinned
@ 2026-10-13 17:10 samarth.colleges
0 siblings, 0 replies; only message in thread
From: samarth.colleges @ 2026-10-13 17:10 UTC (permalink / raw)
To: Jason Gunthorpe, Joerg Roedel, Will Deacon
Cc: Robin Murphy, Joao Martins, Kevin Tian, iommu, linux-kernel,
Samarth Narang
From: Samarth Narang <samarth.colleges@gmail.com>
The iova_bitmap_set() function reports dirty IOVAs into a user-provided bitmap, it does so by
pinning the bitmap pages lazily one chunk at a time as the reported IOVA advances.
When advancing to the next chunk fails, the function simply returns without recording the dirty bits.
if (iova_bitmap_advance_to(bitmap, iova))
return;
So on an IOMMU_HWPT_GET_DIRTY_BITMAP ioctl, if any bitmap chunk past the
first cannot be pinned, the dirty pages in that chunk are cleared in the page table,
not set in the bitmap, and the ioctl will still return success.
This means that the destination VM will observe stale memory.
This patch records the first such error in the iova_bitmap and propagates it so the
ioctl fails instead of silently succeeding.
Fixes: 4a00f9434891 ("iommupt: Add read_and_clear_dirty op")
Signed-off-by: Samarth Narang <samarth.colleges@gmail.com>
---
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index 4e447ce74..e6540b0a2 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -589,7 +589,7 @@ iommu_read_and_clear_dirty(struct iommu_domain *domain,
arg.iopt = iopt;
arg.domain = domain;
arg.dirty = &dirty;
- iova_bitmap_for_each(iter, &arg, __iommu_read_and_clear_dirty);
+ ret = iova_bitmap_for_each(iter, &arg, __iommu_read_and_clear_dirty);
if (!(flags & IOMMU_DIRTY_NO_CLEAR))
iommu_iotlb_sync(domain, &gather);
diff --git a/drivers/iommu/iommufd/iova_bitmap.c b/drivers/iommu/iommufd/iova_bitmap.c
index dac3e657d..483f0cc84 100644
--- a/drivers/iommu/iommufd/iova_bitmap.c
+++ b/drivers/iommu/iommufd/iova_bitmap.c
@@ -116,6 +116,9 @@ struct iova_bitmap {
/* length of the IOVA range for the whole bitmap */
size_t length;
+
+ /* first error from pinning a bitmap chunk; -EFAULT etc. */
+ int err;
};
/*
@@ -384,7 +387,9 @@ static int iova_bitmap_advance_to(struct iova_bitmap *bitmap,
int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
iova_bitmap_fn_t fn)
{
- return fn(bitmap, bitmap->iova, bitmap->length, opaque);
+ int ret = fn(bitmap, bitmap->iova, bitmap->length, opaque);
+
+ return ret ? ret : bitmap->err;
}
EXPORT_SYMBOL_NS_GPL(iova_bitmap_for_each, "IOMMUFD");
@@ -411,8 +416,13 @@ void iova_bitmap_set(struct iova_bitmap *bitmap,
* may fail if it's out of bounds, or pinning the pages
* returns an error.
*/
- if (iova_bitmap_advance_to(bitmap, iova))
+ int ret = iova_bitmap_advance_to(bitmap, iova);
+
+ if (ret) {
+ if (!bitmap->err)
+ bitmap->err = ret;
return;
+ }
}
last_page_idx = mapped->npages - 1;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-13 17:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 17:10 [PATCH] iommufd/iova_bitmap: fail GET_DIRTY_BITMAP when a bitmap page cannot be pinned samarth.colleges
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®