When an IOMMU domain with nesting attribute is used for guest SVA, a system-wide PASID is allocated for binding with the device and the domain. For security reason, we need to check the PASID passsed from user-space. e.g. page table bind/unbind and PASID related cache invalidation. Cc: Kevin Tian <kevin.tian@xxxxxxxxx> CC: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> Cc: Alex Williamson <alex.williamson@xxxxxxxxxx> Cc: Eric Auger <eric.auger@xxxxxxxxxx> Cc: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx> Cc: Joerg Roedel <joro@xxxxxxxxxx> Cc: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx> Signed-off-by: Liu Yi L <yi.l.liu@xxxxxxxxx> Signed-off-by: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> --- drivers/iommu/intel-iommu.c | 10 ++++++++++ drivers/iommu/intel-svm.c | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2d59a5d..25650ac 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -5433,6 +5433,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev, int granu = 0; u64 pasid = 0; u64 addr = 0; + void *pdata; granu = to_vtd_granularity(cache_type, inv_info->granularity); if (granu == -EINVAL) { @@ -5452,6 +5453,15 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev, (inv_info->addr_info.flags & IOMMU_INV_ADDR_FLAGS_PASID)) pasid = inv_info->addr_info.pasid; + pdata = ioasid_find(dmar_domain->ioasid_sid, pasid, NULL); + if (!pdata) { + ret = -EINVAL; + goto out_unlock; + } else if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto out_unlock; + } + switch (BIT(cache_type)) { case IOMMU_CACHE_INV_TYPE_IOTLB: /* HW will ignore LSB bits based on address mask */ diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index bf55e2f..49059c1 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -332,7 +332,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, dmar_domain = to_dmar_domain(domain); mutex_lock(&pasid_mutex); - svm = ioasid_find(INVALID_IOASID_SET, data->hpasid, NULL); + svm = ioasid_find(dmar_domain->ioasid_sid, data->hpasid, NULL); if (IS_ERR(svm)) { ret = PTR_ERR(svm); goto out; @@ -450,6 +450,7 @@ int intel_svm_unbind_gpasid(struct iommu_domain *domain, struct iommu_gpasid_unbind_data *data) { struct intel_iommu *iommu = intel_svm_device_to_iommu(dev); + struct dmar_domain *dmar_domain; struct intel_svm_dev *sdev; struct intel_svm *svm; int ret = -EINVAL; @@ -464,9 +465,10 @@ int intel_svm_unbind_gpasid(struct iommu_domain *domain, return -EINVAL; pasid = data->pasid; + dmar_domain = to_dmar_domain(domain); mutex_lock(&pasid_mutex); - svm = ioasid_find(INVALID_IOASID_SET, pasid, NULL); + svm = ioasid_find(dmar_domain->ioasid_sid, pasid, NULL); if (!svm) { ret = -EINVAL; goto out; -- 2.7.4