XSA-80

CVE-2013-6400


问题描述

http://xenbits.xen.org/xsa/advisory-80.html

IOMMU TLB flushing may be inadvertently suppressed

An internal flag is used to temporarily suppress IOMMU TLB flushes, in order to consolidate multiple single page flushes into one wider flush. This flag is not cleared again, on certain error paths. This can result in TLB flushes not happening when they are needed. Retaining stale TLB entries could allow guests access to memory that ought to have been revoked, or grant greater access than intended.

improper error handling (not clear internal flag)


Patch描述

http://xenbits.xen.org/xsa/xsa82.patch

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.

--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4648,7 +4648,7 @@ static int xenmem_add_to_physmap(struct 
         {
             rc = xenmem_add_to_physmap_once(d, xatp);
             if ( rc < 0 )
-                return rc;
+                break;
 
             xatp->idx++;
             xatp->gpfn++;
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -306,11 +306,11 @@ static int iommu_populate_page_table(str
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
     struct page_info *page;
-    int rc;
+    int rc = 0;
 
+    this_cpu(iommu_dont_flush_iotlb) = 1;
     spin_lock(&d->page_alloc_lock);
 
-    this_cpu(iommu_dont_flush_iotlb) = 1;
     page_list_for_each ( page, &d->page_list )
     {
         if ( is_hvm_domain(d) ||
@@ -320,18 +320,20 @@ static int iommu_populate_page_table(str
             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;
 }

Consequence

Malicious guest administrators might be able to cause host-wide denial of service, or escalate their privilege to that of the host.

DoS, privilege escalation