x86/shadow: correct SH_LINEAR mapping detection in sh_guess_wrmap()

The fix for XSA-243 / CVE-2017-15592 (c/s bf2b4eadcf) introduced a change
in behaviour for sh_guest_wrmap(), where it had to cope with no shadow linear
mapping being present.

As the name suggests, guest_vtable is a mapping of the guests pagetable, not
Xen's pagetable, meaning that it isn't the pagetable we need to check for the
shadow linear slot in.

The practical upshot is that a shadow HVM vcpu which switches into 4-level
paging mode, with an L4 pagetable that contains a mapping which aliases Xen's
SH_LINEAR_PT_VIRT_START will fool the safety check for whether a SHADOW_LINEAR
mapping is present.  As the check passes (when it should have failed), Xen
subsequently falls over the missing mapping with a pagefault such as:

    (XEN) Pagetable walk from ffff8140a0503880:
    (XEN)  L4[0x102] = 000000046c218063 ffffffffffffffff
    (XEN)  L3[0x102] = 000000046c218063 ffffffffffffffff
    (XEN)  L2[0x102] = 000000046c218063 ffffffffffffffff
    (XEN)  L1[0x103] = 0000000000000000 ffffffffffffffff

This is part of XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Tim Deegan <tim@xen.org>
master commit: d20daf4294
master date: 2017-11-16 10:38:14 +0100
This commit is contained in:
Andrew Cooper authored and Jan Beulich committed 2017-11-16 12:03:26 +01:00
1 parent 1f551847f5
commit 259a5c3000
1 file changed
+12 -5
+12 -5
View File
@@ -4305,11 +4305,18 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn)
/* Carefully look in the shadow linear map for the l1e we expect */
#if SHADOW_PAGING_LEVELS >= 4
/* Is a shadow linear map is installed in the first place? */
sl4p = v->arch.paging.shadow.guest_vtable;
sl4p += shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START);
if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
return 0;
/*
* Non-external guests (i.e. PV) have a SHADOW_LINEAR mapping from the
* moment their shadows are created. External guests (i.e. HVM) may not,
* but always have a regular linear mapping, which we can use to observe
* whether a SHADOW_LINEAR mapping is present.
*/
if ( paging_mode_external(d) )
{
sl4p = __linear_l4_table + l4_linear_offset(SH_LINEAR_PT_VIRT_START);
if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
return 0;
}
sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
return 0;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.