diff options
author | Avi Kivity <avi@redhat.com> | 2009-11-24 13:20:15 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-01 15:52:23 -0700 |
commit | 8b91c56fd291670294e197bc2d25ba3844cc53fa (patch) | |
tree | 895b30a7f2ec94af0ee0f67975d88c00807d2244 | |
parent | 6758be586812a95341a06b04e780fdde9c252ba2 (diff) |
KVM: x86 emulator: limit instructions to 15 bytes
commit eb3c79e64a70fb8f7473e30fa07e89c1ecc2c9bb upstream
[ <cebbert@redhat.com>: backport to 2.6.27 ]
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 5 | ||||
-rw-r--r-- | include/asm-x86/kvm_x86_emulate.h | 2 |
2 files changed, 5 insertions, 2 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index f2f90468f8b1..1dc1cfd7b5b0 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -581,6 +581,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++); @@ -839,7 +842,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 = ctxt->vcpu->arch.rip; + c->eip = c->eip_orig = ctxt->vcpu->arch.rip; ctxt->cs_base = seg_base(ctxt, VCPU_SREG_CS); memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs); diff --git a/include/asm-x86/kvm_x86_emulate.h b/include/asm-x86/kvm_x86_emulate.h index 4e8c1e48d91d..fcbb680eef6e 100644 --- a/include/asm-x86/kvm_x86_emulate.h +++ b/include/asm-x86/kvm_x86_emulate.h @@ -128,7 +128,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; |