Skip to content

Commit af0c11c

Browse files
committed
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
2 parents 38ae1df + e414081 commit af0c11c

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

arch/arc/kernel/signal.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
6767
sigset_t *set)
6868
{
6969
int err;
70-
err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs,
70+
err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), regs,
7171
sizeof(sf->uc.uc_mcontext.regs.scratch));
7272
err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
7373

@@ -83,7 +83,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
8383
if (!err)
8484
set_current_blocked(&set);
8585

86-
err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs),
86+
err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs.scratch),
8787
sizeof(sf->uc.uc_mcontext.regs.scratch));
8888

8989
return err;
@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn)
131131
/* Don't restart from sigreturn */
132132
syscall_wont_restart(regs);
133133

134+
/*
135+
* Ensure that sigreturn always returns to user mode (in case the
136+
* regs saved on user stack got fudged between save and sigreturn)
137+
* Otherwise it is easy to panic the kernel with a custom
138+
* signal handler and/or restorer which clobberes the status32/ret
139+
* to return to a bogus location in kernel mode.
140+
*/
141+
regs->status32 |= STATUS_U_MASK;
142+
134143
return regs->r0;
135144

136145
badframe:
@@ -229,8 +238,11 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
229238

230239
/*
231240
* handler returns using sigreturn stub provided already by userpsace
241+
* If not, nuke the process right away
232242
*/
233-
BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER));
243+
if(!(ksig->ka.sa.sa_flags & SA_RESTORER))
244+
return 1;
245+
234246
regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
235247

236248
/* User Stack for signal handler will be above the frame just carved */
@@ -296,12 +308,12 @@ static void
296308
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
297309
{
298310
sigset_t *oldset = sigmask_to_save();
299-
int ret;
311+
int failed;
300312

301313
/* Set up the stack frame */
302-
ret = setup_rt_frame(ksig, oldset, regs);
314+
failed = setup_rt_frame(ksig, oldset, regs);
303315

304-
signal_setup_done(ret, ksig, 0);
316+
signal_setup_done(failed, ksig, 0);
305317
}
306318

307319
void do_signal(struct pt_regs *regs)

0 commit comments

Comments
 (0)