[prev in list] [next in list] [prev in thread] [next in thread] 

List:       xen-users
Subject:    [Xen-users] Xen Security Advisory 243 (CVE-2017-15592) - x86: Incorrect handling of self-linear shad
From:       Xen.org security team <security () xen ! org>
Date:       2017-11-15 17:13:25
Message-ID: E1eF1Fd-0002My-86 () xenbits ! xenproject ! org
[Download RAW message or body]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

            Xen Security Advisory CVE-2017-15592 / XSA-243
                               version 5

 x86: Incorrect handling of self-linear shadow mappings with translated guests

UPDATES IN VERSION 5
====================

New final patch, addressing a hypervisor crash the original fix caused,
which by itself represents another security issue (DoS).

ISSUE DESCRIPTION
=================

The shadow pagetable code uses linear mappings to inspect and modify the
shadow pagetables.  A linear mapping which points back to itself is known as
self-linear.  For translated guests, the shadow linear mappings (being in a
separate address space) are not intended to be self-linear.  For
non-translated guests, the shadow linear mappings (being the same
address space) are intended to be self-linear.

When constructing a monitor pagetable for Xen to run on a vcpu with, the shadow
linear slot is filled with a self-linear mapping, and for translated guests,
shortly thereafter replaced with a non-self-linear mapping, when the guest's
%cr3 is shadowed.

However when writeable heuristics are used, the shadow mappings are used as
part of shadowing %cr3, causing the heuristics to be applied to Xen's
pagetables, not the guest shadow pagetables.

While investigating, it was also identified that PV auto-translate mode was
insecure.  This mode was removed in Xen 4.7 due to being unused, unmaintained
and presumed broken.  We are not aware of any guest implementation of PV
auto-translate mode.

IMPACT
======

A malicious or buggy HVM guest may cause a hypervisor crash, resulting in a
Denial of Service (DoS) affecting the entire host, or cause hypervisor memory
corruption.  We cannot rule out a guest being able to escalate its privilege.

VULNERABLE SYSTEMS
==================

All versions of Xen are vulnerable.

HVM guests using shadow mode paging can exploit this vulnerability.
HVM guests using Hardware Assisted Paging (HAP) as well as PV guests
cannot exploit this vulnerability.

ARM systems are not vulnerable.

MITIGATION
==========

Running only PV guests will avoid this vulnerability.

Where the HVM guest is explicitly configured to use shadow paging (eg
via the `hap=0' xl domain configuration file parameter), changing to
HAP (eg by setting `hap=1') will avoid exposing the vulnerability to
those guests.  HAP is the default (in upstream Xen), where the
hardware supports it; so this mitigation is only applicable if HAP has
been disabled by configuration.

CREDITS
=======

This issue was discovered by Andrew Cooper of Citrix.

RESOLUTION
==========

Applying the appropriate attached set of patches resolves this issue.

xsa243-[12].patch            xen-unstable, Xen 4.9.x
xsa243-{4.8-1,2}.patch       Xen 4.8.x
xsa243-{4.7-1,2}.patch       Xen 4.7.x
xsa243-{4.6-[12],2}.patch    Xen 4.6.x
xsa243-4.{6-1,5-[23]}.patch  Xen 4.5.x

$ sha256sum xsa243*
a5b484db80346f7e75c7921ee4780567f04b9f9b4620c0cde4bfa1df3ac0f87f  xsa243-1.patch
013cff90312305b7f4ce6818a25760bcfca61bfadd860b694afa04d56e60c563  xsa243-2.patch
79e1c5e088eee8e78aa67895a29d611352c64251854e4c5129e33c85988a47a5  xsa243-4.5-2.patch
b838f387747c6e45314f44202c018ad907a8119bb7d8330fc875dc4243626e78  xsa243-4.5-3.patch
722073aad1e734e24b0b79d03a1957e491f3616fe6e244a89050f7a50f8f356b  xsa243-4.6-1.patch
94cb346c486f88f2f4f701564017e1997e518a5a14218f0e38ff882c60fb382c  xsa243-4.6-2.patch
465ba9e3293591a3c84c122ffd73474fe96483f5e21565440d5fbc207fa4c4a9  xsa243-4.7-1.patch
f8e471b42502905a442d43934ac339663a6124118c9762b31f2ad930fd532e64  xsa243-4.8-1.patch
$

DEPLOYMENT DURING EMBARGO
=========================

Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.

But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).

Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.

