Commit 00939beb authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Will Deacon
Browse files

iommu/vt-d: Fold domain_exit() into intel_iommu_domain_free()



It has only one caller, no need for two functions.

Correct the WARN_ON() error handling to leak the entire page table if the
HW is still referencing it so we don't UAF during WARN_ON recovery.

Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/2-v3-dbbe6f7e7ae3+124ffe-vtd_prep_jgg@nvidia.com


Signed-off-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Link: https://lore.kernel.org/r/20250714045028.958850-5-baolu.lu@linux.intel.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent cd0d0e4e
Loading
Loading
Loading
Loading
+18 −20
Original line number Diff line number Diff line
@@ -1396,23 +1396,6 @@ void domain_detach_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
	}
}

static void domain_exit(struct dmar_domain *domain)
{
	if (domain->pgd) {
		struct iommu_pages_list freelist =
			IOMMU_PAGES_LIST_INIT(freelist);

		domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw), &freelist);
		iommu_put_pages_list(&freelist);
	}

	if (WARN_ON(!list_empty(&domain->devices)))
		return;

	kfree(domain->qi_batch);
	kfree(domain);
}

/*
 * For kdump cases, old valid entries may be cached due to the
 * in-flight DMA and copied pgtable, but there is no unmapping
@@ -3406,9 +3389,24 @@ static void intel_iommu_domain_free(struct iommu_domain *domain)
{
	struct dmar_domain *dmar_domain = to_dmar_domain(domain);

	WARN_ON(dmar_domain->nested_parent &&
		!list_empty(&dmar_domain->s1_domains));
	domain_exit(dmar_domain);
	if (WARN_ON(dmar_domain->nested_parent &&
		    !list_empty(&dmar_domain->s1_domains)))
		return;

	if (WARN_ON(!list_empty(&dmar_domain->devices)))
		return;

	if (dmar_domain->pgd) {
		struct iommu_pages_list freelist =
			IOMMU_PAGES_LIST_INIT(freelist);

		domain_unmap(dmar_domain, 0, DOMAIN_MAX_PFN(dmar_domain->gaw),
			     &freelist);
		iommu_put_pages_list(&freelist);
	}

	kfree(dmar_domain->qi_batch);
	kfree(dmar_domain);
}

int paging_domain_compatible(struct iommu_domain *domain, struct device *dev)