diff options
-rw-r--r-- | arch/ppc/kernel/traps.c | 22 | ||||
-rw-r--r-- | arch/ppc/mm/fault.c | 6 | ||||
-rw-r--r-- | include/asm-ppc/system.h | 1 |
3 files changed, 24 insertions, 5 deletions
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 8356d544fa60..961ede87be72 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_code = code; info.si_addr = (void __user *) addr; force_sig_info(signr, &info, current); + + /* + * Init gets no signals that it doesn't have a handler for. + * That's all very well, but if it has caused a synchronous + * exception and we ignore the resulting signal, it will just + * generate the same exception over and over again and we get + * nowhere. Better to kill it and let the kernel panic. + */ + if (current->pid == 1) { + __sighandler_t handler; + + spin_lock_irq(¤t->sighand->siglock); + handler = current->sighand->action[signr-1].sa.sa_handler; + spin_unlock_irq(¤t->sighand->siglock); + if (handler == SIG_DFL) { + /* init has generated a synchronous exception + and it doesn't have a handler for the signal */ + printk(KERN_CRIT "init has generated signal %d " + "but has no handler for it\n", signr); + do_exit(signr); + } + } } /* diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 57d9930843ac..ee5e9f25baf9 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -278,11 +278,7 @@ bad_area: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = code; - info.si_addr = (void __user *) address; - force_sig_info(SIGSEGV, &info, current); + _exception(SIGSEGV, regs, code, address); return 0; } diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h index 513a334c5810..d754ab570fe0 100644 --- a/include/asm-ppc/system.h +++ b/include/asm-ppc/system.h @@ -88,6 +88,7 @@ extern void *cacheable_memcpy(void *, const void *, unsigned int); extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long); extern void bad_page_fault(struct pt_regs *, unsigned long, int); extern void die(const char *, struct pt_regs *, long); +extern void _exception(int, struct pt_regs *, int, unsigned long); #ifdef CONFIG_BOOKE_WDT extern u32 booke_wdt_enabled; extern u32 booke_wdt_period; |