x86emul: also put_fpu() on error paths
authorJan Beulich <jbeulich@suse.com>
Mon, 18 May 2015 10:11:31 +0000 (12:11 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 18 May 2015 10:11:31 +0000 (12:11 +0200)
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 <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/x86_emulate/x86_emulate.c
xen/arch/x86/x86_emulate/x86_emulate.h

index 6c6c58a8ea0292fc52a188663e0d9dd17e83e89f..d43ca4e38e66396e4d4ebe3fa45f02eae3796123 100644 (file)
@@ -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;
 }
index 593b31e84603f6aea0a785578b7a91d399fb61fc..c55063d8402a2baea8ea933472cc80e019b810a7 100644 (file)
@@ -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);