Skip to content

Commit 31929ae

Browse files
committed
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents d35ac6a + dbe245c commit 31929ae

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

drivers/iommu/iommufd/device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,8 @@ void iommufd_access_unpin_pages(struct iommufd_access *access,
553553
iopt_area_iova_to_index(
554554
area,
555555
min(last_iova, iopt_area_last_iova(area))));
556-
up_read(&iopt->iova_rwsem);
557556
WARN_ON(!iopt_area_contig_done(&iter));
557+
up_read(&iopt->iova_rwsem);
558558
}
559559
EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD);
560560

drivers/iommu/iommufd/io_pagetable.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ static int iopt_unmap_iova_range(struct io_pagetable *iopt, unsigned long start,
458458
{
459459
struct iopt_area *area;
460460
unsigned long unmapped_bytes = 0;
461+
unsigned int tries = 0;
461462
int rc = -ENOENT;
462463

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

488+
if (area_first != start)
489+
tries = 0;
490+
487491
/*
488492
* num_accesses writers must hold the iova_rwsem too, so we can
489493
* safely read it under the write side of the iovam_rwsem
490494
* without the pages->mutex.
491495
*/
492496
if (area->num_accesses) {
497+
size_t length = iopt_area_length(area);
498+
493499
start = area_first;
494500
area->prevent_access = true;
495501
up_write(&iopt->iova_rwsem);
496502
up_read(&iopt->domains_rwsem);
497-
iommufd_access_notify_unmap(iopt, area_first,
498-
iopt_area_length(area));
499-
if (WARN_ON(READ_ONCE(area->num_accesses)))
503+
504+
iommufd_access_notify_unmap(iopt, area_first, length);
505+
/* Something is not responding to unmap requests. */
506+
tries++;
507+
if (WARN_ON(tries > 100))
500508
return -EDEADLOCK;
501509
goto again;
502510
}

0 commit comments

Comments
 (0)