From e8c797a8d8816447a101d1f3a3c6913c2827813a Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 13 Apr 2004 21:09:33 -0700 Subject: [PATCH] [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) --- arch/ppc64/kernel/signal.c | 31 +++++++++++++++++++++++-------- arch/ppc64/kernel/signal32.c | 21 ++++++++++++--------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c index 9e01dd3f3eb39..c05dce7ed939d 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/ppc64/kernel/signal.c @@ -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(¤t->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)); diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c index 36760e6d30596..cda17d433e238 100644 --- a/arch/ppc64/kernel/signal32.c +++ b/arch/ppc64/kernel/signal32.c @@ -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; -- 2.53.0