mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
IOMMU: clear "don't flush" override on error paths
Both xenmem_add_to_physmap() and iommu_populate_page_table() each have an error path that fails to clear that flag, thus suppressing further flushes on the respective pCPU. In iommu_populate_page_table() also slightly re-arrange code to avoid the false impression of the flag in question being guarded by a domain's page_alloc_lock. This is CVE-2013-6400 / XSA-80. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
5da5288a0a
commit
552b7fcb9a
2 files changed
+15
-13
No files matched your search
+1
-1
@@ -4648,7 +4648,7 @@ static int xenmem_add_to_physmap(struct domain *d,
|
||||
{
|
||||
rc = xenmem_add_to_physmap_once(d, xatp);
|
||||
if ( rc < 0 )
|
||||
return rc;
|
||||
break;
|
||||
|
||||
xatp->idx++;
|
||||
xatp->gpfn++;
|
||||
|
||||
@@ -322,11 +322,11 @@ static int iommu_populate_page_table(struct domain *d)
|
||||
{
|
||||
struct hvm_iommu *hd = domain_hvm_iommu(d);
|
||||
struct page_info *page;
|
||||
int rc;
|
||||
|
||||
spin_lock(&d->page_alloc_lock);
|
||||
int rc = 0;
|
||||
|
||||
this_cpu(iommu_dont_flush_iotlb) = 1;
|
||||
spin_lock(&d->page_alloc_lock);
|
||||
|
||||
page_list_for_each ( page, &d->page_list )
|
||||
{
|
||||
if ( is_hvm_domain(d) ||
|
||||
@@ -336,18 +336,20 @@ static int iommu_populate_page_table(struct domain *d)
|
||||
rc = hd->platform_ops->map_page(
|
||||
d, mfn_to_gmfn(d, page_to_mfn(page)), page_to_mfn(page),
|
||||
IOMMUF_readable|IOMMUF_writable);
|
||||
if (rc)
|
||||
{
|
||||
spin_unlock(&d->page_alloc_lock);
|
||||
hd->platform_ops->teardown(d);
|
||||
return rc;
|
||||
}
|
||||
if ( rc )
|
||||
break;
|
||||
}
|
||||
}
|
||||
this_cpu(iommu_dont_flush_iotlb) = 0;
|
||||
iommu_iotlb_flush_all(d);
|
||||
|
||||
spin_unlock(&d->page_alloc_lock);
|
||||
return 0;
|
||||
this_cpu(iommu_dont_flush_iotlb) = 0;
|
||||
|
||||
if ( !rc )
|
||||
iommu_iotlb_flush_all(d);
|
||||
else
|
||||
hd->platform_ops->teardown(d);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||