FAILED: patch "[PATCH] iommufd: Fix UAF in selftest IOPF reporting" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 8c07df7cdfcf52f1ff276c588612aabc6c6b8399
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090323-coroner-freeload-0b49@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8c07df7cdfcf52f1ff276c588612aabc6c6b8399 Mon Sep 17 00:00:00 2001
From: Peiyang He <[email protected]>
Date: Tue, 11 Aug 2026 17:55:51 +0800
Subject: [PATCH] iommufd: Fix UAF in selftest IOPF reporting
IOMMUFD selftest TRIGGER_IOPF borrows an attach handle from group->pasid_array without synchronizing against PASID detach, then a concurrent iommu_report_device_fault() can dereference that borrowed handle's domain pointer after the detach erases the handle and frees the backing struct iommufd_attach_handle. TRIGGER_IOPF then dereferences the freed handle, causing a UAF.
Fix by adding a iopf_rwsem in mock_dev to follow the expected design of a real driver. Hold its read side across the whole iommu_report_device_fault() call, and its write side around every path that attaches, detaches, or replaces a device domain. This can block new reports and drains in-flight reports before an old attach handle or the IOPF fault parameter can be removed. Also take the write side while registering a mock device, since it can invoke the mock driver's default-domain attach callback.
drivers/iommu/iommufd/selftest.c +30 -1
@@ -178,6 +178,7 @@ struct mock_dev {struct device dev;struct mock_viommu *viommu;struct rw_semaphore viommu_rwsem; +struct rw_semaphore iopf_rwsem;unsigned long flags;unsigned long vdev_id;int id;
@@ -998,6 +999,7 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)return ERR_PTR (-ENOMEM );init_rwsem (&mdev->viommu_rwsem); +init_rwsem (&mdev->iopf_rwsem);device_initialize (&mdev->dev); mdev->flags = dev_flags; mdev->dev.release = mock_dev_release;
@@ -1023,7 +1025,9 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags) goto err_put; } +down_write (&mdev->iopf_rwsem); rc =iommu_mock_device_add (&mdev->dev, &mock_iommu.iommu_dev); +up_write (&mdev->iopf_rwsem);if (rc) goto err_put;return mdev;
@@ -1078,7 +1082,9 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd, } sobj->idev.idev = idev; +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_attach (idev,IOMMU_NO_PASID , &pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_unbind;
@@ -1093,7 +1099,9 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd,return 0 ; out_detach: +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (idev,IOMMU_NO_PASID ); +up_write (&sobj->idev.mock_dev->iopf_rwsem); out_unbind:iommufd_device_unbind (idev); out_mdev:
@@ -1137,7 +1145,9 @@ static int iommufd_test_mock_domain_replace(struct iommufd_ucmd *ucmd,if (IS_ERR (sobj))return PTR_ERR (sobj); +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_replace (sobj->idev.idev,IOMMU_NO_PASID , &pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_sobj;
@@ -1742,10 +1752,16 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd, {struct iopf_fault event = {};struct iommufd_device *idev; +struct mock_dev *mdev; idev =iommufd_get_device (ucmd, cmd->trigger_iopf.dev_id);if (IS_ERR (idev))return PTR_ERR (idev); +if (!iommufd_selftest_is_mock_dev (idev->dev)) { +iommufd_put_object (ucmd->ictx, &idev->obj); +return -EINVAL ; + } + mdev =to_mock_dev (idev->dev); event.fault.prm.flags =IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE ;if (cmd->trigger_iopf.pasid !=IOMMU_NO_PASID )
@@ -1756,7 +1772,9 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd, event.fault.prm.grpid = cmd->trigger_iopf.grpid; event.fault.prm.perm = cmd->trigger_iopf.perm; +down_read (&mdev->iopf_rwsem);iommu_report_device_fault (idev->dev, &event); +up_read (&mdev->iopf_rwsem);iommufd_put_object (ucmd->ictx, &idev->obj);return 0 ;
@@ -1864,14 +1882,19 @@ static int iommufd_test_pasid_attach(struct iommufd_ucmd *ucmd,if (IS_ERR (sobj))return PTR_ERR (sobj); +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_attach (sobj->idev.idev, cmd->pasid_attach.pasid, &cmd->pasid_attach.pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_sobj; rc =iommufd_ucmd_respond (ucmd,sizeof (*cmd)); -if (rc) +if (rc) { +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (sobj->idev.idev, cmd->pasid_attach.pasid); +up_write (&sobj->idev.mock_dev->iopf_rwsem); + } out_sobj:iommufd_put_object (ucmd->ictx, &sobj->obj);
@@ -1888,8 +1911,10 @@ static int iommufd_test_pasid_replace(struct iommufd_ucmd *ucmd,if (IS_ERR (sobj))return PTR_ERR (sobj); +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_replace (sobj->idev.idev, cmd->pasid_attach.pasid, &cmd->pasid_attach.pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_sobj;
@@ -1909,7 +1934,9 @@ static int iommufd_test_pasid_detach(struct iommufd_ucmd *ucmd,if (IS_ERR (sobj))return PTR_ERR (sobj); +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (sobj->idev.idev, cmd->pasid_detach.pasid); +up_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_put_object (ucmd->ictx, &sobj->obj);return 0 ; }
@@ -1920,7 +1947,9 @@ void iommufd_selftest_destroy(struct iommufd_object *obj)switch (sobj->type) {case TYPE_IDEV : +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (sobj->idev.idev,IOMMU_NO_PASID ); +up_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_unbind (sobj->idev.idev);mock_dev_destroy (sobj->idev.mock_dev);break ;
Sasha Levin
maintainerPATCH 1/2 iommufd: Pass @pasid through the device attach/replace path
From: Yi Liu <[email protected]>
[ Upstream commit 03c9b102bea6f4f0b517c841fe1d2f9c616c95b9 ]
Most of the core logic before conducting the actual device attach/ replace operation can be shared with pasid attach/replace. So pass @pasid through the device attach/replace helpers to prepare adding pasid attach/replace.
So far the @pasid should only be IOMMU_NO_PASID. No functional change.
Stable-dep-of: 8c07df7cdfcf ("iommufd: Fix UAF in selftest IOPF reporting")
--- drivers/iommu/iommufd/device.c | 70 +++++++++++++++---------- drivers/iommu/iommufd/hw_pagetable.c | 13 ++--- drivers/iommu/iommufd/iommufd_private.h | 8 +-- 3 files changed, 52 insertions(+), 39 deletions(-)
drivers/iommu/iommufd/device.c +41 -29
@@ -367,7 +367,8 @@ static bool iommufd_device_is_attached(struct iommufd_device *idev) }static int iommufd_hwpt_attach_device (struct iommufd_hw_pagetable *hwpt, -struct iommufd_device *idev) +struct iommufd_device *idev, +ioasid_t pasid) {struct iommufd_attach_handle *handle;int rc;
@@ -385,6 +386,7 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt, } handle->idev = idev; +WARN_ON (pasid !=IOMMU_NO_PASID ); rc =iommu_attach_group_handle (hwpt->domain, idev->igroup->group, &handle->handle);if (rc)
@@ -401,25 +403,28 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt, }static struct iommufd_attach_handle * -iommufd_device_get_attach_handle (struct iommufd_device *idev) +iommufd_device_get_attach_handle (struct iommufd_device *idev,ioasid_t pasid) {struct iommu_attach_handle *handle;lockdep_assert_held (&idev->igroup->lock); handle = -iommu_attach_handle_get (idev->igroup->group,IOMMU_NO_PASID ,0 ); +iommu_attach_handle_get (idev->igroup->group, pasid,0 );if (IS_ERR (handle))return NULL ;return to_iommufd_handle (handle); }static void iommufd_hwpt_detach_device (struct iommufd_hw_pagetable *hwpt, -struct iommufd_device *idev) +struct iommufd_device *idev, +ioasid_t pasid) {struct iommufd_attach_handle *handle; - handle =iommufd_device_get_attach_handle (idev); +WARN_ON (pasid !=IOMMU_NO_PASID ); + + handle =iommufd_device_get_attach_handle (idev, pasid);iommu_detach_group_handle (hwpt->domain, idev->igroup->group);if (hwpt->fault) {iommufd_auto_response_faults (hwpt, handle);
@@ -429,13 +434,17 @@ static void iommufd_hwpt_detach_device(struct iommufd_hw_pagetable *hwpt, }static int iommufd_hwpt_replace_device (struct iommufd_device *idev, +ioasid_t pasid,struct iommufd_hw_pagetable *hwpt,struct iommufd_hw_pagetable *old) { -struct iommufd_attach_handle *handle, *old_handle = -iommufd_device_get_attach_handle (idev); +struct iommufd_attach_handle *handle, *old_handle;int rc; +WARN_ON (pasid !=IOMMU_NO_PASID ); + + old_handle =iommufd_device_get_attach_handle (idev, pasid); + handle =kzalloc (sizeof (*handle),GFP_KERNEL );if (!handle)return -ENOMEM ;
@@ -470,7 +479,7 @@ static int iommufd_hwpt_replace_device(struct iommufd_device *idev, }int iommufd_hw_pagetable_attach (struct iommufd_hw_pagetable *hwpt, -struct iommufd_device *idev) +struct iommufd_device *idev,ioasid_t pasid) {struct iommufd_hwpt_paging *hwpt_paging =find_hwpt_paging (hwpt);int rc;
@@ -496,7 +505,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,* attachment. */ if (list_empty (&idev->igroup->device_list)) { - rc =iommufd_hwpt_attach_device (hwpt, idev); + rc =iommufd_hwpt_attach_device (hwpt, idev, pasid);if (rc) goto err_unresv; idev->igroup->hwpt = hwpt;
@@ -514,7 +523,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, }struct iommufd_hw_pagetable * -iommufd_hw_pagetable_detach (struct iommufd_device *idev) +iommufd_hw_pagetable_detach (struct iommufd_device *idev,ioasid_t pasid) {struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt;struct iommufd_hwpt_paging *hwpt_paging =find_hwpt_paging (hwpt);
@@ -522,7 +531,7 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev)mutex_lock (&idev->igroup->lock);list_del (&idev->group_item);if (list_empty (&idev->igroup->device_list)) { -iommufd_hwpt_detach_device (hwpt, idev); +iommufd_hwpt_detach_device (hwpt, idev, pasid); idev->igroup->hwpt =NULL ; }if (hwpt_paging)
@@ -534,12 +543,12 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev) }static struct iommufd_hw_pagetable * -iommufd_device_do_attach (struct iommufd_device *idev, +iommufd_device_do_attach (struct iommufd_device *idev,ioasid_t pasid,struct iommufd_hw_pagetable *hwpt) {int rc; - rc =iommufd_hw_pagetable_attach (hwpt, idev); + rc =iommufd_hw_pagetable_attach (hwpt, idev, pasid);if (rc)return ERR_PTR (rc);return NULL ;
@@ -588,7 +597,7 @@ iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup, }static struct iommufd_hw_pagetable * -iommufd_device_do_replace (struct iommufd_device *idev, +iommufd_device_do_replace (struct iommufd_device *idev,ioasid_t pasid,struct iommufd_hw_pagetable *hwpt) {struct iommufd_hwpt_paging *hwpt_paging =find_hwpt_paging (hwpt);
@@ -622,7 +631,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, goto err_unlock; } - rc =iommufd_hwpt_replace_device (idev, hwpt, old_hwpt); + rc =iommufd_hwpt_replace_device (idev, pasid, hwpt, old_hwpt);if (rc) goto err_unresv;
@@ -655,7 +664,8 @@ iommufd_device_do_replace(struct iommufd_device *idev, }typedef struct iommufd_hw_pagetable *(*attach_fn )( -struct iommufd_device *idev,struct iommufd_hw_pagetable *hwpt); +struct iommufd_device *idev,ioasid_t pasid, +struct iommufd_hw_pagetable *hwpt);/* * When automatically managing the domains we search for a compatible domain in
@@ -663,7 +673,7 @@ typedef struct iommufd_hw_pagetable *(*attach_fn)(* Automatic domain selection will never pick a manually created domain. */ static struct iommufd_hw_pagetable * -iommufd_device_auto_get_domain (struct iommufd_device *idev, +iommufd_device_auto_get_domain (struct iommufd_device *idev,ioasid_t pasid,struct iommufd_ioas *ioas,u32 *pt_id,attach_fn do_attach) {
@@ -692,7 +702,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, hwpt = &hwpt_paging->common;if (!iommufd_lock_obj (&hwpt->obj))continue ; - destroy_hwpt = (*do_attach)(idev, hwpt); + destroy_hwpt = (*do_attach)(idev, pasid, hwpt);if (IS_ERR (destroy_hwpt)) {iommufd_put_object (idev->ictx, &hwpt->obj);/*
@@ -710,8 +720,8 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, goto out_unlock; } - hwpt_paging =iommufd_hwpt_paging_alloc (idev->ictx, ioas, idev,0 , - immediate_attach,NULL ); + hwpt_paging =iommufd_hwpt_paging_alloc (idev->ictx, ioas, idev, pasid, +0 , immediate_attach,NULL );if (IS_ERR (hwpt_paging)) { destroy_hwpt =ERR_CAST (hwpt_paging); goto out_unlock;
@@ -719,7 +729,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, hwpt = &hwpt_paging->common;if (!immediate_attach) { - destroy_hwpt = (*do_attach)(idev, hwpt); + destroy_hwpt = (*do_attach)(idev, pasid, hwpt);if (IS_ERR (destroy_hwpt)) goto out_abort; }else {
@@ -740,8 +750,9 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,return destroy_hwpt; } -static int iommufd_device_change_pt (struct iommufd_device *idev,u32 *pt_id, -attach_fn do_attach) +static int iommufd_device_change_pt (struct iommufd_device *idev, +ioasid_t pasid, +u32 *pt_id,attach_fn do_attach) {struct iommufd_hw_pagetable *destroy_hwpt;struct iommufd_object *pt_obj;
@@ -756,7 +767,7 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id,struct iommufd_hw_pagetable *hwpt = container_of(pt_obj, struct iommufd_hw_pagetable, obj); - destroy_hwpt = (*do_attach)(idev, hwpt); + destroy_hwpt = (*do_attach)(idev, pasid, hwpt);if (IS_ERR (destroy_hwpt)) goto out_put_pt_obj;break ;
@@ -765,8 +776,8 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id,struct iommufd_ioas *ioas = container_of(pt_obj, struct iommufd_ioas, obj); - destroy_hwpt =iommufd_device_auto_get_domain (idev, ioas, pt_id, - do_attach); + destroy_hwpt =iommufd_device_auto_get_domain (idev, pasid, ioas, + pt_id, do_attach);if (IS_ERR (destroy_hwpt)) goto out_put_pt_obj;break ;
@@ -803,7 +814,8 @@ int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id) {int rc; - rc =iommufd_device_change_pt (idev, pt_id, &iommufd_device_do_attach); + rc =iommufd_device_change_pt (idev,IOMMU_NO_PASID , pt_id, + &iommufd_device_do_attach);if (rc)return rc;
@@ -833,7 +845,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, IOMMUFD);*/ int iommufd_device_replace (struct iommufd_device *idev,u32 *pt_id) { -return iommufd_device_change_pt (idev, pt_id, +return iommufd_device_change_pt (idev,IOMMU_NO_PASID , pt_id, &iommufd_device_do_replace); }EXPORT_SYMBOL_NS_GPL (iommufd_device_replace,IOMMUFD );
@@ -849,7 +861,7 @@ void iommufd_device_detach(struct iommufd_device *idev) {struct iommufd_hw_pagetable *hwpt; - hwpt =iommufd_hw_pagetable_detach (idev); + hwpt =iommufd_hw_pagetable_detach (idev,IOMMU_NO_PASID );iommufd_hw_pagetable_put (idev->ictx, hwpt);refcount_dec (&idev->obj.users); }
drivers/iommu/iommufd/hw_pagetable.c +7 -6
@@ -87,6 +87,7 @@ iommufd_hwpt_paging_enforce_cc(struct iommufd_hwpt_paging *hwpt_paging)* @ictx: iommufd context * @ioas: IOAS to associate the domain with * @idev: Device to get an iommu_domain for +* @pasid: PASID to get an iommu_domain for * @flags: Flags from userspace * @immediate_attach: True if idev should be attached to the hwpt * @user_data: The user provided driver specific data describing the domain to
@@ -102,8 +103,8 @@ iommufd_hwpt_paging_enforce_cc(struct iommufd_hwpt_paging *hwpt_paging)*/ struct iommufd_hwpt_paging *iommufd_hwpt_paging_alloc (struct iommufd_ctx *ictx,struct iommufd_ioas *ioas, -struct iommufd_device *idev,u32 flags, -bool immediate_attach, +struct iommufd_device *idev,ioasid_t pasid, +u32 flags,bool immediate_attach,const struct iommu_user_data *user_data) { const u32 valid_flags = IOMMU_HWPT_ALLOC_NEST_PARENT |
@@ -183,7 +184,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,* sequence. Once those drivers are fixed this should be removed. */ if (immediate_attach) { - rc =iommufd_hw_pagetable_attach (hwpt, idev); + rc =iommufd_hw_pagetable_attach (hwpt, idev, pasid);if (rc) goto out_abort; }
@@ -196,7 +197,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, out_detach:if (immediate_attach) -iommufd_hw_pagetable_detach (idev); +iommufd_hw_pagetable_detach (idev, pasid); out_abort:iommufd_object_abort_and_destroy (ictx, &hwpt->obj);return ERR_PTR (rc);
@@ -299,8 +300,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) ioas = container_of(pt_obj, struct iommufd_ioas, obj);mutex_lock (&ioas->mutex); hwpt_paging =iommufd_hwpt_paging_alloc ( - ucmd->ictx, ioas, idev, cmd->flags, false, - user_data.len ? &user_data :NULL ); + ucmd->ictx, ioas, idev,IOMMU_NO_PASID , cmd->flags, + false, user_data.len ? &user_data :NULL );if (IS_ERR (hwpt_paging)) { rc =PTR_ERR (hwpt_paging); goto out_unlock;
drivers/iommu/iommufd/iommufd_private.h +4 -4
@@ -365,13 +365,13 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd);struct iommufd_hwpt_paging *iommufd_hwpt_paging_alloc (struct iommufd_ctx *ictx,struct iommufd_ioas *ioas, -struct iommufd_device *idev,u32 flags, -bool immediate_attach, +struct iommufd_device *idev,ioasid_t pasid, +u32 flags,bool immediate_attach,const struct iommu_user_data *user_data);int iommufd_hw_pagetable_attach (struct iommufd_hw_pagetable *hwpt, -struct iommufd_device *idev); +struct iommufd_device *idev,ioasid_t pasid);struct iommufd_hw_pagetable * -iommufd_hw_pagetable_detach (struct iommufd_device *idev); +iommufd_hw_pagetable_detach (struct iommufd_device *idev,ioasid_t pasid);void iommufd_hwpt_paging_destroy (struct iommufd_object *obj);void iommufd_hwpt_paging_abort (struct iommufd_object *obj);void iommufd_hwpt_nested_destroy (struct iommufd_object *obj);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 iommufd: Fix UAF in selftest IOPF reporting
From: Peiyang He <[email protected]>
[ Upstream commit 8c07df7cdfcf52f1ff276c588612aabc6c6b8399 ]
IOMMUFD selftest TRIGGER_IOPF borrows an attach handle from group->pasid_array without synchronizing against PASID detach, then a concurrent iommu_report_device_fault() can dereference that borrowed handle's domain pointer after the detach erases the handle and frees the backing struct iommufd_attach_handle. TRIGGER_IOPF then dereferences the freed handle, causing a UAF.
Fix by adding a iopf_rwsem in mock_dev to follow the expected design of a real driver. Hold its read side across the whole iommu_report_device_fault() call, and its write side around every path that attaches, detaches, or replaces a device domain. This can block new reports and drains in-flight reports before an old attach handle or the IOPF fault parameter can be removed. Also take the write side while registering a mock device, since it can invoke the mock driver's default-domain attach callback.
--- drivers/iommu/iommufd/selftest.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
drivers/iommu/iommufd/selftest.c +20 -0
@@ -138,6 +138,7 @@ enum selftest_obj_type {struct mock_dev {struct device dev; +struct rw_semaphore iopf_rwsem;unsigned long flags;int id; };
@@ -701,6 +702,7 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)if (!mdev)return ERR_PTR (-ENOMEM ); +init_rwsem (&mdev->iopf_rwsem);device_initialize (&mdev->dev); mdev->flags = dev_flags; mdev->dev.release = mock_dev_release;
@@ -715,7 +717,9 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)if (rc) goto err_put; +down_write (&mdev->iopf_rwsem); rc =device_add (&mdev->dev); +up_write (&mdev->iopf_rwsem);if (rc) goto err_put;return mdev;
@@ -770,7 +774,9 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd, } sobj->idev.idev = idev; +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_attach (idev, &pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_unbind;
@@ -785,7 +791,9 @@ static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd,return 0 ; out_detach: +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (idev); +up_write (&sobj->idev.mock_dev->iopf_rwsem); out_unbind:iommufd_device_unbind (idev); out_mdev:
@@ -819,7 +827,9 @@ static int iommufd_test_mock_domain_replace(struct iommufd_ucmd *ucmd, goto out_dev_obj; } +down_write (&sobj->idev.mock_dev->iopf_rwsem); rc =iommufd_device_replace (sobj->idev.idev, &pt_id); +up_write (&sobj->idev.mock_dev->iopf_rwsem);if (rc) goto out_dev_obj;
@@ -1415,10 +1425,16 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd, {struct iopf_fault event = { };struct iommufd_device *idev; +struct mock_dev *mdev; idev =iommufd_get_device (ucmd, cmd->trigger_iopf.dev_id);if (IS_ERR (idev))return PTR_ERR (idev); +if (!iommufd_selftest_is_mock_dev (idev->dev)) { +iommufd_put_object (ucmd->ictx, &idev->obj); +return -EINVAL ; + } + mdev = container_of(idev->dev, struct mock_dev, dev); event.fault.prm.flags =IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE ;if (cmd->trigger_iopf.pasid !=IOMMU_NO_PASID )
@@ -1429,7 +1445,9 @@ static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd, event.fault.prm.grpid = cmd->trigger_iopf.grpid; event.fault.prm.perm = cmd->trigger_iopf.perm; +down_read (&mdev->iopf_rwsem);iommu_report_device_fault (idev->dev, &event); +up_read (&mdev->iopf_rwsem);iommufd_put_object (ucmd->ictx, &idev->obj);return 0 ;
@@ -1441,7 +1459,9 @@ void iommufd_selftest_destroy(struct iommufd_object *obj)switch (sobj->type) {case TYPE_IDEV : +down_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_detach (sobj->idev.idev); +up_write (&sobj->idev.mock_dev->iopf_rwsem);iommufd_device_unbind (sobj->idev.idev);mock_dev_destroy (sobj->idev.mock_dev);break ;
Signature · 1 line
2.53.0