Force insn_off to a single byte, as offset can wrap around or truncate with
respect to sh_ctxt->insn_buf_eip under a number of normal circumstances.
Furthermore, don't use an ASSERT() for bounds checking the write into
hvmemul_ctxt->insn_buf[].
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
x86/hvm: Fix boundary check in hvmemul_insn_fetch()
c/s
0943a03037 added some extra protection for overflowing the emulation
instruction cache, but Coverity points out that boundary condition is off by
one when memcpy()'ing out of the buffer.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
x86/HVM: fix boundary check in hvmemul_insn_fetch() (again)
Commit
5a992b670b ("x86/hvm: Fix boundary check in
hvmemul_insn_fetch()") went a little too far in its correction to
commit
0943a03037 ("x86/hvm: Fixes to hvmemul_insn_fetch()"): Keep the
start offset check, but restore the original end offset one.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
master commit:
0943a03037418e6e40cdd420f2472bbf9afae7a2
master date: 2017-07-19 10:25:18 +0100
master commit:
5a992b670bff697c40b513c9e037598ba35ca7d4
master date: 2017-07-27 11:39:57 +0100
master commit:
58e8986267d976b00c60e0089baa2e5f66f16d3e
master date: 2017-08-10 12:37:24 +0200
{
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
- unsigned int insn_off = offset - hvmemul_ctxt->insn_buf_eip;
+ /* Careful, as offset can wrap or truncate WRT insn_buf_eip. */
+ uint8_t insn_off = offset - hvmemul_ctxt->insn_buf_eip;
/*
* Fall back if requested bytes are not in the prefetch cache.
if ( rc == X86EMUL_OKAY && bytes )
{
- ASSERT(insn_off + bytes <= sizeof(hvmemul_ctxt->insn_buf));
+ /*
+ * Will we overflow insn_buf[]? This shouldn't be able to happen,
+ * which means something went wrong with instruction decoding...
+ */
+ if ( insn_off >= sizeof(hvmemul_ctxt->insn_buf) ||
+ insn_off + bytes > sizeof(hvmemul_ctxt->insn_buf) )
+ {
+ ASSERT_UNREACHABLE();
+ return X86EMUL_UNHANDLEABLE;
+ }
+
memcpy(&hvmemul_ctxt->insn_buf[insn_off], p_data, bytes);
hvmemul_ctxt->insn_buf_bytes = insn_off + bytes;
}