diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-07-29 13:24:57 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-07-29 13:24:57 +0100 |
commit | e8ea651a7a504a7307d22fbbb06dfcb39204cbd3 (patch) | |
tree | 01fa9c5b36ac85eda7fc4a4fd70f9dd74d6892ab | |
parent | 8d375aa1744b012e9139a9fe3d560c61bb1fe437 (diff) | |
download | xen-e8ea651a7a504a7307d22fbbb06dfcb39204cbd3.tar.gz xen-e8ea651a7a504a7307d22fbbb06dfcb39204cbd3.tar.bz2 xen-e8ea651a7a504a7307d22fbbb06dfcb39204cbd3.zip |
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>
-rw-r--r-- | xen/arch/x86/mm/shadow/multi.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 209a14055b..6df3f6e6bb 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3359,7 +3359,7 @@ static int sh_page_fault(struct vcpu *v, gdprintk(XENLOG_DEBUG, "guest attempted write to read-only memory" " page. va page=%#lx, mfn=%#lx\n", va & PAGE_MASK, mfn_x(gmfn)); - goto emulate; /* skip over the instruction */ + goto emulate_readonly; /* skip over the instruction */ } /* In HVM guests, we force CR0.WP always to be set, so that the @@ -3405,6 +3405,11 @@ static int sh_page_fault(struct vcpu *v, } /* + * Write from userspace to ro-mem needs to jump here to avoid getting + * caught by user-mode page-table check above. + */ + emulate_readonly: + /* * We don't need to hold the lock for the whole emulation; we will * take it again when we write to the pagetables. */ @@ -4644,11 +4649,6 @@ static void *emulate_map_dest(struct vcpu *v, unsigned long offset; void *map = NULL; - /* We don't emulate user-mode writes to page tables */ - sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); - if ( sreg->attr.fields.dpl == 3 ) - return MAPPING_UNHANDLEABLE; - sh_ctxt->mfn1 = emulate_gva_to_mfn(v, vaddr, sh_ctxt); if ( !mfn_valid(sh_ctxt->mfn1) ) return ((mfn_x(sh_ctxt->mfn1) == BAD_GVA_TO_GFN) ? @@ -4656,6 +4656,17 @@ static void *emulate_map_dest(struct vcpu *v, (mfn_x(sh_ctxt->mfn1) == READONLY_GFN) ? MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE); +#ifndef NDEBUG + /* We don't emulate user-mode writes to page tables */ + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + if ( sreg->attr.fields.dpl == 3 ) + { + gdprintk(XENLOG_DEBUG, "User-mode write to pagetable reached " + "emulate_map_dest(). This should never happen!\n"); + return MAPPING_UNHANDLEABLE; + } +#endif + /* Unaligned writes mean probably this isn't a pagetable */ if ( vaddr & (bytes - 1) ) sh_remove_shadows(v, sh_ctxt->mfn1, 0, 0 /* Slow, can fail */ ); |