Commit e8c797a8 authored by Anton Blanchard's avatar Anton Blanchard Committed by Linus Torvalds

[PATCH] ppc64 signal frame issue

Fix a corruption bug, we were copying too much information back off
the signal frame.

While in the area help with gccs sign extension optimisation problems
and convert some things to long. (Saves about 30 instructions in signal.c)
parent e1fdc381
......@@ -115,7 +115,7 @@ long sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r5,
* Set up the sigcontext for the signal frame.
*/
static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
static long setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
int signr, sigset_t *set, unsigned long handler)
{
/* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
......@@ -129,7 +129,7 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
#ifdef CONFIG_ALTIVEC
elf_vrreg_t *v_regs = (elf_vrreg_t *)(((unsigned long)sc->vmx_reserve) & ~0xful);
#endif
int err = 0;
long err = 0;
if (regs->msr & MSR_FP)
giveup_fpu(current);
......@@ -173,18 +173,32 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
* Restore the sigcontext from the signal frame.
*/
static int restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, struct sigcontext *sc)
static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
struct sigcontext *sc)
{
#ifdef CONFIG_ALTIVEC
elf_vrreg_t *v_regs;
#endif
unsigned int err = 0;
unsigned long err = 0;
unsigned long save_r13;
elf_greg_t *gregs = (elf_greg_t *)regs;
int i;
/* If this is not a signal return, we preserve the TLS in r13 */
if (!sig)
save_r13 = regs->gpr[13];
err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE);
/* copy everything before MSR */
err |= __copy_from_user(regs, &sc->gp_regs,
PT_MSR*sizeof(unsigned long));
/* skip MSR and SOFTE */
for (i = PT_MSR+1; i <= PT_RESULT; i++) {
if (i == PT_SOFTE)
continue;
err |= __get_user(gregs[i], &sc->gp_regs[i]);
}
if (!sig)
regs->gpr[13] = save_r13;
err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
......@@ -235,9 +249,10 @@ static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
/*
* Setup the trampoline code on the stack
*/
static int setup_trampoline(unsigned int syscall, unsigned int *tramp)
static long setup_trampoline(unsigned int syscall, unsigned int *tramp)
{
int i, err = 0;
int i;
long err = 0;
/* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */
err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]);
......@@ -372,7 +387,7 @@ static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
func_descr_t *funct_desc_ptr;
struct rt_sigframe *frame;
unsigned long newsp = 0;
int err = 0;
long err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame));
......
......@@ -185,25 +185,28 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext32 *frame, int si
* Restore the current user register values from the user stack,
* (except for MSR).
*/
static int restore_user_regs(struct pt_regs *regs, struct mcontext32 __user *sr, int sig)
static long restore_user_regs(struct pt_regs *regs,
struct mcontext32 __user *sr, int sig)
{
elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
int i, err = 0;
int i;
long err = 0;
unsigned int save_r2;
#ifdef CONFIG_ALTIVEC
unsigned long msr;
#endif
/*
* restore general registers but not including MSR. Also take
* care of keeping r2 (TLS) intact if not a signal
* restore general registers but not including MSR or SOFTE. Also
* take care of keeping r2 (TLS) intact if not a signal
*/
if (!sig)
save_r2 = (unsigned int)regs->gpr[2];
for (i = 0; i < PT_MSR; i ++)
err |= __get_user(gregs[i], &sr->mc_gregs[i]);
for (i ++; i <= PT_RESULT; i ++)
for (i = 0; i <= PT_RESULT; i++) {
if ((i == PT_MSR) || (i == PT_SOFTE))
continue;
err |= __get_user(gregs[i], &sr->mc_gregs[i]);
}
if (!sig)
regs->gpr[2] = (unsigned long) save_r2;
if (err)
......@@ -427,9 +430,9 @@ long sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize)
}
static int copy_siginfo_to_user32(compat_siginfo_t *d, siginfo_t *s)
static long copy_siginfo_to_user32(compat_siginfo_t *d, siginfo_t *s)
{
int err;
long err;
if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
return -EFAULT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment