diff options
author | Olof Johansson <olof@lixom.net> | 2007-10-11 20:20:07 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-10-12 00:05:18 -0400 |
commit | d0c3d534a4388a465101b634a95f2ec586415254 (patch) | |
tree | e6acdc89adcb9057b7bbaeba55332fdcb97c2ceb /arch/powerpc/kernel/signal_32.c | |
parent | b63db45ca44a805ef21eb10a3750e88419156423 (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/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 38 |
1 files changed, 38 insertions, 0 deletions
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 | } |