File 5a2fd9c9-x86-shadow-fix-ref-counting-error-handling.patch of Package xen.7673
# Commit 10be8001de7d87be1f0ccdda75cc70e922e56d03
# Date 2017-12-12 14:29:45 +0100
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86/shadow: fix ref-counting error handling
The old-Linux handling in shadow_set_l4e() mistakenly ORed together the
results of sh_get_ref() and sh_pin(). As the latter failing is not a
correctness problem, simply ignore its return value.
In sh_set_toplevel_shadow() a failing sh_get_ref() must not be
accompanied by installing the entry, despite the domain being crashed.
This is XSA-250.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Tim Deegan <tim@xen.org>
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -909,7 +909,7 @@ static int shadow_set_l4e(struct vcpu *v
shadow_l4e_t new_sl4e,
mfn_t sl4mfn)
{
- int flags = 0, ok;
+ int flags = 0;
shadow_l4e_t old_sl4e;
paddr_t paddr;
ASSERT(sl4e != NULL);
@@ -924,15 +924,16 @@ static int shadow_set_l4e(struct vcpu *v
{
/* About to install a new reference */
mfn_t sl3mfn = shadow_l4e_get_mfn(new_sl4e);
- ok = sh_get_ref(v, sl3mfn, paddr);
- /* Are we pinning l3 shadows to handle wierd linux behaviour? */
- if ( sh_type_is_pinnable(v, SH_type_l3_64_shadow) )
- ok |= sh_pin(v, sl3mfn);
- if ( !ok )
+
+ if ( !sh_get_ref(v, sl3mfn, paddr) )
{
domain_crash(v->domain);
return SHADOW_SET_ERROR;
}
+
+ /* Are we pinning l3 shadows to handle weird Linux behaviour? */
+ if ( sh_type_is_pinnable(v, SH_type_l3_64_shadow) )
+ sh_pin(v, sl3mfn);
}
/* Write the new entry */
@@ -3904,14 +3905,15 @@ sh_set_toplevel_shadow(struct vcpu *v,
/* Take a ref to this page: it will be released in sh_detach_old_tables()
* or the next call to set_toplevel_shadow() */
- if ( !sh_get_ref(v, smfn, 0) )
+ if ( sh_get_ref(v, smfn, 0) )
+ new_entry = pagetable_from_mfn(smfn);
+ else
{
SHADOW_ERROR("can't install %#lx as toplevel shadow\n", mfn_x(smfn));
domain_crash(v->domain);
+ new_entry = pagetable_null();
}
- new_entry = pagetable_from_mfn(smfn);
-
install_new_entry:
/* Done. Install it */
SHADOW_PRINTK("%u/%u [%u] gmfn %#"PRI_mfn" smfn %#"PRI_mfn"\n",