(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable.  This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)

For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
  http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBCAAGBQJaDHWmAAoJEIP+FMlX6CvZbKgH/RsntzKBpEJQfElzpN15+eMM
Kakfq3Mzad4JuaOb5dVy4fhE88gHgE344mmiUqu/h+pwRKofC/a3DvS4GPO8NJAI
Zdu1CCkuZ3/L3IpbtdGsLMw1EZGQLXNsQGWCgDB3sNAT6Ue+FvmJbiP0RkIO+qXw
7KSCfs2NtMvkj17jt5ZYj2Y43d0IvWirR3LHkJIDR0ZPYkX5WagAmuOom3bj57lt
0Q/GC40x+kO9lQSw299CZxuHTi34zu0V4/HRtfSSVph5Gbcb+4kxMqv8e3wRfgg9
kBF6FD12oLJkArIeb/J72m13RTiIJDiG3VltS9B2Vmm9+LZOhBvbsfILrePk0qE=
=6RHQ
-----END PGP SIGNATURE-----

["xsa243-1.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests

When initially creating a monitor table for 4-level translated guests, don't
install a shadow-linear mapping.  This mapping is actually self-linear, and
trips up the writeable heuristic logic into following Xen's mappings, not the
guests' shadows it was expecting to follow.

A consequence of this is that sh_guess_wrmap() needs to cope with there being
no shadow-linear mapping present, which in practice occurs once each time a
vcpu switches to 4-level paging from a different paging mode.

An appropriate shadow-linear slot will be inserted into the monitor table
either while constructing lower level monitor tables, or by sh_update_cr3().

While fixing this, clarify the safety of the other mappings.  Despite
appearing unsafe, it is correct to create a guest-linear mapping for
translated domains; this is self-linear and doesn't point into the translated
domain.  Drop a dead clause for translate != external guests.

This is XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>

diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 8d4f244..a18d286 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1485,26 +1485,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
         sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
     }
 
-    /* Shadow linear mapping for 4-level shadows.  N.B. for 3-level
-     * shadows on 64-bit xen, this linear mapping is later replaced by the
-     * monitor pagetable structure, which is built in make_monitor_table
-     * and maintained by sh_update_linear_entries. */
-    sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-        shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR_RW);
-
-    /* Self linear mapping.  */
-    if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
+    /*
+     * Linear mapping slots:
+     *
+     * Calling this function with gl4mfn == sl4mfn is used to construct a
+     * monitor table for translated domains.  In this case, gl4mfn forms the
+     * self-linear mapping (i.e. not pointing into the translated domain), and
+     * the shadow-linear slot is skipped.  The shadow-linear slot is either
+     * filled when constructing lower level monitor tables, or via
+     * sh_update_cr3() for 4-level guests.
+     *
+     * Calling this function with gl4mfn != sl4mfn is used for non-translated
+     * guests, where the shadow-linear slot is actually self-linear, and the
+     * guest-linear slot points into the guests view of its pagetables.
+     */
+    if ( shadow_mode_translate(d) )
     {
-        // linear tables may not be used with translated PV guests
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        ASSERT(mfn_eq(gl4mfn, sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
             shadow_l4e_empty();
     }
     else
     {
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-            shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR_RW);
+        ASSERT(!mfn_eq(gl4mfn, sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+            shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR_RW);
     }
 
+    sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR_RW);
+
     unmap_domain_page(sl4e);
 }
 #endif
@@ -4405,6 +4417,11 @@ 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;
     sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
     if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
         return 0;

