]> git.ipfire.org Git - thirdparty/kernel/linux.git/commit
iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read()
authorNicolin Chen <nicolinc@nvidia.com>
Mon, 1 Jun 2026 20:42:37 +0000 (13:42 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Fri, 5 Jun 2026 14:07:12 +0000 (11:07 -0300)
commit091ab6d70dc444f56ed14faedbcacfc979f4c613
treeafaf30e098c947ef6c4cabdcf423c41f403ed920
parent172fc8b19825a0f5884c38f2289188284e2d45ee
iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read()

The cookie returned by xa_alloc() in iommufd_fault_fops_read() is per fault
group, but the inner copy_to_user() runs per fault inside the group. If a
copy fails mid-group, xa_erase clears the cookie and the group is restored
to the deliver list, yet done is not rolled back. The function returns the
partial byte count, with the successfully copied faults sitting at offsets
below done carrying the now-erased cookie. The next read() then re-fetches
the group, allocates a fresh cookie, and re-delivers every fault including
the ones already copied; userspace sees duplicates carrying the new cookie,
and a stale cookie that can never be responded to.

Use a local group_done variable that tracks the per-group progress inside
the inner loop, and only commit done = group_done after the inner loop has
finished successfully. On a copy_to_user failure the outer break skips the
commit, so done remains at its prior start-of-group baseline; the partial
bytes already written past done are undefined to userspace per the read(2)
contract, and the next read re-delivers the whole group atomically.

Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object")
Link: https://patch.msgid.link/r/360cab4d4aeccb0bae275a970e2b3c340a71e0e0.1780343944.git.nicolinc@nvidia.com
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/iommufd/eventq.c