diff mbox series

[RFC,09/13] x86/um: nommu: signal handling

Message ID f3c873365cccce18b2f1889984bf521d3cfb68f2.1729770373.git.thehajime@gmail.com
State RFC
Headers show
Series [RFC,01/13] fs: binfmt_elf_efpic: add architecture hook elf_arch_finalize_exec | expand

Commit Message

Hajime Tazaki Oct. 24, 2024, 12:09 p.m. UTC
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 <thehajime@gmail.com>
---
 arch/x86/um/signal.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

Comments

Johannes Berg Oct. 25, 2024, 9:30 a.m. UTC | #1
On Thu, 2024-10-24 at 21:09 +0900, Hajime Tazaki wrote:
> 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Ā 

typo: restoration

> @@ -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;

you shouldn't put code in the middle of variable declarations ...

I see why, but probably just split #if/#else/#endif?

johannes
Hajime Tazaki Oct. 25, 2024, 1:04 p.m. UTC | #2
On Fri, 25 Oct 2024 18:30:41 +0900,
Johannes Berg wrote:
> 
> On Thu, 2024-10-24 at 21:09 +0900, Hajime Tazaki wrote:
> > 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Ā 
> 
> typo: restoration

will fix it.

> > @@ -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;
> 
> you shouldn't put code in the middle of variable declarations ...
> 
> I see why, but probably just split #if/#else/#endif?

thanks, will reformat it to make it clear.

-- Hajime
diff mbox series

Patch

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;