(rc = ops->write_segment(x86_seg_ss, &sreg, ctxt)) )
goto done;
+ /*
+ * SYSCALL (unlike most instructions) evaluates its singlestep action
+ * based on the resulting EFLG_TF, not the starting EFLG_TF.
+ *
+ * As the #DB is raised after the CPL change and before the OS can
+ * switch stack, it is a large risk for privilege escalation.
+ *
+ * 64bit kernels should mask EFLG_TF in MSR_FMASK to avoid any
+ * vulnerability. Running the #DB handler on an IST stack is also a
+ * mitigation.
+ *
+ * 32bit kernels have no ability to mask EFLG_TF at all. Their only
+ * mitigation is to use a task gate for handling #DB (or to not use
+ * enable EFER.SCE to start with).
+ */
+ tf = _regs.eflags & EFLG_TF;
+
break;
}
*ctxt->regs = _regs;
- /* Inject #DB if single-step tracing was enabled at instruction start. */
+ /* Should a singlestep #DB be raised? */
if ( tf && (rc == X86EMUL_OKAY) && ops->inject_hw_exception )
rc = ops->inject_hw_exception(EXC_DB, -1, ctxt) ? : X86EMUL_EXCEPTION;