x86/vmx: Rework #DB intercept logic to fix VMEntry failure with BTF

The consistency checks in effect when Blocked-by-STI/MovSS are active includes
DEBUGCTL.BTF too.  Take this into account when editing PENDING_DBG.BS.

This ends up narrowing the cases where PENDING_DBG is modified.  Rework the
comment to be more precise.

This is XSA-518 / CVE-2026-79611.

Fixes: 1d3eb82598 ("x86/vtx: Work around SingleStep + STI/MovSS VMEntry failures")
Reported-by: Teddy Astie <teddy.astie@vates.tech>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Teddy Astie <teddy.astie@vates.tech>
(cherry picked from commit 1017562ac0)
This commit is contained in:
Andrew Cooper committed 2026-10-13 13:48:17 +01:00
1 parent edcad3da3e
commit 7e80d14127
1 file changed
+18 -23
+18 -23
View File
@@ -4396,33 +4396,28 @@ void asmlinkage vmx_vmexit_handler(struct cpu_user_regs *regs)
* We intercept #DB unconditionally to work around CVE-2015-8104 /
* XSA-156 (guest-kernel induced host DoS).
*
* STI/MovSS shadows block/defer interrupts/exceptions (exact
* details are complicated and poorly documented). Debug
* exceptions delayed for any reason are stored in the
* PENDING_DBG_EXCEPTIONS field.
* Most sources of #DB accumuate status in PENDING_DBG, which are
* then dispatched in priority order prior to fetching the next
* instruction. When the #DB intercept triggers, PENDING_DBG is 0
* with the status bits having moved into EXIT_QUALIFICATION.
*
* The falling edge of PENDING_DBG causes #DB to be delivered,
* resulting in a VMExit, as #DB is intercepted. The VMCS still
* reports blocked-by-STI/MovSS.
* At any point if Blocked-by-STI/MovSS are active, extra VMEntry
* consistency checks are applied, cross-checking EFLAGS.TF,
* PENDING_DBG.BS and DEBUGCTL.BTF. These consistency checks
* apply to Activity-state-HLT too, but Xen doesn't support this.
*
* The VMEntry checks when EFLAGS.TF is set don't like a VMCS in
* this state. Despite a #DB queued in VMENTRY_INTR_INFO, the
* state is rejected as DR6.BS isn't pending. Fix this up.
* The VMCS state at the point of #DB intercept does not satisfy
* the consistency checks. In the case that a SingleStep should
* be pending, fill PENDING_DBG back in to satisfy the consitency
* check.
*/
if ( unlikely(regs->eflags & X86_EFLAGS_TF) )
if ( unlikely(regs->eflags & X86_EFLAGS_TF) &&
(vmread(GUEST_INTERRUPTIBILITY_INFO) &
(VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS)) &&
!(vmread(GUEST_IA32_DEBUGCTL) & IA32_DEBUGCTLMSR_BTF) )
{
unsigned long int_info;
__vmread(GUEST_INTERRUPTIBILITY_INFO, &int_info);
if ( int_info & (VMX_INTR_SHADOW_STI | VMX_INTR_SHADOW_MOV_SS) )
{
unsigned long pending_dbg;
__vmread(GUEST_PENDING_DBG_EXCEPTIONS, &pending_dbg);
__vmwrite(GUEST_PENDING_DBG_EXCEPTIONS,
pending_dbg | DR_STEP);
}
ASSERT(vmread(GUEST_PENDING_DBG_EXCEPTIONS) == 0);
__vmwrite(GUEST_PENDING_DBG_EXCEPTIONS, X86_DR6_BS);
}
if ( !v->domain->debugger_attached )
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.