aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_32.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-06-04 03:22:48 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:58 -0400
commita3f61dc0a5335334958ec3b97d0b1946b4ae5375 (patch)
treee7b151d724dca73220d8346c2a0c2a3525c5c91c /arch/powerpc/kernel/signal_32.c
parent5f9f375a62d3fd3d7f0d5adc23039ade523e62ba (diff)
[POWERPC] Merge creation of signal frame
The code for creating signal frames was still duplicated and split in strange ways between 32 and 64 bits, including the SA_ONSTACK handling being in do_signal on 32 bits but inside handle_rt_signal on 64 bits etc... This moves the 64 bits get_sigframe() to the generic signal.c, cleans it a bit, moves the access_ok() call done by all callers to it as well, and adapts/cleanups the 3 different signal handling cases to use that common function. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> 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.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 32481e71d71e..590057e9e987 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -282,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,
282/* 282/*
283 * When we have signals to deliver, we set up on the 283 * When we have signals to deliver, we set up on the
284 * user stack, going down from the original stack pointer: 284 * user stack, going down from the original stack pointer:
285 * a sigregs struct 285 * an ABI gap of 56 words
286 * an mcontext struct
286 * a sigcontext struct 287 * a sigcontext struct
287 * a gap of __SIGNAL_FRAMESIZE bytes 288 * a gap of __SIGNAL_FRAMESIZE bytes
288 * 289 *
289 * Each of these things must be a multiple of 16 bytes in size. 290 * Each of these things must be a multiple of 16 bytes in size. The following
291 * structure represent all of this except the __SIGNAL_FRAMESIZE gap
290 * 292 *
291 */ 293 */
292struct sigregs { 294struct sigframe {
295 struct sigcontext sctx; /* the sigcontext */
293 struct mcontext mctx; /* all the register values */ 296 struct mcontext mctx; /* all the register values */
294 /* 297 /*
295 * Programs using the rs6000/xcoff abi can save up to 19 gp 298 * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -698,21 +701,16 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
698 */ 701 */
699int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, 702int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
700 siginfo_t *info, sigset_t *oldset, 703 siginfo_t *info, sigset_t *oldset,
701 struct pt_regs *regs, unsigned long newsp) 704 struct pt_regs *regs)
702{ 705{
703 struct rt_sigframe __user *rt_sf; 706 struct rt_sigframe __user *rt_sf;
704 struct mcontext __user *frame; 707 struct mcontext __user *frame;
705 unsigned long origsp = newsp; 708 unsigned long newsp = 0;
706 709
707 /* Set up Signal Frame */ 710 /* Set up Signal Frame */
708 /* Put a Real Time Context onto stack */ 711 /* Put a Real Time Context onto stack */
709 newsp -= sizeof(*rt_sf); 712 rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
710 rt_sf = (struct rt_sigframe __user *)newsp; 713 if (unlikely(rt_sf == NULL))
711
712 /* create a stack frame for the caller of the handler */
713 newsp -= __SIGNAL_FRAMESIZE + 16;
714
715 if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
716 goto badframe; 714 goto badframe;
717 715
718 /* Put the siginfo & fill in most of the ucontext */ 716 /* Put the siginfo & fill in most of the ucontext */
@@ -742,8 +740,12 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
742 740
743 current->thread.fpscr.val = 0; /* turn off all fp exceptions */ 741 current->thread.fpscr.val = 0; /* turn off all fp exceptions */
744 742
743 /* create a stack frame for the caller of the handler */
744 newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
745 if (put_user(regs->gpr[1], (u32 __user *)newsp)) 745 if (put_user(regs->gpr[1], (u32 __user *)newsp))
746 goto badframe; 746 goto badframe;
747
748 /* Fill registers for signal handler */
747 regs->gpr[1] = newsp; 749 regs->gpr[1] = newsp;
748 regs->gpr[3] = sig; 750 regs->gpr[3] = sig;
749 regs->gpr[4] = (unsigned long) &rt_sf->info; 751 regs->gpr[4] = (unsigned long) &rt_sf->info;
@@ -988,26 +990,17 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
988 * OK, we're invoking a handler 990 * OK, we're invoking a handler
989 */ 991 */
990int handle_signal32(unsigned long sig, struct k_sigaction *ka, 992int handle_signal32(unsigned long sig, struct k_sigaction *ka,
991 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, 993 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
992 unsigned long newsp)
993{ 994{
994 struct sigcontext __user *sc; 995 struct sigcontext __user *sc;
995 struct sigregs __user *frame; 996 struct sigframe __user *frame;
996 unsigned long origsp = newsp; 997 unsigned long newsp = 0;
997 998
998 /* Set up Signal Frame */ 999 /* Set up Signal Frame */
999 newsp -= sizeof(struct sigregs); 1000 frame = get_sigframe(ka, regs, sizeof(*frame));
1000 frame = (struct sigregs __user *) newsp; 1001 if (unlikely(frame == NULL))
1001
1002 /* Put a sigcontext on the stack */
1003 newsp -= sizeof(*sc);
1004 sc = (struct sigcontext __user *) newsp;
1005
1006 /* create a stack frame for the caller of the handler */
1007 newsp -= __SIGNAL_FRAMESIZE;
1008
1009 if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
1010 goto badframe; 1002 goto badframe;
1003 sc = (struct sigcontext __user *) &frame->sctx;
1011 1004
1012#if _NSIG != 64 1005#if _NSIG != 64
1013#error "Please adjust handle_signal()" 1006#error "Please adjust handle_signal()"
@@ -1019,7 +1012,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1019#else 1012#else
1020 || __put_user(oldset->sig[1], &sc->_unused[3]) 1013 || __put_user(oldset->sig[1], &sc->_unused[3])
1021#endif 1014#endif
1022 || __put_user(to_user_ptr(frame), &sc->regs) 1015 || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
1023 || __put_user(sig, &sc->signal)) 1016 || __put_user(sig, &sc->signal))
1024 goto badframe; 1017 goto badframe;
1025 1018
@@ -1035,8 +1028,11 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
1035 1028
1036 current->thread.fpscr.val = 0; /* turn off all fp exceptions */ 1029 current->thread.fpscr.val = 0; /* turn off all fp exceptions */
1037 1030
1031 /* create a stack frame for the caller of the handler */
1032 newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
1038 if (put_user(regs->gpr[1], (u32 __user *)newsp)) 1033 if (put_user(regs->gpr[1], (u32 __user *)newsp))
1039 goto badframe; 1034 goto badframe;
1035
1040 regs->gpr[1] = newsp; 1036 regs->gpr[1] = newsp;
1041 regs->gpr[3] = sig; 1037 regs->gpr[3] = sig;
1042 regs->gpr[4] = (unsigned long) sc; 1038 regs->gpr[4] = (unsigned long) sc;