summaryrefslogtreecommitdiffstats
path: root/system/xen/xsa/xsa187-4.7-0001-x86-shadow-Avoid-overflowing-sh_ctxt-seg.patch
diff options
context:
space:
mode:
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.patch42
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);
+