[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Fix ptwr_do_page_fault() after new more permissive



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxxxx
# Node ID 5d44f3ab9950bf2adde2baa0b54221eba1698fc5
# Parent  8eab9f3cdb1ad1bf84e1f325a15dfdb9774a8ac8
[XEN] Fix ptwr_do_page_fault() after new more permissive
entry conditions to that function. Now that we no longer
check PGERR_page_present (i.e., that fault is a protection
fault), because it's not safe to do so, we can enter
ptwr_do_page_fault() with a not-present L2 page directory.
We then crash on our first access to the linear_l2_table.
This patch fixes all unprotected accesses to the
linear_l2_table to correctly handle faults.

Also move setup of globally-visible ptwr info record to end
of ptwr_do_page_fault(). We don't want the info picked up
by reentrant invocations of the page-fault handler.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/mm.c |   42 ++++++++++++++++++++++++++----------------
 1 files changed, 26 insertions(+), 16 deletions(-)

diff -r 8eab9f3cdb1a -r 5d44f3ab9950 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Sun Jun 18 19:49:31 2006 +0100
+++ b/xen/arch/x86/mm.c Mon Jun 19 10:18:39 2006 +0100
@@ -3495,11 +3495,13 @@ int ptwr_do_page_fault(struct domain *d,
     /*
      * Attempt to read the PTE that maps the VA being accessed. By checking for
      * PDE validity in the L2 we avoid many expensive fixups in __get_user().
-     * NB. The L2 entry cannot be detached as the caller already checked that.
+     * NB. The L2 entry cannot be detached due to existing ptwr work: the
+     * caller already checked that.
      */
-    if ( !(l2e_get_flags(__linear_l2_table[l2_linear_offset(addr)]) &
-           _PAGE_PRESENT) ||
-         __copy_from_user(&pte,&linear_pg_table[l1_linear_offset(addr)],
+    pl2e = &__linear_l2_table[l2_linear_offset(addr)];
+    if ( __copy_from_user(&l2e, pl2e, sizeof(l2e)) ||
+        !(l2e_get_flags(l2e) & _PAGE_PRESENT) ||
+         __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)],
                           sizeof(pte)) )
     {
         return 0;
@@ -3617,18 +3619,16 @@ int ptwr_do_page_fault(struct domain *d,
                 "pfn %lx\n", PTWR_PRINT_WHICH, addr,
                 l2_idx << L2_PAGETABLE_SHIFT, pfn);
 
-    d->arch.ptwr[which].l1va   = addr | 1;
-    d->arch.ptwr[which].l2_idx = l2_idx;
-    d->arch.ptwr[which].vcpu   = current;
-
-#ifdef PERF_ARRAYS
-    d->arch.ptwr[which].eip    = regs->eip;
-#endif
-
     /* For safety, disconnect the L1 p.t. page from current space. */
     if ( which == PTWR_PT_ACTIVE )
     {
-        l2e_remove_flags(*pl2e, _PAGE_PRESENT);
+        l2e_remove_flags(l2e, _PAGE_PRESENT);
+        if ( unlikely(__copy_to_user(pl2e, &l2e, sizeof(l2e))) )
+        {
+            MEM_LOG("ptwr: Could not unhook l2e at %p", pl2e);
+            domain_crash(d);
+            return 0;
+        }
         flush_tlb_mask(d->domain_dirty_cpumask);
     }
     
@@ -3642,14 +3642,24 @@ int ptwr_do_page_fault(struct domain *d,
     if ( unlikely(__put_user(pte.l1,
                              &linear_pg_table[l1_linear_offset(addr)].l1)) )
     {
-        MEM_LOG("ptwr: Could not update pte at %p", (unsigned long *)
+        MEM_LOG("ptwr: Could not update pte at %p",
                 &linear_pg_table[l1_linear_offset(addr)]);
-        /* Toss the writable pagetable state and crash. */
-        d->arch.ptwr[which].l1va = 0;
         domain_crash(d);
         return 0;
     }
     
+    /*
+     * Now record the writable pagetable state *after* any accesses that can
+     * cause a recursive page fault (i.e., those via the *_user() accessors).
+     * Otherwise we can enter ptwr_flush() with half-done ptwr state.
+     */
+    d->arch.ptwr[which].l1va   = addr | 1;
+    d->arch.ptwr[which].l2_idx = l2_idx;
+    d->arch.ptwr[which].vcpu   = current;
+#ifdef PERF_ARRAYS
+    d->arch.ptwr[which].eip    = regs->eip;
+#endif
+
     return EXCRET_fault_fixed;
 
  emulate:

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.