This commit updates the behavior of signal handling under !MMU
environment. 1) the stack preparation for the signal handlers and
2) retoration of stack after rt_sigreturn(2) syscall.  Those are needed
as the stack usage on vfork(2) syscall is different.

Signed-off-by: Hajime Tazaki <thehaj...@gmail.com>
---
 arch/x86/um/signal.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 2cc8c2309022..ae9b231dd8f8 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -537,6 +537,18 @@ int setup_signal_stack_si(unsigned long stack_top, struct 
ksignal *ksig,
                /* could use a vstub here */
                return err;
 
+#ifndef CONFIG_MMU
+       /*
+        * we need to push handler address at top of stack, as
+        * __kernel_vsyscall, called after this returns with ret with
+        * stack contents, thus push the handler here.
+        */
+       frame = (struct rt_sigframe __user *) ((unsigned long) frame -
+                                              sizeof(unsigned long));
+       err |= __put_user((unsigned long)ksig->ka.sa.sa_handler,
+                         (unsigned long *)frame);
+#endif
+
        if (err)
                return err;
 
@@ -562,6 +574,20 @@ SYSCALL_DEFINE0(rt_sigreturn)
        unsigned long sp = PT_REGS_SP(&current->thread.regs);
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(sp - sizeof(long));
+#ifndef CONFIG_MMU
+       /**
+        * we enter here with:
+        *
+        * __restore_rt:
+        *     mov $15, %rax
+        *     call *%rax (translated from syscall)
+        *
+        * (code is from musl libc)
+        * so, stack needs to be popped of "call"ed address before
+        * looking at rt_sigframe.
+        */
+       frame = (struct rt_sigframe __user *)((unsigned long)frame + 
sizeof(long));
+#endif
        struct ucontext __user *uc = &frame->uc;
        sigset_t set;
 
-- 
2.43.0


Reply via email to