Changeset View
Changeset View
Standalone View
Standalone View
head/emulators/xen-kernel47/files/xsa243-4.7.patch
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
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; |