Commit bb9c861ee1b94c97cd98c783a2b4c1cf53ff1712

Authored by Al Viro
Committed by Linus Torvalds
1 parent a05c4e1d66

m32r: hole in shifting pc back

It's a userland pointer; worse, an untrustable one since ptrace
has just provided a chance to modify it.

X-Roothole-Covering-Cabal: TINRCC
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 17 additions and 21 deletions Side-by-side Diff

arch/m32r/kernel/signal.c
... ... @@ -251,6 +251,19 @@
251 251 return -EFAULT;
252 252 }
253 253  
  254 +static int prev_insn(struct pt_regs *regs)
  255 +{
  256 + u16 inst;
  257 + if (get_user(&inst, (u16 __user *)(regs->bpc - 2)))
  258 + return -EFAULT;
  259 + if ((inst & 0xfff0) == 0x10f0) /* trap ? */
  260 + regs->bpc -= 2;
  261 + else
  262 + regs->bpc -= 4;
  263 + regs->syscall_nr = -1;
  264 + return 0;
  265 +}
  266 +
254 267 /*
255 268 * OK, we're invoking a handler
256 269 */
... ... @@ -259,8 +272,6 @@
259 272 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
260 273 sigset_t *oldset, struct pt_regs *regs)
261 274 {
262   - unsigned short inst;
263   -
264 275 /* Are we from a system call? */
265 276 if (regs->syscall_nr >= 0) {
266 277 /* If so, check system call restarting.. */
... ... @@ -278,12 +289,8 @@
278 289 /* fallthrough */
279 290 case -ERESTARTNOINTR:
280 291 regs->r0 = regs->orig_r0;
281   - inst = *(unsigned short *)(regs->bpc - 2);
282   - if ((inst & 0xfff0) == 0x10f0) /* trap ? */
283   - regs->bpc -= 2;
284   - else
285   - regs->bpc -= 4;
286   - regs->syscall_nr = -1;
  292 + if (prev_insn(regs) < 0)
  293 + return -EFAULT;
287 294 }
288 295 }
289 296  
... ... @@ -310,7 +317,6 @@
310 317 siginfo_t info;
311 318 int signr;
312 319 struct k_sigaction ka;
313   - unsigned short inst;
314 320 sigset_t *oldset;
315 321  
316 322 /*
317 323  
... ... @@ -353,21 +359,11 @@
353 359 regs->r0 == -ERESTARTSYS ||
354 360 regs->r0 == -ERESTARTNOINTR) {
355 361 regs->r0 = regs->orig_r0;
356   - inst = *(unsigned short *)(regs->bpc - 2);
357   - if ((inst & 0xfff0) == 0x10f0) /* trap ? */
358   - regs->bpc -= 2;
359   - else
360   - regs->bpc -= 4;
361   - regs->syscall_nr = -1;
  362 + prev_insn(regs);
362 363 } else if (regs->r0 == -ERESTART_RESTARTBLOCK){
363 364 regs->r0 = regs->orig_r0;
364 365 regs->r7 = __NR_restart_syscall;
365   - inst = *(unsigned short *)(regs->bpc - 2);
366   - if ((inst & 0xfff0) == 0x10f0) /* trap ? */
367   - regs->bpc -= 2;
368   - else
369   - regs->bpc -= 4;
370   - regs->syscall_nr = -1;
  366 + prev_insn(regs);
371 367 }
372 368 }
373 369 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {