Skip to content

Commit 7a425ec

Browse files
committed
iommufd: Fix refcounting race during mmap
The owner object of the imap can be destroyed while the imap remains in the mtree. So access to the imap pointer without holding locks is racy with destruction. The imap is safe to access outside the lock once a users refcount is obtained, the owner object cannot start destruction until users is 0. Thus the users refcount should not be obtained at the end of iommufd_fops_mmap() but instead inside the mtree lock held around the mtree_load(). Move the refcount there and use refcount_inc_not_zero() as we can have a 0 refcount inside the mtree during destruction races. Link: https://patch.msgid.link/r/[email protected] Cc: [email protected] Fixes: 56e9a0d ("iommufd: Add mmap interface") Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent f83ec76 commit 7a425ec

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

drivers/iommu/iommufd/main.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -550,16 +550,23 @@ static int iommufd_fops_mmap(struct file *filp, struct vm_area_struct *vma)
550550
if (vma->vm_flags & VM_EXEC)
551551
return -EPERM;
552552

553+
mtree_lock(&ictx->mt_mmap);
553554
/* vma->vm_pgoff carries a page-shifted start position to an immap */
554555
immap = mtree_load(&ictx->mt_mmap, vma->vm_pgoff << PAGE_SHIFT);
555-
if (!immap)
556+
if (!immap || !refcount_inc_not_zero(&immap->owner->users)) {
557+
mtree_unlock(&ictx->mt_mmap);
556558
return -ENXIO;
559+
}
560+
mtree_unlock(&ictx->mt_mmap);
561+
557562
/*
558563
* mtree_load() returns the immap for any contained mmio_addr, so only
559564
* allow the exact immap thing to be mapped
560565
*/
561-
if (vma->vm_pgoff != immap->vm_pgoff || length != immap->length)
562-
return -ENXIO;
566+
if (vma->vm_pgoff != immap->vm_pgoff || length != immap->length) {
567+
rc = -ENXIO;
568+
goto err_refcount;
569+
}
563570

564571
vma->vm_pgoff = 0;
565572
vma->vm_private_data = immap;
@@ -570,10 +577,11 @@ static int iommufd_fops_mmap(struct file *filp, struct vm_area_struct *vma)
570577
immap->mmio_addr >> PAGE_SHIFT, length,
571578
vma->vm_page_prot);
572579
if (rc)
573-
return rc;
580+
goto err_refcount;
581+
return 0;
574582

575-
/* vm_ops.open won't be called for mmap itself. */
576-
refcount_inc(&immap->owner->users);
583+
err_refcount:
584+
refcount_dec(&immap->owner->users);
577585
return rc;
578586
}
579587

0 commit comments

Comments
 (0)