]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommufd: Enforce PASID-compatible domain for RID
authorYi Liu <yi.l.liu@intel.com>
Fri, 21 Mar 2025 17:19:34 +0000 (10:19 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 25 Mar 2025 13:18:31 +0000 (10:18 -0300)
Per the definition of IOMMU_HWPT_ALLOC_PASID, iommufd needs to enforce
the RID to use PASID-compatible domain if PASID has been attached, and
vice versa. The PASID path has already enforced it. This adds the
enforcement in the RID path.

This enforcement requires a lock across the RID and PASID attach path,
the idev->igroup->lock is used as both the RID and the PASID path holds
it.

Link: https://patch.msgid.link/r/20250321171940.7213-13-yi.l.liu@intel.com
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/iommufd/device.c

index 4cc6de03f76ee5c19b1f0c21d0438a1c4ab725b2..1605f6c0e1eee5e01acee30c55f5837d0496ff9f 100644 (file)
@@ -399,8 +399,28 @@ static int iommufd_hwpt_pasid_compat(struct iommufd_hw_pagetable *hwpt,
                                     struct iommufd_device *idev,
                                     ioasid_t pasid)
 {
-       if (pasid != IOMMU_NO_PASID && !hwpt->pasid_compat)
-               return -EINVAL;
+       struct iommufd_group *igroup = idev->igroup;
+
+       lockdep_assert_held(&igroup->lock);
+
+       if (pasid == IOMMU_NO_PASID) {
+               unsigned long start = IOMMU_NO_PASID;
+
+               if (!hwpt->pasid_compat &&
+                   xa_find_after(&igroup->pasid_attach,
+                                 &start, UINT_MAX, XA_PRESENT))
+                       return -EINVAL;
+       } else {
+               struct iommufd_attach *attach;
+
+               if (!hwpt->pasid_compat)
+                       return -EINVAL;
+
+               attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID);
+               if (attach && attach->hwpt && !attach->hwpt->pasid_compat)
+                       return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -411,8 +431,6 @@ static int iommufd_hwpt_attach_device(struct iommufd_hw_pagetable *hwpt,
        struct iommufd_attach_handle *handle;
        int rc;
 
-       lockdep_assert_held(&idev->igroup->lock);
-
        rc = iommufd_hwpt_pasid_compat(hwpt, idev, pasid);
        if (rc)
                return rc;