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>

authored by Al Viro and committed by Linus Torvalds bb9c861e a05c4e1d

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