x86/svm: Apply the virtual-8086 IOPL check to INT n only

In virtual-8086 mode with IOPL < 3, INT n raises #GP(0).  INT1, INT3
and INTO are not affected.  They are delivered normally.

svm_emul_swint_injection() applies the check to all of them, so an ICEBP
raises #GP instead of #DB.  It also reports the IDT entry in the #GP
error code instead of 0.

Move the check earier prior to setting up ec, and limit it to INT n only.

Fixes: 897d59a426 ("x86/svm: Introduce svm_emul_swint_injection()")
Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Stefano Stabellini authored and Andrew Cooper committed 2026-10-26 18:36:52 +00:00
1 parent 69633efbca
commit bd7e286e87
1 file changed
+11 -10
+11 -10
View File
@@ -1139,6 +1139,17 @@ static void svm_emul_swint_injection(struct x86_event *event)
if ( !(vmcb_get_cr0(vmcb) & X86_CR0_PE) ) if ( !(vmcb_get_cr0(vmcb) & X86_CR0_PE) )
goto raise_exception; /* TODO: support real-mode injection? */ goto raise_exception; /* TODO: support real-mode injection? */
/*
* In vm86 mode, INT $N is subject to IOPL.
*
* TODO: It is also subject to CR4.VME=1, which would require reading the
* TSS Software Interrupt Redirection bitmap.
*/
if ( type == X86_ET_SW_INT &&
regs->eflags & X86_EFLAGS_VM &&
MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 )
goto raise_exception;
idte_size = lm ? 16 : 8; idte_size = lm ? 16 : 8;
idte_offset = trap * idte_size; idte_offset = trap * idte_size;
@@ -1146,16 +1157,6 @@ static void svm_emul_swint_injection(struct x86_event *event)
ec = (trap << 3) | X86_XEC_IDT | ec = (trap << 3) | X86_XEC_IDT |
(type == X86_ET_PRIV_SW_EXC ? X86_XEC_EXT : 0); (type == X86_ET_PRIV_SW_EXC ? X86_XEC_EXT : 0);
/*
* TODO: This does not cover the v8086 mode with CR4.VME case
* correctly, but falls on the safe side from the point of view of a
* 32bit OS. Someone with many TUITs can see about reading the TSS
* Software Interrupt Redirection bitmap.
*/
if ( (regs->eflags & X86_EFLAGS_VM) &&
MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 )
goto raise_exception;
/* /*
* Read all 8/16 bytes so the idtr limit check is applied properly to * Read all 8/16 bytes so the idtr limit check is applied properly to
* this entry, even though we don't look at all the words read. * this entry, even though we don't look at all the words read.
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.