During real mode interrupt emulation, KVM currently pushes data to the stack before checking IDT limits. This patch fetches the IDT early and injects a #GP if the limit is exceeded. This prevents potential corruption. Signed-off-by: Kayra Cizmeci --- arch/x86/kvm/emulate.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8013dccb3110..32168db07dd2 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2022,7 +2022,11 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq) gva_t eip_addr; u16 cs, eip; - /* TODO: Add limit checks */ + ops->get_idt(ctxt, &dt); + + if (dt.size < (irq << 2) + 3) + return emulate_gp(ctxt, 0); + ctxt->src.val = ctxt->eflags; rc = em_push(ctxt); if (rc != X86EMUL_CONTINUE) @@ -2040,8 +2044,6 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq) if (rc != X86EMUL_CONTINUE) return rc; - ops->get_idt(ctxt, &dt); - eip_addr = dt.address + (irq << 2); cs_addr = dt.address + (irq << 2) + 2; @@ -4324,7 +4326,7 @@ static const struct opcode opcode_table[256] = { I(Stack, em_leave), I(ImplicitOps | SrcImmU16 | IsBranch | ShadowStack, em_ret_far_imm), I(ImplicitOps | IsBranch | ShadowStack, em_ret_far), - D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch | ShadowStack, intn), + D(ImplicitOps | IsBranch), DI(SrcImmUByte | IsBranch | ShadowStack, intn), D(ImplicitOps | No64 | IsBranch), II(ImplicitOps | IsBranch | ShadowStack, em_iret, iret), /* 0xD0 - 0xD7 */ -- 2.54.0