Commit af0c11ca authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arc-4.0-fixes-part-2' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc

Pull ARC fixes from Vineet Gupta:
 "We found some issues with signal handling taking down the system.  I
  know its late, but these are important and all marked for stable.

  ARC signal handling related fixes uncovered during recent testing of
  NPTL tools"

* tag 'arc-4.0-fixes-part-2' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
  ARC: signal handling robustify
  ARC: SA_SIGINFO ucontext regs off-by-one
parents 38ae1dfc e4140819
...@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, ...@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
sigset_t *set) sigset_t *set)
{ {
int err; int err;
err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs,
sizeof(sf->uc.uc_mcontext.regs.scratch)); sizeof(sf->uc.uc_mcontext.regs.scratch));
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
...@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) ...@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
if (!err) if (!err)
set_current_blocked(&set); set_current_blocked(&set);
err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs), err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch),
sizeof(sf->uc.uc_mcontext.regs.scratch)); sizeof(sf->uc.uc_mcontext.regs.scratch));
return err; return err;
...@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn) ...@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn)
/* Don't restart from sigreturn */ /* Don't restart from sigreturn */
syscall_wont_restart(regs); syscall_wont_restart(regs);
/*
* Ensure that sigreturn always returns to user mode (in case the
* regs saved on user stack got fudged between save and sigreturn)
* Otherwise it is easy to panic the kernel with a custom
* signal handler and/or restorer which clobberes the status32/ret
* to return to a bogus location in kernel mode.
*/
regs->status32 |= STATUS_U_MASK;
return regs->r0; return regs->r0;
badframe: badframe:
...@@ -229,8 +238,11 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) ...@@ -229,8 +238,11 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
/* /*
* handler returns using sigreturn stub provided already by userpsace * handler returns using sigreturn stub provided already by userpsace
* If not, nuke the process right away
*/ */
BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER)); if(!(ksig->ka.sa.sa_flags & SA_RESTORER))
return 1;
regs->blink = (unsigned long)ksig->ka.sa.sa_restorer; regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
/* User Stack for signal handler will be above the frame just carved */ /* User Stack for signal handler will be above the frame just carved */
...@@ -296,12 +308,12 @@ static void ...@@ -296,12 +308,12 @@ static void
handle_signal(struct ksignal *ksig, struct pt_regs *regs) handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int failed;
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_rt_frame(ksig, oldset, regs); failed = setup_rt_frame(ksig, oldset, regs);
signal_setup_done(ret, ksig, 0); signal_setup_done(failed, ksig, 0);
} }
void do_signal(struct pt_regs *regs) void do_signal(struct pt_regs *regs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment