x86emul: also put_fpu() on error paths fail_if() and generate_exception_if() could theoretically bypass the normal flow reaching put_fpu(), and not invoking it would leave the fpu_exception_callback pointer in place, allowing for the callback to be called at an unexpected time. Luckily the two generate_exception_if()-s that would actually trigger this are currently commented out, so this is not (yet) a (security) issue. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -670,10 +670,14 @@ do{ (_fic)->exn_raised = 0; rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \ if ( rc ) goto done; \ } while (0) -#define put_fpu(_fic) \ -do{ \ +#define _put_fpu() \ +do { \ if ( ops->put_fpu != NULL ) \ - ops->put_fpu(ctxt); \ + (ops->put_fpu)(ctxt); \ +} while (0) +#define put_fpu(_fic) \ +do { \ + _put_fpu(); \ generate_exception_if((_fic)->exn_raised, EXC_MF, -1); \ } while (0) @@ -3787,6 +3791,7 @@ x86_emulate( *ctxt->regs = _regs; done: + _put_fpu(); return rc; twobyte_insn: @@ -4632,5 +4637,6 @@ x86_emulate( goto writeback; cannot_emulate: + _put_fpu(); return X86EMUL_UNHANDLEABLE; } --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -384,7 +384,11 @@ struct x86_emulate_ops enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt); - /* put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. */ + /* + * put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. + * The handler, if installed, must be prepared to get called without + * the get_fpu one having got called before! + */ void (*put_fpu)( struct x86_emulate_ctxt *ctxt);