diff options
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_32.c | 38 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal_64.c | 15 | ||||
| -rw-r--r-- | arch/powerpc/kernel/traps.c | 12 | ||||
| -rw-r--r-- | kernel/sysctl.c | 2 |
5 files changed, 71 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index c434d6c4e4e6..a65a44fbe523 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -16,6 +16,12 @@ | |||
| 16 | 16 | ||
| 17 | #include "signal.h" | 17 | #include "signal.h" |
| 18 | 18 | ||
| 19 | /* Log an error when sending an unhandled signal to a process. Controlled | ||
| 20 | * through debug.exception-trace sysctl. | ||
| 21 | */ | ||
| 22 | |||
| 23 | int show_unhandled_signals = 0; | ||
| 24 | |||
| 19 | /* | 25 | /* |
| 20 | * Allocate space for the signal frame | 26 | * Allocate space for the signal frame |
| 21 | */ | 27 | */ |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 590057e9e987..6126bca8b70a 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -705,11 +705,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
| 705 | { | 705 | { |
| 706 | struct rt_sigframe __user *rt_sf; | 706 | struct rt_sigframe __user *rt_sf; |
| 707 | struct mcontext __user *frame; | 707 | struct mcontext __user *frame; |
| 708 | void __user *addr; | ||
| 708 | unsigned long newsp = 0; | 709 | unsigned long newsp = 0; |
| 709 | 710 | ||
| 710 | /* Set up Signal Frame */ | 711 | /* Set up Signal Frame */ |
| 711 | /* Put a Real Time Context onto stack */ | 712 | /* Put a Real Time Context onto stack */ |
| 712 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); | 713 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); |
| 714 | addr = rt_sf; | ||
| 713 | if (unlikely(rt_sf == NULL)) | 715 | if (unlikely(rt_sf == NULL)) |
| 714 | goto badframe; | 716 | goto badframe; |
| 715 | 717 | ||
| @@ -728,6 +730,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
| 728 | 730 | ||
| 729 | /* Save user registers on the stack */ | 731 | /* Save user registers on the stack */ |
| 730 | frame = &rt_sf->uc.uc_mcontext; | 732 | frame = &rt_sf->uc.uc_mcontext; |
| 733 | addr = frame; | ||
| 731 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { | 734 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { |
| 732 | if (save_user_regs(regs, frame, 0)) | 735 | if (save_user_regs(regs, frame, 0)) |
| 733 | goto badframe; | 736 | goto badframe; |
| @@ -742,6 +745,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
| 742 | 745 | ||
| 743 | /* create a stack frame for the caller of the handler */ | 746 | /* create a stack frame for the caller of the handler */ |
| 744 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | 747 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); |
| 748 | addr = (void __user *)regs->gpr[1]; | ||
| 745 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 749 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
| 746 | goto badframe; | 750 | goto badframe; |
| 747 | 751 | ||
| @@ -762,6 +766,12 @@ badframe: | |||
| 762 | printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", | 766 | printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", |
| 763 | regs, frame, newsp); | 767 | regs, frame, newsp); |
| 764 | #endif | 768 | #endif |
| 769 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 770 | printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: " | ||
| 771 | "%p nip %08lx lr %08lx\n", | ||
| 772 | current->comm, current->pid, | ||
| 773 | addr, regs->nip, regs->link); | ||
| 774 | |||
| 765 | force_sigsegv(sig, current); | 775 | force_sigsegv(sig, current); |
| 766 | return 0; | 776 | return 0; |
| 767 | } | 777 | } |
| @@ -886,6 +896,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
| 886 | return 0; | 896 | return 0; |
| 887 | 897 | ||
| 888 | bad: | 898 | bad: |
| 899 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 900 | printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: " | ||
| 901 | "%p nip %08lx lr %08lx\n", | ||
| 902 | current->comm, current->pid, | ||
| 903 | rt_sf, regs->nip, regs->link); | ||
| 904 | |||
| 889 | force_sig(SIGSEGV, current); | 905 | force_sig(SIGSEGV, current); |
| 890 | return 0; | 906 | return 0; |
| 891 | } | 907 | } |
| @@ -967,6 +983,13 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 967 | * We kill the task with a SIGSEGV in this situation. | 983 | * We kill the task with a SIGSEGV in this situation. |
| 968 | */ | 984 | */ |
| 969 | if (do_setcontext(ctx, regs, 1)) { | 985 | if (do_setcontext(ctx, regs, 1)) { |
| 986 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 987 | printk(KERN_INFO "%s[%d]: bad frame in " | ||
| 988 | "sys_debug_setcontext: %p nip %08lx " | ||
| 989 | "lr %08lx\n", | ||
| 990 | current->comm, current->pid, | ||
| 991 | ctx, regs->nip, regs->link); | ||
| 992 | |||
| 970 | force_sig(SIGSEGV, current); | 993 | force_sig(SIGSEGV, current); |
| 971 | goto out; | 994 | goto out; |
| 972 | } | 995 | } |
| @@ -1048,6 +1071,12 @@ badframe: | |||
| 1048 | printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", | 1071 | printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", |
| 1049 | regs, frame, newsp); | 1072 | regs, frame, newsp); |
| 1050 | #endif | 1073 | #endif |
| 1074 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 1075 | printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: " | ||
| 1076 | "%p nip %08lx lr %08lx\n", | ||
| 1077 | current->comm, current->pid, | ||
| 1078 | frame, regs->nip, regs->link); | ||
| 1079 | |||
| 1051 | force_sigsegv(sig, current); | 1080 | force_sigsegv(sig, current); |
| 1052 | return 0; | 1081 | return 0; |
| 1053 | } | 1082 | } |
| @@ -1061,12 +1090,14 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
| 1061 | struct sigcontext __user *sc; | 1090 | struct sigcontext __user *sc; |
| 1062 | struct sigcontext sigctx; | 1091 | struct sigcontext sigctx; |
| 1063 | struct mcontext __user *sr; | 1092 | struct mcontext __user *sr; |
| 1093 | void __user *addr; | ||
| 1064 | sigset_t set; | 1094 | sigset_t set; |
| 1065 | 1095 | ||
| 1066 | /* Always make any pending restarted system calls return -EINTR */ | 1096 | /* Always make any pending restarted system calls return -EINTR */ |
| 1067 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 1097 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 1068 | 1098 | ||
| 1069 | sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); | 1099 | sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); |
| 1100 | addr = sc; | ||
| 1070 | if (copy_from_user(&sigctx, sc, sizeof(sigctx))) | 1101 | if (copy_from_user(&sigctx, sc, sizeof(sigctx))) |
| 1071 | goto badframe; | 1102 | goto badframe; |
| 1072 | 1103 | ||
| @@ -1083,6 +1114,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
| 1083 | restore_sigmask(&set); | 1114 | restore_sigmask(&set); |
| 1084 | 1115 | ||
| 1085 | sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); | 1116 | sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); |
| 1117 | addr = sr; | ||
| 1086 | if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) | 1118 | if (!access_ok(VERIFY_READ, sr, sizeof(*sr)) |
| 1087 | || restore_user_regs(regs, sr, 1)) | 1119 | || restore_user_regs(regs, sr, 1)) |
| 1088 | goto badframe; | 1120 | goto badframe; |
| @@ -1091,6 +1123,12 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
| 1091 | return 0; | 1123 | return 0; |
| 1092 | 1124 | ||
| 1093 | badframe: | 1125 | badframe: |
| 1126 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 1127 | printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: " | ||
| 1128 | "%p nip %08lx lr %08lx\n", | ||
| 1129 | current->comm, current->pid, | ||
| 1130 | addr, regs->nip, regs->link); | ||
| 1131 | |||
| 1094 | force_sig(SIGSEGV, current); | 1132 | force_sig(SIGSEGV, current); |
| 1095 | return 0; | 1133 | return 0; |
| 1096 | } | 1134 | } |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index de895e6d8c62..faeb8f207ea4 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -64,6 +64,11 @@ struct rt_sigframe { | |||
| 64 | char abigap[288]; | 64 | char abigap[288]; |
| 65 | } __attribute__ ((aligned (16))); | 65 | } __attribute__ ((aligned (16))); |
| 66 | 66 | ||
| 67 | static const char fmt32[] = KERN_INFO \ | ||
| 68 | "%s[%d]: bad frame in %s: %08lx nip %08lx lr %08lx\n"; | ||
| 69 | static const char fmt64[] = KERN_INFO \ | ||
| 70 | "%s[%d]: bad frame in %s: %016lx nip %016lx lr %016lx\n"; | ||
| 71 | |||
| 67 | /* | 72 | /* |
| 68 | * Set up the sigcontext for the signal frame. | 73 | * Set up the sigcontext for the signal frame. |
| 69 | */ | 74 | */ |
| @@ -315,6 +320,11 @@ badframe: | |||
| 315 | printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", | 320 | printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", |
| 316 | regs, uc, &uc->uc_mcontext); | 321 | regs, uc, &uc->uc_mcontext); |
| 317 | #endif | 322 | #endif |
| 323 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 324 | printk(regs->msr & MSR_SF ? fmt64 : fmt32, | ||
| 325 | current->comm, current->pid, "rt_sigreturn", | ||
| 326 | (long)uc, regs->nip, regs->link); | ||
| 327 | |||
| 318 | force_sig(SIGSEGV, current); | 328 | force_sig(SIGSEGV, current); |
| 319 | return 0; | 329 | return 0; |
| 320 | } | 330 | } |
| @@ -398,6 +408,11 @@ badframe: | |||
| 398 | printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", | 408 | printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", |
| 399 | regs, frame, newsp); | 409 | regs, frame, newsp); |
| 400 | #endif | 410 | #endif |
| 411 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 412 | printk(regs->msr & MSR_SF ? fmt64 : fmt32, | ||
| 413 | current->comm, current->pid, "setup_rt_frame", | ||
| 414 | (long)frame, regs->nip, regs->link); | ||
| 415 | |||
| 401 | force_sigsegv(signr, current); | 416 | force_sigsegv(signr, current); |
| 402 | return 0; | 417 | return 0; |
| 403 | } | 418 | } |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 2f1857c9819f..bf9e39c6e296 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -172,11 +172,21 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 172 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | 172 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) |
| 173 | { | 173 | { |
| 174 | siginfo_t info; | 174 | siginfo_t info; |
| 175 | const char fmt32[] = KERN_INFO "%s[%d]: unhandled signal %d " \ | ||
| 176 | "at %08lx nip %08lx lr %08lx code %x\n"; | ||
| 177 | const char fmt64[] = KERN_INFO "%s[%d]: unhandled signal %d " \ | ||
| 178 | "at %016lx nip %016lx lr %016lx code %x\n"; | ||
| 175 | 179 | ||
| 176 | if (!user_mode(regs)) { | 180 | if (!user_mode(regs)) { |
| 177 | if (die("Exception in kernel mode", regs, signr)) | 181 | if (die("Exception in kernel mode", regs, signr)) |
| 178 | return; | 182 | return; |
| 179 | } | 183 | } else if (show_unhandled_signals && |
| 184 | unhandled_signal(current, signr) && | ||
| 185 | printk_ratelimit()) { | ||
| 186 | printk(regs->msr & MSR_SF ? fmt64 : fmt32, | ||
| 187 | current->comm, current->pid, signr, | ||
| 188 | addr, regs->nip, regs->link, code); | ||
| 189 | } | ||
| 180 | 190 | ||
| 181 | memset(&info, 0, sizeof(info)); | 191 | memset(&info, 0, sizeof(info)); |
| 182 | info.si_signo = signr; | 192 | info.si_signo = signr; |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 53a456ebf6d5..c7314f952647 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -1221,7 +1221,7 @@ static ctl_table fs_table[] = { | |||
| 1221 | }; | 1221 | }; |
| 1222 | 1222 | ||
| 1223 | static ctl_table debug_table[] = { | 1223 | static ctl_table debug_table[] = { |
| 1224 | #ifdef CONFIG_X86 | 1224 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) |
| 1225 | { | 1225 | { |
| 1226 | .ctl_name = CTL_UNNUMBERED, | 1226 | .ctl_name = CTL_UNNUMBERED, |
| 1227 | .procname = "exception-trace", | 1227 | .procname = "exception-trace", |
