Skip to content

Commit e414081

Browse files
committed
ARC: signal handling robustify
A malicious signal handler / restorer can DOS the system by fudging the user regs saved on stack, causing weird things such as sigreturn returning to user mode PC but cpu state still being kernel mode.... Ensure that in sigreturn path status32 always has U bit; any other bogosity (gargbage PC etc) will be taken care of by normal user mode exceptions mechanisms. Reproducer signal handler: void handle_sig(int signo, siginfo_t *info, void *context) { ucontext_t *uc = context; struct user_regs_struct *regs = &(uc->uc_mcontext.regs); regs->scratch.status32 = 0; } Before the fix, kernel would go off to weeds like below: --------->8----------- [ARCLinux]$ ./signal-test Path: /signal-test CPU: 0 PID: 61 Comm: signal-test Not tainted 4.0.0-rc5+ raspberrypi#65 task: 8f177880 ti: 5ffe6000 task.ti: 8f15c000 [ECR ]: 0x00220200 => Invalid Write @ 0x00000010 by insn @ 0x00010698 [EFA ]: 0x00000010 [BLINK ]: 0x2007c1ee [ERET ]: 0x10698 [STAT32]: 0x00000000 : <-------- BTA: 0x00010680 SP: 0x5ffe7e48 FP: 0x00000000 LPS: 0x20003c6c LPE: 0x20003c70 LPC: 0x00000000 ... --------->8----------- Reported-by: Alexey Brodkin <[email protected]> Cc: <[email protected]> Signed-off-by: Vineet Gupta <[email protected]>
1 parent 6914e1e commit e414081

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

arch/arc/kernel/signal.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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)