["xsa243-2.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: correct SH_LINEAR mapping detection in sh_guess_wrmap()

The fix for XSA-243 / CVE-2017-15592 (c/s bf2b4eadcf379) 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>

--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -4350,11 +4350,18 @@ static int sh_guess_wrmap(struct vcpu *v
 
     /* 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;

["xsa243-4.5-2.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests

When initially creating a monitor table for 4-level translated guests, don't
install a shadow-linear mapping.  This mapping is actually self-linear, and
trips up the writeable heuristic logic into following Xen's mappings, not the
guests' shadows it was expecting to follow.

A consequence of this is that sh_guess_wrmap() needs to cope with there being
no shadow-linear mapping present, which in practice occurs once each time a
vcpu switches to 4-level paging from a different paging mode.

An appropriate shadow-linear slot will be inserted into the monitor table
either while constructing lower level monitor tables, or by sh_update_cr3().

While fixing this, clarify the safety of the other mappings.  Despite
appearing unsafe, it is correct to create a guest-linear mapping for
translated domains; this is self-linear and doesn't point into the translated
domain.  Drop a dead clause for translate != external guests.

This is part of XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>

diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index e16bf1b..948c86a 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1453,26 +1453,38 @@ void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
         shadow_l4e_from_mfn(page_to_mfn(d->arch.perdomain_l3_pg),
                             __PAGE_HYPERVISOR);
 
-    /* Shadow linear mapping for 4-level shadows.  N.B. for 3-level
-     * shadows on 64-bit xen, this linear mapping is later replaced by the
-     * monitor pagetable structure, which is built in make_monitor_table
-     * and maintained by sh_update_linear_entries. */
-    sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-        shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
-
-    /* Self linear mapping.  */
-    if ( shadow_mode_translate(v->domain) && !shadow_mode_external(v->domain) )
-    {
-        // linear tables may not be used with translated PV guests
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+    /*
+     * Linear mapping slots:
+     *
+     * Calling this function with gl4mfn == sl4mfn is used to construct a
+     * monitor table for translated domains.  In this case, gl4mfn forms the
+     * self-linear mapping (i.e. not pointing into the translated domain), and
+     * the shadow-linear slot is skipped.  The shadow-linear slot is either
+     * filled when constructing lower level monitor tables, or via
+     * sh_update_cr3() for 4-level guests.
+     *
+     * Calling this function with gl4mfn != sl4mfn is used for non-translated
+     * guests, where the shadow-linear slot is actually self-linear, and the
+     * guest-linear slot points into the guests view of its pagetables.
+     */
+    if ( shadow_mode_translate(d) )
+    {
+        ASSERT(mfn_x(gl4mfn) == mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
             shadow_l4e_empty();
     }
     else
     {
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-            shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+        ASSERT(mfn_x(gl4mfn) != mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+            shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
     }
 
+    sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+
     sh_unmap_domain_page(sl4e);    
 }
 #endif
@@ -4243,6 +4255,11 @@ 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;
     sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
     if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
         return 0;

["xsa243-4.5-3.patch" (application/octet-stream)]

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

The fix for XSA-243 / CVE-2017-15592 (c/s bf2b4eadcf379) 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>

--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -4255,11 +4255,18 @@ static int sh_guess_wrmap(struct vcpu *v
 
     /* 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(v->domain) )
+    {
+        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;

["xsa243-4.6-1.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86: Disable the use of auto-translated PV guests

This is a minimal backport of c/s 92942fd3d469 "x86/mm: drop
guest_{map,get_eff}_l1e() hooks" from Xen 4.7, which stated:

  Disallow the unmaintained and presumed broken translated-but-not-external
  paging mode combination ...

It turns out that this mode is insecure to run with, as opposed to just simply
broken.

This is part of XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index dcff4fb..945bb61 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -835,6 +835,15 @@ void paging_final_teardown(struct domain *d)
  * creation. */
 int paging_enable(struct domain *d, u32 mode)
 {
+    switch ( mode & (PG_external | PG_translate) )
+    {
+    case 0:
+    case PG_external | PG_translate:
+        break;
+    default:
+        return -EINVAL;
+    }
+
     if ( hap_enabled(d) )
         return hap_enable(d, mode | PG_HAP_enable);
     else

["xsa243-4.6-2.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests

When initially creating a monitor table for 4-level translated guests, don't
install a shadow-linear mapping.  This mapping is actually self-linear, and
trips up the writeable heuristic logic into following Xen's mappings, not the
guests' shadows it was expecting to follow.

A consequence of this is that sh_guess_wrmap() needs to cope with there being
no shadow-linear mapping present, which in practice occurs once each time a
vcpu switches to 4-level paging from a different paging mode.

An appropriate shadow-linear slot will be inserted into the monitor table
either while constructing lower level monitor tables, or by sh_update_cr3().

While fixing this, clarify the safety of the other mappings.  Despite
appearing unsafe, it is correct to create a guest-linear mapping for
translated domains; this is self-linear and doesn't point into the translated
domain.  Drop a dead clause for translate != external guests.

This is part of XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>

diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index c34ebe0..cb8ddde 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1456,26 +1456,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
         sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
     }
 
-    /* Shadow linear mapping for 4-level shadows.  N.B. for 3-level
-     * shadows on 64-bit xen, this linear mapping is later replaced by the
-     * monitor pagetable structure, which is built in make_monitor_table
-     * and maintained by sh_update_linear_entries. */
-    sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-        shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
-
-    /* Self linear mapping.  */
-    if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
-    {
-        // linear tables may not be used with translated PV guests
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+    /*
+     * Linear mapping slots:
+     *
+     * Calling this function with gl4mfn == sl4mfn is used to construct a
+     * monitor table for translated domains.  In this case, gl4mfn forms the
+     * self-linear mapping (i.e. not pointing into the translated domain), and
+     * the shadow-linear slot is skipped.  The shadow-linear slot is either
+     * filled when constructing lower level monitor tables, or via
+     * sh_update_cr3() for 4-level guests.
+     *
+     * Calling this function with gl4mfn != sl4mfn is used for non-translated
+     * guests, where the shadow-linear slot is actually self-linear, and the
+     * guest-linear slot points into the guests view of its pagetables.
+     */
+    if ( shadow_mode_translate(d) )
+    {
+        ASSERT(mfn_x(gl4mfn) == mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
             shadow_l4e_empty();
     }
     else
     {
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-            shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+        ASSERT(mfn_x(gl4mfn) != mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+            shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
     }
 
+    sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+
     unmap_domain_page(sl4e);
 }
 #endif
@@ -4270,6 +4282,11 @@ 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;
     sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
     if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
         return 0;

["xsa243-4.7-1.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests

When initially creating a monitor table for 4-level translated guests, don't
install a shadow-linear mapping.  This mapping is actually self-linear, and
trips up the writeable heuristic logic into following Xen's mappings, not the
guests' shadows it was expecting to follow.

A consequence of this is that sh_guess_wrmap() needs to cope with there being
no shadow-linear mapping present, which in practice occurs once each time a
vcpu switches to 4-level paging from a different paging mode.

An appropriate shadow-linear slot will be inserted into the monitor table
either while constructing lower level monitor tables, or by sh_update_cr3().

While fixing this, clarify the safety of the other mappings.  Despite
appearing unsafe, it is correct to create a guest-linear mapping for
translated domains; this is self-linear and doesn't point into the translated
domain.  Drop a dead clause for translate != external guests.

This is XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>

diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 428be37..c83932f 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1472,26 +1472,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
         sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
     }
 
-    /* Shadow linear mapping for 4-level shadows.  N.B. for 3-level
-     * shadows on 64-bit xen, this linear mapping is later replaced by the
-     * monitor pagetable structure, which is built in make_monitor_table
-     * and maintained by sh_update_linear_entries. */
-    sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-        shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
-
-    /* Self linear mapping.  */
-    if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
+    /*
+     * Linear mapping slots:
+     *
+     * Calling this function with gl4mfn == sl4mfn is used to construct a
+     * monitor table for translated domains.  In this case, gl4mfn forms the
+     * self-linear mapping (i.e. not pointing into the translated domain), and
+     * the shadow-linear slot is skipped.  The shadow-linear slot is either
+     * filled when constructing lower level monitor tables, or via
+     * sh_update_cr3() for 4-level guests.
+     *
+     * Calling this function with gl4mfn != sl4mfn is used for non-translated
+     * guests, where the shadow-linear slot is actually self-linear, and the
+     * guest-linear slot points into the guests view of its pagetables.
+     */
+    if ( shadow_mode_translate(d) )
     {
-        // linear tables may not be used with translated PV guests
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        ASSERT(mfn_x(gl4mfn) == mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
             shadow_l4e_empty();
     }
     else
     {
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-            shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+        ASSERT(mfn_x(gl4mfn) != mfn_x(sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+            shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
     }
 
+    sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+
     unmap_domain_page(sl4e);
 }
 #endif
@@ -4293,6 +4305,11 @@ 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;
     sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
     if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
         return 0;

["xsa243-4.8-1.patch" (application/octet-stream)]

From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Don't create self-linear shadow mappings for 4-level translated guests

When initially creating a monitor table for 4-level translated guests, don't
install a shadow-linear mapping.  This mapping is actually self-linear, and
trips up the writeable heuristic logic into following Xen's mappings, not the
guests' shadows it was expecting to follow.

A consequence of this is that sh_guess_wrmap() needs to cope with there being
no shadow-linear mapping present, which in practice occurs once each time a
vcpu switches to 4-level paging from a different paging mode.

An appropriate shadow-linear slot will be inserted into the monitor table
either while constructing lower level monitor tables, or by sh_update_cr3().

While fixing this, clarify the safety of the other mappings.  Despite
appearing unsafe, it is correct to create a guest-linear mapping for
translated domains; this is self-linear and doesn't point into the translated
domain.  Drop a dead clause for translate != external guests.

This is XSA-243.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>

diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index d70b1c6..029e8d4 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1472,26 +1472,38 @@ void sh_install_xen_entries_in_l4(struct domain *d, mfn_t gl4mfn, mfn_t sl4mfn)
         sl4e[shadow_l4_table_offset(RO_MPT_VIRT_START)] = shadow_l4e_empty();
     }
 
-    /* Shadow linear mapping for 4-level shadows.  N.B. for 3-level
-     * shadows on 64-bit xen, this linear mapping is later replaced by the
-     * monitor pagetable structure, which is built in make_monitor_table
-     * and maintained by sh_update_linear_entries. */
-    sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
-        shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
-
-    /* Self linear mapping.  */
-    if ( shadow_mode_translate(d) && !shadow_mode_external(d) )
+    /*
+     * Linear mapping slots:
+     *
+     * Calling this function with gl4mfn == sl4mfn is used to construct a
+     * monitor table for translated domains.  In this case, gl4mfn forms the
+     * self-linear mapping (i.e. not pointing into the translated domain), and
+     * the shadow-linear slot is skipped.  The shadow-linear slot is either
+     * filled when constructing lower level monitor tables, or via
+     * sh_update_cr3() for 4-level guests.
+     *
+     * Calling this function with gl4mfn != sl4mfn is used for non-translated
+     * guests, where the shadow-linear slot is actually self-linear, and the
+     * guest-linear slot points into the guests view of its pagetables.
+     */
+    if ( shadow_mode_translate(d) )
     {
-        // linear tables may not be used with translated PV guests
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        ASSERT(mfn_eq(gl4mfn, sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
             shadow_l4e_empty();
     }
     else
     {
-        sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
-            shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+        ASSERT(!mfn_eq(gl4mfn, sl4mfn));
+
+        sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
+            shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
     }
 
+    sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] =
+        shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR);
+
     unmap_domain_page(sl4e);
 }
 #endif
@@ -4287,6 +4299,11 @@ 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;
     sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
     if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
         return 0;

[Attachment #11 (text/plain)]

_______________________________________________
Xen-users mailing list
Xen-users@lists.xen.org
https://lists.xen.org/xen-users

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic