Skip to content

Commit

Permalink
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/jgg/iommufd

Pull iommufd updates from Jason Gunthorpe:
 "Just two syzkaller fixes, both for the same basic issue: using the
  area pointer during an access forced unmap while the locks protecting
  it were let go"

* tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd:
  iommufd: Call iopt_area_contig_done() under the lock
  iommufd: Do not access the area pointer after unlocking
  • Loading branch information
Linus Torvalds committed Jun 30, 2023
2 parents d35ac6a + dbe245c commit 31929ae
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
2 changes: 1 addition & 1 deletion drivers/iommu/iommufd/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,8 @@ void iommufd_access_unpin_pages(struct iommufd_access *access,
iopt_area_iova_to_index(
area,
min(last_iova, iopt_area_last_iova(area))));
up_read(&iopt->iova_rwsem);
WARN_ON(!iopt_area_contig_done(&iter));
up_read(&iopt->iova_rwsem);
}
EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD);

Expand Down
14 changes: 11 additions & 3 deletions drivers/iommu/iommufd/io_pagetable.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start,
{
struct iopt_area *area;
unsigned long unmapped_bytes = 0;
unsigned int tries = 0;
int rc = -ENOENT;

/*
Expand All @@ -484,19 +485,26 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start,
goto out_unlock_iova;
}

if (area_first != start)
tries = 0;

/*
* num_accesses writers must hold the iova_rwsem too, so we can
* safely read it under the write side of the iovam_rwsem
* without the pages->mutex.
*/
if (area->num_accesses) {
size_t length = iopt_area_length(area);

start = area_first;
area->prevent_access = true;
up_write(&iopt->iova_rwsem);
up_read(&iopt->domains_rwsem);
iommufd_access_notify_unmap(iopt, area_first,
iopt_area_length(area));
if (WARN_ON(READ_ONCE(area->num_accesses)))

iommufd_access_notify_unmap(iopt, area_first, length);
/* Something is not responding to unmap requests. */
tries++;
if (WARN_ON(tries > 100))
return -EDEADLOCK;
goto again;
}
Expand Down

0 comments on commit 31929ae

Please sign in to comment.