diff mbox series

[v2,21/25] linux-user/sparc: Minor corrections to do_sigreturn

Message ID 20210426025334.1168495-22-richard.henderson@linaro.org
State New
Headers show
Series linux-user/sparc: Implement rt signals | expand

Commit Message

Richard Henderson April 26, 2021, 2:53 a.m. UTC
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>

---
 linux-user/sparc/signal.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

-- 
2.25.1
diff mbox series

Patch

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)) {
+
+    /* 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;
     }
 
-    /* 1. Make sure we are not getting garbage from the user */
-
-    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;