]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86: Decoding guest instructions which cross page boundary may fail
authorNadav Amit <namit@cs.technion.ac.il>
Thu, 2 Oct 2014 22:10:04 +0000 (01:10 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 Nov 2014 18:10:28 +0000 (10:10 -0800)
commit 08da44aedba0f493e10695fa334348a7a4f72eb3 upstream.

Once an instruction crosses a page boundary, the size read from the second page
disregards the common case that part of the operand resides on the first page.
As a result, fetch of long insturctions may fail, and thereby cause the
decoding to fail as well.

Fixes: 5cfc7e0f5e5e1adf998df94f8e36edaf5d30d38e
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kvm/emulate.c

index 258b0d9349941f5028165cead5a7e29ee171b90d..a26358fc16109c6d9d60ea177e345a33c7e52bd4 100644 (file)
@@ -773,8 +773,10 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
                                               unsigned size)
 {
-       if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
-               return __do_insn_fetch_bytes(ctxt, size);
+       unsigned done_size = ctxt->fetch.end - ctxt->fetch.ptr;
+
+       if (unlikely(done_size < size))
+               return __do_insn_fetch_bytes(ctxt, size - done_size);
        else
                return X86EMUL_CONTINUE;
 }