Commit bb0bb3b6 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc32: Kill init on unhandled synchronous signals

This is a patch that I have had in my tree for ages.  If init causes
an exception that raises a signal, such as a SIGSEGV, SIGILL or
SIGFPE, and it hasn't registered a handler for it, we don't deliver
the signal, since init doesn't get any signals that it doesn't have a
handler for.  But that means that we just return to userland and
generate the same exception again immediately.  With this patch we
print a message and kill init in this situation.

This is very useful when you have a bug in the kernel that means that
init doesn't get as far as executing its first instruction. :)
Without this patch the system hangs when it gets to starting the
userland init; with it you at least get a message giving you a clue
about what has gone wrong.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 1e63bc73
...@@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) ...@@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
info.si_code = code; info.si_code = code;
info.si_addr = (void __user *) addr; info.si_addr = (void __user *) addr;
force_sig_info(signr, &info, current); 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(&current->sighand->siglock);
handler = current->sighand->action[signr-1].sa.sa_handler;
spin_unlock_irq(&current->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);
}
}
} }
/* /*
......
...@@ -278,11 +278,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -278,11 +278,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
/* User mode accesses cause a SIGSEGV */ /* User mode accesses cause a SIGSEGV */
if (user_mode(regs)) { if (user_mode(regs)) {
info.si_signo = SIGSEGV; _exception(SIGSEGV, regs, code, address);
info.si_errno = 0;
info.si_code = code;
info.si_addr = (void __user *) address;
force_sig_info(SIGSEGV, &info, current);
return 0; return 0;
} }
......
...@@ -88,6 +88,7 @@ extern void *cacheable_memcpy(void *, const void *, unsigned int); ...@@ -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 int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
extern void bad_page_fault(struct pt_regs *, unsigned long, int); extern void bad_page_fault(struct pt_regs *, unsigned long, int);
extern void die(const char *, struct pt_regs *, long); extern void die(const char *, struct pt_regs *, long);
extern void _exception(int, struct pt_regs *, int, unsigned long);
#ifdef CONFIG_BOOKE_WDT #ifdef CONFIG_BOOKE_WDT
extern u32 booke_wdt_enabled; extern u32 booke_wdt_enabled;
extern u32 booke_wdt_period; extern u32 booke_wdt_period;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment