diff options
Diffstat (limited to 'arch/mips/kernel/signal.c')
| -rw-r--r-- | arch/mips/kernel/signal.c | 27 | 
1 files changed, 18 insertions, 9 deletions
| diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index c9b2a75563e1..5bce782e694c 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -563,6 +563,13 @@ void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,  	sp = regs->regs[29];  	/* +	 * If we are on the alternate signal stack and would overflow it, don't. +	 * Return an always-bogus address instead so we will die with SIGSEGV. +	 */ +	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) +		return (void __user __force *)(-1UL); + +	/*  	 * FPU emulator may have it's own trampoline active just  	 * above the user stack, 16-bytes before the next lowest  	 * 16 byte boundary.  Try to avoid trashing it. @@ -747,23 +754,25 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,  			  struct pt_regs *regs, sigset_t *set)  {  	struct rt_sigframe __user *frame; -	int err = 0;  	frame = get_sigframe(ksig, regs, sizeof(*frame));  	if (!access_ok(frame, sizeof (*frame)))  		return -EFAULT;  	/* Create siginfo.  */ -	err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info); +	if (copy_siginfo_to_user(&frame->rs_info, &ksig->info)) +		return -EFAULT;  	/* Create the ucontext.	 */ -	err |= __put_user(0, &frame->rs_uc.uc_flags); -	err |= __put_user(NULL, &frame->rs_uc.uc_link); -	err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); -	err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); -	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); - -	if (err) +	if (__put_user(0, &frame->rs_uc.uc_flags)) +		return -EFAULT; +	if (__put_user(NULL, &frame->rs_uc.uc_link)) +		return -EFAULT; +	if (__save_altstack(&frame->rs_uc.uc_stack, regs->regs[29])) +		return -EFAULT; +	if (setup_sigcontext(regs, &frame->rs_uc.uc_mcontext)) +		return -EFAULT; +	if (__copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)))  		return -EFAULT;  	/* |