[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [for-4.15][PATCH v2 4/5] xen/iommu: x86: Don't leak the IOMMU page-tables
From: Julien Grall <jgrall@xxxxxxxxxx> The new IOMMU page-tables allocator will release the pages when relinquish the domain resources. However, this is not sufficient when the domain is dying because nothing prevents page-table to be allocated. iommu_alloc_pgtable() is now checking if the domain is dying before adding the page in the list. We are relying on &hd->arch.pgtables.lock to synchronize d->is_dying. Take the opportunity to check in arch_iommu_domain_destroy() that all that page tables have been freed. Signed-off-by: Julien Grall <jgrall@xxxxxxxxxx> --- There is one more bug that will be solved in the next patch as I felt they each needed a long explanation. Changes in v2: - Rework the approach - Move the patch earlier in the series --- xen/drivers/passthrough/x86/iommu.c | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/xen/drivers/passthrough/x86/iommu.c b/xen/drivers/passthrough/x86/iommu.c index cea1032b3d02..82d770107a47 100644 --- a/xen/drivers/passthrough/x86/iommu.c +++ b/xen/drivers/passthrough/x86/iommu.c @@ -149,6 +149,13 @@ int arch_iommu_domain_init(struct domain *d) void arch_iommu_domain_destroy(struct domain *d) { + /* + * There should be not page-tables left allocated by the time the + * domain is destroyed. Note that arch_iommu_domain_destroy() is + * called unconditionally, so pgtables may be unitialized. + */ + ASSERT(dom_iommu(d)->platform_ops == NULL || + page_list_empty(&dom_iommu(d)->arch.pgtables.list)); } static bool __hwdom_init hwdom_iommu_map(const struct domain *d, @@ -267,6 +274,12 @@ int iommu_free_pgtables(struct domain *d) struct page_info *pg; unsigned int done = 0; + if ( !is_iommu_enabled(d) ) + return 0; + + /* After this barrier no new page allocations can occur. */ + spin_barrier(&hd->arch.pgtables.lock); + while ( (pg = page_list_remove_head(&hd->arch.pgtables.list)) ) { free_domheap_page(pg); @@ -284,6 +297,7 @@ struct page_info *iommu_alloc_pgtable(struct domain *d) unsigned int memflags = 0; struct page_info *pg; void *p; + bool alive = false; #ifdef CONFIG_NUMA if ( hd->node != NUMA_NO_NODE ) @@ -303,9 +317,29 @@ struct page_info *iommu_alloc_pgtable(struct domain *d) unmap_domain_page(p); spin_lock(&hd->arch.pgtables.lock); - page_list_add(pg, &hd->arch.pgtables.list); + /* + * The IOMMU page-tables are freed when relinquishing the domain, but + * nothing prevent allocation to happen afterwards. There is no valid + * reasons to continue to update the IOMMU page-tables while the + * domain is dying. + * + * So prevent page-table allocation when the domain is dying. + * + * We relying on &hd->arch.pgtables.lock to synchronize d->is_dying. + */ + if ( likely(!d->is_dying) ) + { + alive = true; + page_list_add(pg, &hd->arch.pgtables.list); + } spin_unlock(&hd->arch.pgtables.lock); + if ( unlikely(!alive) ) + { + free_domheap_page(pg); + pg = NULL; + } + return pg; } -- 2.17.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |