[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[qemu-xen staging-4.13] target/arm: Don't abort on M-profile exception return in linux-user mode



commit 9027d3fba605d8f6093342ebe4a1da450d374630
Author:     Peter Maydell <peter.maydell@xxxxxxxxxx>
AuthorDate: Thu Aug 22 14:15:34 2019 +0100
Commit:     Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
CommitDate: Sun Oct 27 23:58:01 2019 -0500

    target/arm: Don't abort on M-profile exception return in linux-user mode
    
    An attempt to do an exception-return (branch to one of the magic
    addresses) in linux-user mode for M-profile should behave like
    a normal branch, because linux-user mode is always going to be
    in 'handler' mode. This used to work, but we broke it when we added
    support for the M-profile security extension in commit d02a8698d7ae2bfed.
    
    In that commit we allowed even handler-mode calls to magic return
    values to be checked for and dealt with by causing an
    EXCP_EXCEPTION_EXIT exception to be taken, because this is
    needed for the FNC_RETURN return-from-non-secure-function-call
    handling. For system mode we added a check in do_v7m_exception_exit()
    to make any spurious calls from Handler mode behave correctly, but
    forgot that linux-user mode would also be affected.
    
    How an attempted return-from-non-secure-function-call in linux-user
    mode should be handled is not clear -- on real hardware it would
    result in return to secure code (not to the Linux kernel) which
    could then handle the error in any way it chose. For QEMU we take
    the simple approach of treating this erroneous return the same way
    it would be handled on a CPU without the security extensions --
    treat it as a normal branch.
    
    The upshot of all this is that for linux-user mode we should never
    do any of the bx_excret magic, so the code change is simple.
    
    This ought to be a weird corner case that only affects broken guest
    code (because Linux user processes should never be attempting to do
    exception returns or NS function returns), except that the code that
    assigns addresses in RAM for the process and stack in our linux-user
    code does not attempt to avoid this magic address range, so
    legitimate code attempting to return to a trampoline routine on the
    stack can fall into this case. This change fixes those programs,
    but we should also look at restricting the range of memory we
    use for M-profile linux-user guests to the area that would be
    real RAM in hardware.
    
    Cc: qemu-stable@xxxxxxxxxx
    Reported-by: Christophe Lyon <christophe.lyon@xxxxxxxxxx>
    Reviewed-by: Richard Henderson <richard.henderson@xxxxxxxxxx>
    Signed-off-by: Peter Maydell <peter.maydell@xxxxxxxxxx>
    Message-id: 20190822131534.16602-1-peter.maydell@xxxxxxxxxx
    Fixes: https://bugs.launchpad.net/qemu/+bug/1840922
    Signed-off-by: Peter Maydell <peter.maydell@xxxxxxxxxx>
    (cherry picked from commit 5e5584c89f36b302c666bc6db535fd3f7ff35ad2)
    Signed-off-by: Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
---
 target/arm/translate.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7853462b21..24cb4ba075 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -952,10 +952,27 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
     store_cpu_field(var, thumb);
 }
 
-/* Set PC and Thumb state from var. var is marked as dead.
+/*
+ * Set PC and Thumb state from var. var is marked as dead.
  * For M-profile CPUs, include logic to detect exception-return
  * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
  * and BX reg, and no others, and happens only for code in Handler mode.
+ * The Security Extension also requires us to check for the FNC_RETURN
+ * which signals a function return from non-secure state; this can happen
+ * in both Handler and Thread mode.
+ * To avoid having to do multiple comparisons in inline generated code,
+ * we make the check we do here loose, so it will match for EXC_RETURN
+ * in Thread mode. For system emulation do_v7m_exception_exit() checks
+ * for these spurious cases and returns without doing anything (giving
+ * the same behaviour as for a branch to a non-magic address).
+ *
+ * In linux-user mode it is unclear what the right behaviour for an
+ * attempted FNC_RETURN should be, because in real hardware this will go
+ * directly to Secure code (ie not the Linux kernel) which will then treat
+ * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
+ * attempt behave the way it would on a CPU without the security extension,
+ * which is to say "like a normal branch". That means we can simply treat
+ * all branches as normal with no magic address behaviour.
  */
 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
 {
@@ -963,10 +980,12 @@ static inline void gen_bx_excret(DisasContext *s, 
TCGv_i32 var)
      * s->base.is_jmp that we need to do the rest of the work later.
      */
     gen_bx(s, var);
+#ifndef CONFIG_USER_ONLY
     if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
         (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
         s->base.is_jmp = DISAS_BX_EXCRET;
     }
+#endif
 }
 
 static inline void gen_bx_excret_final_code(DisasContext *s)
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#staging-4.13



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.