drivers/iommu/iommufd/io_pagetable.c | 3 +++ 1 file changed, 3 insertions(+)
The division exception occurs because:
The denominator bitmap->bitmap is 0, which is derived from the nil value
of bitmap->data passed in by the reproducer.
Before calling iova_bitmap_alloc() to allocate iter, add a check for a
null value in data to avoid the division exception.
syzbot reported:
divide error in iova_bitmap_alloc
Call Trace:
<TASK>
iommu_read_and_clear_dirty drivers/iommu/iommufd/io_pagetable.c:543 [inline]
iopt_read_and_clear_dirty_data+0x271/0x4c0 drivers/iommu/iommufd/io_pagetable.c:603
iommufd_hwpt_get_dirty_bitmap+0x1c3/0x340 drivers/iommu/iommufd/hw_pagetable.c:485
Reported-by: syzbot+093a8a8b859472e6c257@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=093a8a8b859472e6c257
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
drivers/iommu/iommufd/io_pagetable.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index c0360c450880..9ddaed95e79f 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -540,6 +540,9 @@ iommu_read_and_clear_dirty(struct iommu_domain *domain,
if (!ops || !ops->read_and_clear_dirty)
return -EOPNOTSUPP;
+ if (!bitmap->data)
+ return -EINVAL;
+
iter = iova_bitmap_alloc(bitmap->iova, bitmap->length,
bitmap->page_size,
u64_to_user_ptr(bitmap->data));
--
2.43.0
On Wed, Oct 08, 2025 at 03:53:07PM +0800, Edward Adam Davis wrote:
> The division exception occurs because:
> The denominator bitmap->bitmap is 0, which is derived from the nil value
> of bitmap->data passed in by the reproducer.
No, that just causes the reproducer to bail early. The reported
problem is divide by zero. Which is caused by this:
unsigned long pgsize = 1UL << bitmap->mapped.pgshift;
return iova / (BITS_PER_TYPE(*bitmap->bitmap) * pgsize);
// ioctl$IOMMU_HWPT_GET_DIRTY_BITMAP arguments: [
// fd: fd_iommufd (resource)
// cmd: const = 0x3b8c (4 bytes)
// arg: ptr[in, iommu_hwpt_get_dirty_bitmap] {
// iommu_hwpt_get_dirty_bitmap {
// size: len = 0x30 (4 bytes)
// hwpt_id: hwpt_handle (resource)
// flags: iommufd_hwpt_get_dirty_bitmap_flags = 0x0 (4 bytes)
// __reserved: const = 0x0 (4 bytes)
// iova: int64 = 0x0 (8 bytes)
// length: int64 = 0x0 (8 bytes)
// page_size: int64 = 0x8000000000000000 (8 bytes)
^^^^^^^^^^^^^^^^^^^^^^^^^
0x8000000000000000 * BITS_PER_TYPE(*bitmap->bitmap) == 0
It should be fixed by adjusting the logic:
+ return (iova >> bitmap->mapped.pgshift) /
+ BITS_PER_TYPE(*bitmap->bitmap);
I will send a patch.
Jason
© 2016 - 2026 Red Hat, Inc.