ia64/xen-unstable

changeset 18189:5fbcbee355e2

x86, hvm: Fix issue with user-mode writes to read-only memory.

This patch fixes an issue where a guest could get stuck if a write to
memory marked p2m_ram_ro happened from user mode. It would get
misinterpreted as a user-mode page-table write, and the "dummy write"
emulation necessary to skip over the instruction never got done. In
looking into this, I also discovered that the user-mode page-table
check is done in two places, the second (in emulate_map_dest) of which
can never be reached and is just a waste of cycles. Tim Deegan
requested that rather than completely removing that code, I'd leave it
in for debug-builds with an added warning-print.

Signed-off-by: Trolle Selander <trolle.selander@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 29 13:24:57 2008 +0100 (2008-07-29)
parents eb10a50752bc
children b0ee5e8613e9
files xen/arch/x86/mm/shadow/multi.c
line diff
     1.1 --- a/xen/arch/x86/mm/shadow/multi.c	Tue Jul 29 13:11:29 2008 +0100
     1.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Tue Jul 29 13:24:57 2008 +0100
     1.3 @@ -3359,7 +3359,7 @@ static int sh_page_fault(struct vcpu *v,
     1.4              gdprintk(XENLOG_DEBUG, "guest attempted write to read-only memory"
     1.5                       " page. va page=%#lx, mfn=%#lx\n",
     1.6                       va & PAGE_MASK, mfn_x(gmfn));
     1.7 -        goto emulate; /* skip over the instruction */
     1.8 +        goto emulate_readonly; /* skip over the instruction */
     1.9      }
    1.10  
    1.11      /* In HVM guests, we force CR0.WP always to be set, so that the
    1.12 @@ -3405,6 +3405,11 @@ static int sh_page_fault(struct vcpu *v,
    1.13      }
    1.14  
    1.15      /*
    1.16 +     * Write from userspace to ro-mem needs to jump here to avoid getting
    1.17 +     * caught by user-mode page-table check above.
    1.18 +     */
    1.19 + emulate_readonly:
    1.20 +    /*
    1.21       * We don't need to hold the lock for the whole emulation; we will
    1.22       * take it again when we write to the pagetables.
    1.23       */
    1.24 @@ -4644,11 +4649,6 @@ static void *emulate_map_dest(struct vcp
    1.25      unsigned long offset;
    1.26      void *map = NULL;
    1.27  
    1.28 -    /* We don't emulate user-mode writes to page tables */
    1.29 -    sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt);
    1.30 -    if ( sreg->attr.fields.dpl == 3 )
    1.31 -        return MAPPING_UNHANDLEABLE;
    1.32 -
    1.33      sh_ctxt->mfn1 = emulate_gva_to_mfn(v, vaddr, sh_ctxt);
    1.34      if ( !mfn_valid(sh_ctxt->mfn1) ) 
    1.35          return ((mfn_x(sh_ctxt->mfn1) == BAD_GVA_TO_GFN) ?
    1.36 @@ -4656,6 +4656,17 @@ static void *emulate_map_dest(struct vcp
    1.37                  (mfn_x(sh_ctxt->mfn1) == READONLY_GFN) ?
    1.38                  MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE);
    1.39  
    1.40 +#ifndef NDEBUG
    1.41 +    /* We don't emulate user-mode writes to page tables */
    1.42 +    sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt);
    1.43 +    if ( sreg->attr.fields.dpl == 3 )
    1.44 +    {
    1.45 +        gdprintk(XENLOG_DEBUG, "User-mode write to pagetable reached "
    1.46 +                 "emulate_map_dest(). This should never happen!\n");
    1.47 +        return MAPPING_UNHANDLEABLE;
    1.48 +    }
    1.49 +#endif
    1.50 +                
    1.51      /* Unaligned writes mean probably this isn't a pagetable */
    1.52      if ( vaddr & (bytes - 1) )
    1.53          sh_remove_shadows(v, sh_ctxt->mfn1, 0, 0 /* Slow, can fail */ );