diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 182c6a39d5a2d553322450eb13cb61ddee22d32b..ab38322111c4c7e83275b0c163490535a45745b5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1383,6 +1383,12 @@ and is between 256 and 4096 characters. It is defined in the file autoconfiguration. Ranges are in pairs (memory base and size). + print-fatal-signals= + [KNL] debug: print fatal signals + print-fatal-signals=1: print segfault info to + the kernel console. + default: off. + profile= [KNL] Enable kernel profiling via /proc/profile Format: [schedule,] Param: "schedule" - profile schedule points. diff --git a/kernel/signal.c b/kernel/signal.c index f9405609774eadc4115006e8f80f418413d84217..39d122753bac93eb7cfa62d0f2e2e451a4908dd5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -718,6 +718,37 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, #define LEGACY_QUEUE(sigptr, sig) \ (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig))) +int print_fatal_signals; + +static void print_fatal_signal(struct pt_regs *regs, int signr) +{ + printk("%s/%d: potentially unexpected fatal signal %d.\n", + current->comm, current->pid, signr); + +#ifdef __i386__ + printk("code at %08lx: ", regs->eip); + { + int i; + for (i = 0; i < 16; i++) { + unsigned char insn; + + __get_user(insn, (unsigned char *)(regs->eip + i)); + printk("%02x ", insn); + } + } +#endif + printk("\n"); + show_regs(regs); +} + +static int __init setup_print_fatal_signals(char *str) +{ + get_option (&str, &print_fatal_signals); + + return 1; +} + +__setup("print-fatal-signals=", setup_print_fatal_signals); static int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) @@ -1855,6 +1886,8 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, * Anything else is fatal, maybe with a core dump. */ current->flags |= PF_SIGNALED; + if ((signr != SIGKILL) && print_fatal_signals) + print_fatal_signal(regs, signr); if (sig_kernel_coredump(signr)) { /* * If it was able to dump core, this kills all diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ccaebbbd75ae4f0b66119c0a1dce610b232e0115..2cce2286bdcda987a8a95e5830e5830ff1911e0f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -61,6 +61,7 @@ extern int proc_nr_files(ctl_table *table, int write, struct file *filp, /* External variables not in a header file. */ extern int C_A_D; +extern int print_fatal_signals; extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; extern int sysctl_panic_on_oom; @@ -340,6 +341,14 @@ static ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif + { + .ctl_name = CTL_UNNUMBERED, + .procname = "print-fatal-signals", + .data = &print_fatal_signals, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, #ifdef __sparc__ { .ctl_name = KERN_SPARC_REBOOT,