diff options
| -rw-r--r-- | arch/openrisc/include/asm/sigcontext.h | 7 | ||||
| -rw-r--r-- | arch/openrisc/kernel/signal.c | 29 |
2 files changed, 12 insertions, 24 deletions
diff --git a/arch/openrisc/include/asm/sigcontext.h b/arch/openrisc/include/asm/sigcontext.h index 54a5c50132e3..b79c2b19afbe 100644 --- a/arch/openrisc/include/asm/sigcontext.h +++ b/arch/openrisc/include/asm/sigcontext.h | |||
| @@ -23,16 +23,11 @@ | |||
| 23 | 23 | ||
| 24 | /* This struct is saved by setup_frame in signal.c, to keep the current | 24 | /* This struct is saved by setup_frame in signal.c, to keep the current |
| 25 | context while a signal handler is executed. It's restored by sys_sigreturn. | 25 | context while a signal handler is executed. It's restored by sys_sigreturn. |
| 26 | |||
| 27 | To keep things simple, we use pt_regs here even though normally you just | ||
| 28 | specify the list of regs to save. Then we can use copy_from_user on the | ||
| 29 | entire regs instead of a bunch of get_user's as well... | ||
| 30 | */ | 26 | */ |
| 31 | 27 | ||
| 32 | struct sigcontext { | 28 | struct sigcontext { |
| 33 | struct pt_regs regs; /* needs to be first */ | 29 | struct user_regs_struct regs; /* needs to be first */ |
| 34 | unsigned long oldmask; | 30 | unsigned long oldmask; |
| 35 | unsigned long usp; /* usp before stacking this gunk on it */ | ||
| 36 | }; | 31 | }; |
| 37 | 32 | ||
| 38 | #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ | 33 | #endif /* __ASM_OPENRISC_SIGCONTEXT_H */ |
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 5f759c76834e..95207ab0c99e 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c | |||
| @@ -52,31 +52,25 @@ struct rt_sigframe { | |||
| 52 | static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) | 52 | static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) |
| 53 | { | 53 | { |
| 54 | unsigned int err = 0; | 54 | unsigned int err = 0; |
| 55 | unsigned long old_usp; | ||
| 56 | 55 | ||
| 57 | /* Alwys make any pending restarted system call return -EINTR */ | 56 | /* Alwys make any pending restarted system call return -EINTR */ |
| 58 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 57 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 59 | 58 | ||
| 60 | /* restore the regs from &sc->regs (same as sc, since regs is first) | 59 | /* |
| 60 | * Restore the regs from &sc->regs. | ||
| 61 | * (sc is already checked for VERIFY_READ since the sigframe was | 61 | * (sc is already checked for VERIFY_READ since the sigframe was |
| 62 | * checked in sys_sigreturn previously) | 62 | * checked in sys_sigreturn previously) |
| 63 | */ | 63 | */ |
| 64 | 64 | if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long))) | |
| 65 | if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) | 65 | goto badframe; |
| 66 | if (__copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long))) | ||
| 67 | goto badframe; | ||
| 68 | if (__copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long))) | ||
| 66 | goto badframe; | 69 | goto badframe; |
| 67 | 70 | ||
| 68 | /* make sure the SM-bit is cleared so user-mode cannot fool us */ | 71 | /* make sure the SM-bit is cleared so user-mode cannot fool us */ |
| 69 | regs->sr &= ~SPR_SR_SM; | 72 | regs->sr &= ~SPR_SR_SM; |
| 70 | 73 | ||
| 71 | /* restore the old USP as it was before we stacked the sc etc. | ||
| 72 | * (we cannot just pop the sigcontext since we aligned the sp and | ||
| 73 | * stuff after pushing it) | ||
| 74 | */ | ||
| 75 | |||
| 76 | err |= __get_user(old_usp, &sc->usp); | ||
| 77 | |||
| 78 | regs->sp = old_usp; | ||
| 79 | |||
| 80 | /* TODO: the other ports use regs->orig_XX to disable syscall checks | 74 | /* TODO: the other ports use regs->orig_XX to disable syscall checks |
| 81 | * after this completes, but we don't use that mechanism. maybe we can | 75 | * after this completes, but we don't use that mechanism. maybe we can |
| 82 | * use it now ? | 76 | * use it now ? |
| @@ -137,18 +131,17 @@ static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, | |||
| 137 | unsigned long mask) | 131 | unsigned long mask) |
| 138 | { | 132 | { |
| 139 | int err = 0; | 133 | int err = 0; |
| 140 | unsigned long usp = regs->sp; | ||
| 141 | 134 | ||
| 142 | /* copy the regs. they are first in sc so we can use sc directly */ | 135 | /* copy the regs */ |
| 143 | 136 | ||
| 144 | err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); | 137 | err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); |
| 138 | err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long)); | ||
| 139 | err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long)); | ||
| 145 | 140 | ||
| 146 | /* then some other stuff */ | 141 | /* then some other stuff */ |
| 147 | 142 | ||
| 148 | err |= __put_user(mask, &sc->oldmask); | 143 | err |= __put_user(mask, &sc->oldmask); |
| 149 | 144 | ||
| 150 | err |= __put_user(usp, &sc->usp); | ||
| 151 | |||
| 152 | return err; | 145 | return err; |
| 153 | } | 146 | } |
| 154 | 147 | ||
