Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 60527
b: refs/heads/master
c: a3f61dc
h: refs/heads/master
i:
  60525: 78111bc
  60523: 5e8319b
  60519: add8f65
  60511: 4ce3fe4
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jun 14, 2007
1 parent 64bfba9 commit c283c95
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5f9f375a62d3fd3d7f0d5adc23039ade523e62ba
refs/heads/master: a3f61dc0a5335334958ec3b97d0b1946b4ae5375
39 changes: 29 additions & 10 deletions trunk/arch/powerpc/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <linux/ptrace.h>
#include <linux/signal.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>

#include "signal.h"
Expand All @@ -28,6 +29,32 @@ static inline int is_32bit_task(void)
}
#endif

/*
* Allocate space for the signal frame
*/
void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
{
unsigned long oldsp, newsp;

/* Default to using normal stack */
oldsp = regs->gpr[1];

/* Check for alt stack */
if ((ka->sa.sa_flags & SA_ONSTACK) &&
current->sas_ss_size && !on_sig_stack(oldsp))
oldsp = (current->sas_ss_sp + current->sas_ss_size);

/* Get aligned frame */
newsp = (oldsp - frame_size) & ~0xFUL;

/* Check access */
if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp))
return NULL;

return (void __user *)newsp;
}


/*
* Restore the user process's signal mask
Expand Down Expand Up @@ -130,20 +157,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
#endif

if (is32) {
unsigned int newsp;

if ((ka.sa.sa_flags & SA_ONSTACK) &&
current->sas_ss_size && !on_sig_stack(regs->gpr[1]))
newsp = current->sas_ss_sp + current->sas_ss_size;
else
newsp = regs->gpr[1];

if (ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal32(signr, &ka, &info, oldset,
regs, newsp);
regs);
else
ret = handle_signal32(signr, &ka, &info, oldset,
regs, newsp);
regs);
#ifdef CONFIG_PPC64
} else {
ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
Expand Down
6 changes: 4 additions & 2 deletions trunk/arch/powerpc/kernel/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size);
extern void restore_sigmask(sigset_t *set);

extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, unsigned long newsp);
struct pt_regs *regs);

extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, unsigned long newsp);
struct pt_regs *regs);

extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
siginfo_t *info, sigset_t *set,
Expand Down
52 changes: 24 additions & 28 deletions trunk/arch/powerpc/kernel/signal_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act,
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* an ABI gap of 56 words
* an mcontext struct
* a sigcontext struct
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
* Each of these things must be a multiple of 16 bytes in size. The following
* structure represent all of this except the __SIGNAL_FRAMESIZE gap
*
*/
struct sigregs {
struct sigframe {
struct sigcontext sctx; /* the sigcontext */
struct mcontext mctx; /* all the register values */
/*
* Programs using the rs6000/xcoff abi can save up to 19 gp
Expand Down Expand Up @@ -698,21 +701,16 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5,
*/
int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs, unsigned long newsp)
struct pt_regs *regs)
{
struct rt_sigframe __user *rt_sf;
struct mcontext __user *frame;
unsigned long origsp = newsp;
unsigned long newsp = 0;

/* Set up Signal Frame */
/* Put a Real Time Context onto stack */
newsp -= sizeof(*rt_sf);
rt_sf = (struct rt_sigframe __user *)newsp;

/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE + 16;

if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
if (unlikely(rt_sf == NULL))
goto badframe;

/* Put the siginfo & fill in most of the ucontext */
Expand Down Expand Up @@ -742,8 +740,12 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,

current->thread.fpscr.val = 0; /* turn off all fp exceptions */

/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;

/* Fill registers for signal handler */
regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) &rt_sf->info;
Expand Down Expand Up @@ -988,26 +990,17 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
* OK, we're invoking a handler
*/
int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
unsigned long newsp)
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
struct sigcontext __user *sc;
struct sigregs __user *frame;
unsigned long origsp = newsp;
struct sigframe __user *frame;
unsigned long newsp = 0;

/* Set up Signal Frame */
newsp -= sizeof(struct sigregs);
frame = (struct sigregs __user *) newsp;

/* Put a sigcontext on the stack */
newsp -= sizeof(*sc);
sc = (struct sigcontext __user *) newsp;

/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE;

if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
frame = get_sigframe(ka, regs, sizeof(*frame));
if (unlikely(frame == NULL))
goto badframe;
sc = (struct sigcontext __user *) &frame->sctx;

#if _NSIG != 64
#error "Please adjust handle_signal()"
Expand All @@ -1019,7 +1012,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
#else
|| __put_user(oldset->sig[1], &sc->_unused[3])
#endif
|| __put_user(to_user_ptr(frame), &sc->regs)
|| __put_user(to_user_ptr(&frame->mctx), &sc->regs)
|| __put_user(sig, &sc->signal))
goto badframe;

Expand All @@ -1035,8 +1028,11 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,

current->thread.fpscr.val = 0; /* turn off all fp exceptions */

/* create a stack frame for the caller of the handler */
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
if (put_user(regs->gpr[1], (u32 __user *)newsp))
goto badframe;

regs->gpr[1] = newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
Expand Down
24 changes: 2 additions & 22 deletions trunk/arch/powerpc/kernel/signal_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,25 +195,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
return err;
}

/*
* Allocate space for the signal frame
*/
static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size)
{
unsigned long newsp;

/* Default to using normal stack */
newsp = regs->gpr[1];

if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
if (! on_sig_stack(regs->gpr[1]))
newsp = (current->sas_ss_sp + current->sas_ss_size);
}

return (void __user *)((newsp - frame_size) & -16ul);
}

/*
* Setup the trampoline code on the stack
*/
Expand Down Expand Up @@ -348,8 +329,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
long err = 0;

frame = get_sigframe(ka, regs, sizeof(*frame));

if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
if (unlikely(frame == NULL))
goto badframe;

err |= __put_user(&frame->info, &frame->pinfo);
Expand Down Expand Up @@ -386,7 +366,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;

/* Allocate a dummy caller frame for the signal handler. */
newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);

/* Set up "regs" so we "return" to the signal handler. */
Expand Down

0 comments on commit c283c95

Please sign in to comment.