]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64 signal frame issue
authorAnton Blanchard <anton@samba.org>
Wed, 14 Apr 2004 04:09:33 +0000 (21:09 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 14 Apr 2004 04:09:33 +0000 (21:09 -0700)
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)

arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal32.c

index 9e01dd3f3eb39617ffcd9b4a722aae71c47e1588..c05dce7ed939da175b32c4ce79f2b6efa84f5029 100644 (file)
@@ -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));
 
index 36760e6d305966abb40a91ba3a8984818b563cc5..cda17d433e23874feb5be628ba40698f1c6add28 100644 (file)
@@ -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;