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 | /* |