diff options
| -rw-r--r-- | arch/blackfin/kernel/signal.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index 35459e681483..6682b73a8523 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
| @@ -187,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
| 187 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 187 | err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
| 188 | 188 | ||
| 189 | if (err) | 189 | if (err) |
| 190 | goto give_sigsegv; | 190 | return -EFAULT; |
| 191 | 191 | ||
| 192 | /* Set up registers for signal handler */ | 192 | /* Set up registers for signal handler */ |
| 193 | wrusp((unsigned long)frame); | ||
| 194 | if (current->personality & FDPIC_FUNCPTRS) { | 193 | if (current->personality & FDPIC_FUNCPTRS) { |
| 195 | struct fdpic_func_descriptor __user *funcptr = | 194 | struct fdpic_func_descriptor __user *funcptr = |
| 196 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; | 195 | (struct fdpic_func_descriptor *) ka->sa.sa_handler; |
| 197 | __get_user(regs->pc, &funcptr->text); | 196 | u32 pc, p3; |
| 198 | __get_user(regs->p3, &funcptr->GOT); | 197 | err |= __get_user(pc, &funcptr->text); |
| 198 | err |= __get_user(p3, &funcptr->GOT); | ||
| 199 | if (err) | ||
| 200 | return -EFAULT; | ||
| 201 | regs->pc = pc; | ||
| 202 | regs->p3 = p3; | ||
| 199 | } else | 203 | } else |
| 200 | regs->pc = (unsigned long)ka->sa.sa_handler; | 204 | regs->pc = (unsigned long)ka->sa.sa_handler; |
| 205 | wrusp((unsigned long)frame); | ||
| 201 | regs->rets = SIGRETURN_STUB; | 206 | regs->rets = SIGRETURN_STUB; |
| 202 | 207 | ||
| 203 | regs->r0 = frame->sig; | 208 | regs->r0 = frame->sig; |
| @@ -205,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
| 205 | regs->r2 = (unsigned long)(&frame->uc); | 210 | regs->r2 = (unsigned long)(&frame->uc); |
| 206 | 211 | ||
| 207 | return 0; | 212 | return 0; |
| 208 | |||
| 209 | give_sigsegv: | ||
| 210 | force_sigsegv(sig, current); | ||
| 211 | return -EFAULT; | ||
| 212 | } | 213 | } |
| 213 | 214 | ||
| 214 | static inline void | 215 | static inline void |
| @@ -248,20 +249,17 @@ static void | |||
| 248 | handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, | 249 | handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, |
| 249 | struct pt_regs *regs) | 250 | struct pt_regs *regs) |
| 250 | { | 251 | { |
| 251 | int ret; | ||
| 252 | |||
| 253 | /* are we from a system call? to see pt_regs->orig_p0 */ | 252 | /* are we from a system call? to see pt_regs->orig_p0 */ |
| 254 | if (regs->orig_p0 >= 0) | 253 | if (regs->orig_p0 >= 0) |
| 255 | /* If so, check system call restarting.. */ | 254 | /* If so, check system call restarting.. */ |
| 256 | handle_restart(regs, ka, 1); | 255 | handle_restart(regs, ka, 1); |
| 257 | 256 | ||
| 258 | /* set up the stack frame */ | 257 | /* set up the stack frame */ |
| 259 | ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); | 258 | if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) |
| 260 | if (ret) | 259 | force_sigsegv(sig, current); |
| 261 | return; | 260 | else |
| 262 | 261 | signal_delivered(sig, info, ka, regs, | |
| 263 | signal_delivered(sig, info, ka, regs, | 262 | test_thread_flag(TIF_SINGLESTEP)); |
| 264 | test_thread_flag(TIF_SINGLESTEP)); | ||
| 265 | } | 263 | } |
| 266 | 264 | ||
| 267 | /* | 265 | /* |
