aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-10-11 20:20:07 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-12 00:05:18 -0400
commitd0c3d534a4388a465101b634a95f2ec586415254 (patch)
treee6acdc89adcb9057b7bbaeba55332fdcb97c2ceb /arch/powerpc
parentb63db45ca44a805ef21eb10a3750e88419156423 (diff)
[POWERPC] Implement logging of unhandled signals
Implement show_unhandled_signals sysctl + support to print when a process is killed due to unhandled signals just as i386 and x86_64 does. Default to having it off, unlike x86 that defaults on. Signed-off-by: Olof Johansson <olof@lixom.net> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/signal.c6
-rw-r--r--arch/powerpc/kernel/signal_32.c38
-rw-r--r--arch/powerpc/kernel/signal_64.c15
-rw-r--r--arch/powerpc/kernel/traps.c12
4 files changed, 70 insertions, 1 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
23int 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
1093badframe: 1125badframe:
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
67static const char fmt32[] = KERN_INFO \
68 "%s[%d]: bad frame in %s: %08lx nip %08lx lr %08lx\n";
69static 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)
172void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) 172void _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;