From d445f0cc38412ce55959b3da68b9fb481b6d9d45 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 9 Dec 2016 12:04:23 +0100 Subject: [PATCH] x86emul: avoid undefined behavior when dealing with 10-byte FPU operands Accessing an 8-byte (or perhaps just 4-byte in the test harness when built as 32-bit app) field to read/write 10 bytes (leveraging the successive field) is a latent bug, as the compiler could copy things around. Use the 32 bytes large SSE/AVX slot instead. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- xen/arch/x86/x86_emulate/x86_emulate.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index a5336f58bf..dac057908b 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -3728,15 +3728,19 @@ x86_emulate( dst.bytes = 4; break; case 5: /* fld m80fp */ - if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, mmvalp, 10, ctxt)) != X86EMUL_OKAY ) goto done; - emulate_fpu_insn_memsrc("fldt", src.val); + emulate_fpu_insn_memsrc("fldt", *mmvalp); dst.type = OP_NONE; break; case 7: /* fstp m80fp */ - emulate_fpu_insn_memdst("fstpt", dst.val); - dst.bytes = 10; + fail_if(!ops->write); + emulate_fpu_insn_memdst("fstpt", *mmvalp); + if ( (rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, + 10, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.type = OP_NONE; break; default: generate_exception(EXC_UD); @@ -3945,10 +3949,10 @@ x86_emulate( dst.bytes = 2; break; case 4: /* fbld m80dec */ - if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, mmvalp, 10, ctxt)) != X86EMUL_OKAY ) goto done; - emulate_fpu_insn_memsrc("fbld", src.val); + emulate_fpu_insn_memsrc("fbld", *mmvalp); dst.type = OP_NONE; break; case 5: /* fild m64i */ @@ -3959,8 +3963,12 @@ x86_emulate( dst.type = OP_NONE; break; case 6: /* fbstp packed bcd */ - emulate_fpu_insn_memdst("fbstp", dst.val); - dst.bytes = 10; + fail_if(!ops->write); + emulate_fpu_insn_memdst("fbstp", *mmvalp); + if ( (rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, + 10, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.type = OP_NONE; break; case 7: /* fistp m64i */ emulate_fpu_insn_memdst("fistpll", dst.val); -- 2.39.5