From 9dad622260620bdda042282c785ecf1c1e67cfc0 Mon Sep 17 00:00:00 2001 From: Avi Kivity <avi@redhat.com> Date: Mon, 30 Nov 2009 10:21:25 -0200 Subject: [PATCH 3/3] KVM: x86 emulator: limit instructions to 15 bytes RH-Author: Avi Kivity <avi@redhat.com> Message-id: <1259576485-1188-1-git-send-email-avi@redhat.com> Patchwork-id: 3813 O-Subject: [PATCH SECURITY KVM 5.5, 5.4.z] KVM: x86 emulator: limit instructions to 15 bytes Bugzilla: 541165 RH-Acked-by: Eugene Teo <eugene@redhat.com> RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Gleb Natapov <gleb@redhat.com> While we are never normally passed an instruction that exceeds 15 bytes, smp games can cause us to attempt to interpret one, which will cause large latencies in non-preempt hosts. Signed-off-by: Avi Kivity <avi@redhat.com> Bugzilla: #541164 (5.4.z) Bugzilla: #541165 (5.5) Upstream: queued for 2.6.33 and -stable; kvm.git e42d9b8141d1. --- arch/x86/include/asm/kvm_x86_emulate.h | 2 +- arch/x86/kvm/x86_emulate.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- arch/x86/include/asm/kvm_x86_emulate.h | 2 +- arch/x86/kvm/x86_emulate.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_x86_emulate.h b/arch/x86/include/asm/kvm_x86_emulate.h index b7ed2c4..7c18e12 100644 --- a/arch/x86/include/asm/kvm_x86_emulate.h +++ b/arch/x86/include/asm/kvm_x86_emulate.h @@ -129,7 +129,7 @@ struct decode_cache { u8 seg_override; unsigned int d; unsigned long regs[NR_VCPU_REGS]; - unsigned long eip; + unsigned long eip, eip_orig; /* modrm */ u8 modrm; u8 modrm_mod; diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 20f6062..cbc4e60 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -603,6 +603,9 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt, { int rc = 0; + /* x86 instructions are limited to 15 bytes. */ + if (eip + size - ctxt->decode.eip_orig > 15) + return X86EMUL_UNHANDLEABLE; eip += ctxt->cs_base; while (size--) { rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++); @@ -861,7 +864,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) /* Shadow copy of register state. Committed on successful emulation. */ memset(c, 0, sizeof(struct decode_cache)); - c->eip = kvm_rip_read(ctxt->vcpu); + c->eip = c->eip_orig = kvm_rip_read(ctxt->vcpu); ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS); memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); -- 1.6.3.rc4.29.g8146