5e8735d
From: Andrew Cooper <andrew.cooper3@citrix.com>
5e8735d
Date: Sun, 18 Dec 2016 15:42:59 +0000
5e8735d
Subject: [PATCH] x86/emul: Correct the handling of eflags with SYSCALL
5e8735d
5e8735d
A singlestep #DB is determined by the resulting eflags value from the
5e8735d
execution of SYSCALL, not the original eflags value.
5e8735d
5e8735d
By using the original eflags value, we negate the guest kernels attempt to
5e8735d
protect itself from a privilege escalation by masking TF.
5e8735d
5e8735d
Have the SYSCALL emulation recalculate tf after the instruction is complete.
5e8735d
5e8735d
This is XSA-204
5e8735d
5e8735d
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
5e8735d
Reviewed-by: Jan Beulich <jbeulich@suse.com>
5e8735d
---
5e8735d
 xen/arch/x86/x86_emulate/x86_emulate.c | 19 ++++++++++++++++++-
5e8735d
 1 file changed, 18 insertions(+), 1 deletion(-)
5e8735d
5e8735d
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
5e8735d
index d82e85d..ff952a9 100644
5e8735d
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
5e8735d
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
5e8735d
@@ -4561,6 +4561,23 @@ x86_emulate(
5e8735d
              (rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) )
5e8735d
             goto done;
5e8735d
 
5e8735d
+        /*
5e8735d
+         * SYSCALL (unlike most instructions) evaluates its singlestep action
5e8735d
+         * based on the resulting EFLG_TF, not the starting EFLG_TF.
5e8735d
+         *
5e8735d
+         * As the #DB is raised after the CPL change and before the OS can
5e8735d
+         * switch stack, it is a large risk for privilege escalation.
5e8735d
+         *
5e8735d
+         * 64bit kernels should mask EFLG_TF in MSR_FMASK to avoid any
5e8735d
+         * vulnerability.  Running the #DB handler on an IST stack is also a
5e8735d
+         * mitigation.
5e8735d
+         *
5e8735d
+         * 32bit kernels have no ability to mask EFLG_TF at all.  Their only
5e8735d
+         * mitigation is to use a task gate for handling #DB (or to not use
5e8735d
+         * enable EFER.SCE to start with).
5e8735d
+         */
5e8735d
+        tf = _regs.eflags & EFLG_TF;
5e8735d
+
5e8735d
         break;
5e8735d
     }
5e8735d
 
5e8735d
@@ -5412,7 +5429,7 @@ x86_emulate(
5e8735d
 
5e8735d
     *ctxt->regs = _regs;
5e8735d
 
5e8735d
-    /* Inject #DB if single-step tracing was enabled at instruction start. */
5e8735d
+    /* Should a singlestep #DB be raised? */
5e8735d
     if ( tf && (rc == X86EMUL_OKAY) && ops->inject_hw_exception )
5e8735d
         rc = ops->inject_hw_exception(EXC_DB, -1, ctxt) ? : X86EMUL_EXCEPTION;
5e8735d