Linux can return error from restore_sigcontext in some conditions, which
forces a SIGSEGV. Plumb through this error handling which will be used
by the next change.
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
linux-user/riscv/signal.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index 22b1b8149f..ece276f85f 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -145,7 +145,7 @@ badframe:
force_sig(TARGET_SIGSEGV);
}
-static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
+static bool restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
{
int i;
@@ -161,9 +161,11 @@ static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
uint32_t fcsr;
__get_user(fcsr, &sc->fcsr);
riscv_csr_write(env, CSR_FCSR, fcsr);
+
+ return true;
}
-static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
+static bool restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
{
sigset_t blocked;
target_sigset_t target_set;
@@ -177,7 +179,7 @@ static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
target_to_host_sigset_internal(&blocked, &target_set);
set_sigmask(&blocked);
- restore_sigcontext(env, &uc->uc_mcontext);
+ return restore_sigcontext(env, &uc->uc_mcontext);
}
long do_rt_sigreturn(CPURISCVState *env)
@@ -191,7 +193,10 @@ long do_rt_sigreturn(CPURISCVState *env)
goto badframe;
}
- restore_ucontext(env, &frame->uc);
+ if (!restore_ucontext(env, &frame->uc)) {
+ goto badframe;
+ }
+
target_restore_altstack(&frame->uc.uc_stack, env);
unlock_user_struct(frame, frame_addr, 0);
--
2.51.0