[v11,4/7] iommufd: Use iommufd_access_change_ioas in iommufd_access_destroy_object

Message ID f9fbeca2cde7f8515da18d689b3e02a6a40a5e14.1690523699.git.nicolinc@nvidia.com
State New
Headers
Series Add IO page table replacement support |

Commit Message

Nicolin Chen July 28, 2023, 6:33 a.m. UTC
  Update the unprotect routine in iommufd_access_destroy_object() to calling
the new iommufd_access_change_ioas() helper. This will reduce some risk of
race condition with another concurrent iommufd_access_replace/detach call.

Note that the behavior of this function call is changed: a WARN_ON will be
triggered by a -EBUSY return code if there is another ongoing detach.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommufd/device.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)
  

Comments

Jason Gunthorpe July 28, 2023, 12:42 p.m. UTC | #1
On Thu, Jul 27, 2023 at 11:33:26PM -0700, Nicolin Chen wrote:
> Update the unprotect routine in iommufd_access_destroy_object() to calling
> the new iommufd_access_change_ioas() helper. This will reduce some risk of
> race condition with another concurrent iommufd_access_replace/detach call.
> 
> Note that the behavior of this function call is changed: a WARN_ON will be
> triggered by a -EBUSY return code if there is another ongoing detach.

This should be completely impossible, at this point the object must
have a refcount of 0 so if another thread is concurrently detaching it
we are already UAFing.

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

Jason
  

Patch

diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index e5c408415e95..c0b9cd97ec58 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -753,12 +753,10 @@  void iommufd_access_destroy_object(struct iommufd_object *obj)
 	struct iommufd_access *access =
 		container_of(obj, struct iommufd_access, obj);
 
-	if (access->ioas) {
-		iopt_remove_access(&access->ioas->iopt, access,
-				   access->iopt_access_list_id);
-		refcount_dec(&access->ioas->obj.users);
-		access->ioas = NULL;
-	}
+	mutex_lock(&access->ioas_lock);
+	if (access->ioas)
+		WARN_ON(iommufd_access_change_ioas(access, NULL));
+	mutex_unlock(&access->ioas_lock);
 	iommufd_ctx_put(access->ictx);
 }