Skip to contentSkip to conversation

xen/xsm: Fix xsm_mmu_* and xsm_update_va_mapping hooks

RFC PATCH New Stephen Smalley 1 participant 1 message Feb 2, 2011

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 xen/xsm: Fix xsm_mmu_* and xsm_update_va_mapping hooks

This isn't targeted at 4.1 given the freeze, but is instead just a RFC. This is an attempt to properly fix the hypervisor crash previously described in
http://marc.info/?l=xen-devel&m=128396289707362&w=2

In looking into this issue, I think the proper fix is to move the xsm_mmu_* and xsm_update_va_mapping hook calls later in the callers, after more validation has been performed and the page_info struct is readily available, and pass the page_info to the hooks. This patch moves the xsm_mmu_normal_update, xsm_mmu_machphys_update and xsm_update_va_mapping hook calls accordingly, and updates their interfaces and hook function implementations. This appears to resolve the crashes for me. However, as I am not overly familiar with this area of code, I'd appreciate any feedback or suggestions for improvement. Thanks.

---

 xen/arch/x86/mm.c     |   30 ++++++++++++++++++------------
 xen/include/xsm/xsm.h |   28 +++++++++++++++-------------
 xen/xsm/dummy.c       |   11 ++++++-----
 xen/xsm/flask/hooks.c |   41 ++++++++---------------------------------
 4 files changed, 47 insertions(+), 63 deletions(-)
xen/arch/x86/mm.c +18 -12
@@ -3416,10 +3416,6 @@
         {
             p2m_type_t p2mt;
 
-            rc = xsm_mmu_normal_update(d, pg_owner, req.val);
-            if ( rc )
-                break;
-
             req.ptr -= cmd;
             gmfn = req.ptr >> PAGE_SHIFT;
             mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(pt_owner), gmfn, &p2mt));
@@ -3445,6 +3441,13 @@
                           (unsigned long)(req.ptr & ~PAGE_MASK));
             page = mfn_to_page(mfn);
 
+            rc = xsm_mmu_normal_update(d, req.val, page);
+            if ( rc ) {
+                unmap_domain_page_with_cache(va, &mapcache);
+                put_page(page);
+                break;
+            }
+
             if ( page_lock(page) )
             {
                 switch ( page->u.inuse.type_info & PGT_type_mask )
@@ -3612,10 +3615,6 @@
             mfn = req.ptr >> PAGE_SHIFT;
             gpfn = req.val;
 
-            rc = xsm_mmu_machphys_update(d, mfn);
-            if ( rc )
-                break;
-
             if ( unlikely(!get_page_from_pagenr(mfn, pg_owner)) )
             {
                 MEM_LOG("Could not get page for mach->phys update");
@@ -3628,6 +3627,10 @@
                 break;
             }
 
+            rc = xsm_mmu_machphys_update(d, mfn_to_page(mfn));
+            if ( rc )
+                break;
+
             set_gpfn_from_mfn(mfn, gpfn);
             okay = 1;
 
@@ -4247,10 +4250,6 @@
 
     perfc_incr(calls_to_update_va);
 
-    rc = xsm_update_va_mapping(d, pg_owner, val);
-    if ( rc )
-        return rc;
-
     rc = -EINVAL;
     pl1e = guest_map_l1e(v, va, &gl1mfn);
     if ( unlikely(!pl1e || !get_page_from_pagenr(gl1mfn, d)) )
@@ -4270,6 +4269,13 @@
         goto out;
     }
 
+    rc = xsm_update_va_mapping(d, val, gl1pg);
+    if ( rc ) {
+        page_unlock(gl1pg);
+        put_page(gl1pg);
+        goto out;
+    }
+
     rc = mod_l1_entry(pl1e, val, gl1mfn, 0, v, pg_owner) ? 0 : -EINVAL;
 
     page_unlock(gl1pg);
xen/include/xsm/xsm.h +15 -13
@@ -136,11 +136,12 @@
     int (*getidletime) (void);
     int (*machine_memory_map) (void);
     int (*domain_memory_map) (struct domain *d);
-    int (*mmu_normal_update) (struct domain *d, struct domain *f, 
-                                                                intpte_t fpte);
-    int (*mmu_machphys_update) (struct domain *d, unsigned long mfn);
-    int (*update_va_mapping) (struct domain *d, struct domain *f, 
-                                                            l1_pgentry_t pte);
+    int (*mmu_normal_update) (struct domain *d,
+			      intpte_t fpte, struct page_info *page);
+    int (*mmu_machphys_update) (struct domain *d, struct page_info *page);
+    int (*update_va_mapping) (struct domain *d,
+			      l1_pgentry_t pte,
+			      struct page_info *page);
     int (*add_to_physmap) (struct domain *d1, struct domain *d2);
     int (*sendtrigger) (struct domain *d);
     int (*test_assign_device) (uint32_t machine_bdf);
@@ -567,21 +568,22 @@
     return xsm_call(domain_memory_map(d));
 }
 
-static inline int xsm_mmu_normal_update (struct domain *d, struct domain *f, 
-                                                                intpte_t fpte)
+static inline int xsm_mmu_normal_update (struct domain *d,
+					 intpte_t fpte, struct page_info *page)
 {
-    return xsm_call(mmu_normal_update(d, f, fpte));
+    return xsm_call(mmu_normal_update(d, fpte, page));
 }
 
-static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn)
+static inline int xsm_mmu_machphys_update (struct domain *d, struct page_info *page)
 {
-    return xsm_call(mmu_machphys_update(d, mfn));
+    return xsm_call(mmu_machphys_update(d, page));
 }
 
-static inline int xsm_update_va_mapping(struct domain *d, struct domain *f, 
-                                                            l1_pgentry_t pte)
+static inline int xsm_update_va_mapping(struct domain *d,
+					l1_pgentry_t pte,
+					struct page_info *page)
 {
-    return xsm_call(update_va_mapping(d, f, pte));
+    return xsm_call(update_va_mapping(d, pte, page));
 }
 
 static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2)
xen/xsm/dummy.c +6 -5
@@ -405,19 +405,20 @@
     return 0;
 }
 
-static int dummy_mmu_normal_update (struct domain *d, struct domain *f, 
-                                                                intpte_t fpte)
+static int dummy_mmu_normal_update (struct domain *d,
+				    intpte_t fpte, struct page_info *page)
 {
     return 0;
 }
 
-static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn)
+static int dummy_mmu_machphys_update (struct domain *d, struct page_info *page)
 {
     return 0;
 }
 
-static int dummy_update_va_mapping (struct domain *d, struct domain *f, 
-                                                            l1_pgentry_t pte)
+static int dummy_update_va_mapping (struct domain *d,
+				    l1_pgentry_t pte,
+				    struct page_info *page)
 {
     return 0;
 }
xen/xsm/flask/hooks.c +8 -33

88 lines not on this page · raw message

Signature · 2 lines
Stephen Smalley
National Security Agency