diff options
Diffstat (limited to 'system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch')
-rw-r--r-- | system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch b/system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch new file mode 100644 index 0000000000..bc99596083 --- /dev/null +++ b/system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch @@ -0,0 +1,42 @@ +From: Andrew Cooper <andrew.cooper3@citrix.com> +Subject: x86/shadow: Avoid overflowing sh_ctxt->seg_reg[] + +hvm_get_seg_reg() does not perform a range check on its input segment, calls +hvm_get_segment_register() and writes straight into sh_ctxt->seg_reg[]. + +x86_seg_none is outside the bounds of sh_ctxt->seg_reg[], and will hit a BUG() +in {vmx,svm}_get_segment_register(). + +HVM guests running with shadow paging can end up performing a virtual to +linear translation with x86_seg_none. This is used for addresses which are +already linear. However, none of this is a legitimate pagetable update, so +fail the emulation in such a case. + +This is XSA-187 + +Reported-by: Andrew Cooper <andrew.cooper3@citrix.com> +Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> +Reviewed-by: Tim Deegan <tim@xen.org> + +--- a/xen/arch/x86/mm/shadow/common.c ++++ b/xen/arch/x86/mm/shadow/common.c +@@ -140,9 +140,18 @@ static int hvm_translate_linear_addr( + struct sh_emulate_ctxt *sh_ctxt, + unsigned long *paddr) + { +- struct segment_register *reg = hvm_get_seg_reg(seg, sh_ctxt); ++ struct segment_register *reg; + int okay; + ++ /* ++ * Can arrive here with non-user segments. However, no such cirucmstance ++ * is part of a legitimate pagetable update, so fail the emulation. ++ */ ++ if ( !is_x86_user_segment(seg) ) ++ return X86EMUL_UNHANDLEABLE; ++ ++ reg = hvm_get_seg_reg(seg, sh_ctxt); ++ + okay = hvm_virtual_to_linear_addr( + seg, reg, offset, bytes, access_type, sh_ctxt->ctxt.addr_size, paddr); + |