aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-04-25 19:53:30 -0700
committerLaurent Vivier <laurent@vivier.eu>2021-05-15 21:43:23 +0200
commit1176e57a8b34c845a89b2b0f86e424a825d40faa (patch)
tree120fa4dbbbffff8b2310bfd6373fe0e6782a16ae
parent757d260143488d1d0b4016020969ab28259b854b (diff)
linux-user/sparc: Minor corrections to do_sigreturn
Check that the input sp is 16 byte aligned, not 4. Do that before the lock_user_struct check. Validate the saved sp is 8 byte aligned. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20210426025334.1168495-22-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
-rw-r--r--linux-user/sparc/signal.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index f0f614a3af..0ff57af43d 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -254,7 +254,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
long do_sigreturn(CPUSPARCState *env)
{
abi_ulong sf_addr;
- struct target_signal_frame *sf;
+ struct target_signal_frame *sf = NULL;
abi_ulong pc, npc, ptr;
target_sigset_t set;
sigset_t host_set;
@@ -262,18 +262,21 @@ long do_sigreturn(CPUSPARCState *env)
sf_addr = env->regwptr[WREG_SP];
trace_user_do_sigreturn(env, sf_addr);
- if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
- goto segv_and_exit;
- }
/* 1. Make sure we are not getting garbage from the user */
+ if ((sf_addr & 15) || !lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
+ goto segv_and_exit;
+ }
- if (sf_addr & 3)
+ /* Make sure stack pointer is aligned. */
+ __get_user(ptr, &sf->regs.u_regs[14]);
+ if (ptr & 7) {
goto segv_and_exit;
+ }
- __get_user(pc, &sf->regs.pc);
+ /* Make sure instruction pointers are aligned. */
+ __get_user(pc, &sf->regs.pc);
__get_user(npc, &sf->regs.npc);
-
if ((pc | npc) & 3) {
goto segv_and_exit;
}
@@ -309,7 +312,7 @@ long do_sigreturn(CPUSPARCState *env)
unlock_user_struct(sf, sf_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
-segv_and_exit:
+ segv_and_exit:
unlock_user_struct(sf, sf_addr, 0);
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;