diff options
Diffstat (limited to 'arch/sh/kernel/signal_32.c')
-rw-r--r-- | arch/sh/kernel/signal_32.c | 79 |
1 files changed, 32 insertions, 47 deletions
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 594cd371aa28..2f002b24fb92 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | |||
262 | extern void __kernel_sigreturn(void); | 262 | extern void __kernel_sigreturn(void); |
263 | extern void __kernel_rt_sigreturn(void); | 263 | extern void __kernel_rt_sigreturn(void); |
264 | 264 | ||
265 | static int setup_frame(int sig, struct k_sigaction *ka, | 265 | static int setup_frame(struct ksignal *ksig, sigset_t *set, |
266 | sigset_t *set, struct pt_regs *regs) | 266 | struct pt_regs *regs) |
267 | { | 267 | { |
268 | struct sigframe __user *frame; | 268 | struct sigframe __user *frame; |
269 | int err = 0; | 269 | int err = 0, sig = ksig->sig; |
270 | int signal; | 270 | int signal; |
271 | 271 | ||
272 | frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); | 272 | frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame)); |
273 | 273 | ||
274 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 274 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
275 | goto give_sigsegv; | 275 | return -EFAULT; |
276 | 276 | ||
277 | signal = current_thread_info()->exec_domain | 277 | signal = current_thread_info()->exec_domain |
278 | && current_thread_info()->exec_domain->signal_invmap | 278 | && current_thread_info()->exec_domain->signal_invmap |
@@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
288 | 288 | ||
289 | /* Set up to return from userspace. If provided, use a stub | 289 | /* Set up to return from userspace. If provided, use a stub |
290 | already in userspace. */ | 290 | already in userspace. */ |
291 | if (ka->sa.sa_flags & SA_RESTORER) { | 291 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
292 | regs->pr = (unsigned long) ka->sa.sa_restorer; | 292 | regs->pr = (unsigned long) ksig->ka.sa.sa_restorer; |
293 | #ifdef CONFIG_VSYSCALL | 293 | #ifdef CONFIG_VSYSCALL |
294 | } else if (likely(current->mm->context.vdso)) { | 294 | } else if (likely(current->mm->context.vdso)) { |
295 | regs->pr = VDSO_SYM(&__kernel_sigreturn); | 295 | regs->pr = VDSO_SYM(&__kernel_sigreturn); |
@@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
309 | } | 309 | } |
310 | 310 | ||
311 | if (err) | 311 | if (err) |
312 | goto give_sigsegv; | 312 | return -EFAULT; |
313 | 313 | ||
314 | /* Set up registers for signal handler */ | 314 | /* Set up registers for signal handler */ |
315 | regs->regs[15] = (unsigned long) frame; | 315 | regs->regs[15] = (unsigned long) frame; |
@@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
319 | 319 | ||
320 | if (current->personality & FDPIC_FUNCPTRS) { | 320 | if (current->personality & FDPIC_FUNCPTRS) { |
321 | struct fdpic_func_descriptor __user *funcptr = | 321 | struct fdpic_func_descriptor __user *funcptr = |
322 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; | 322 | (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler; |
323 | 323 | ||
324 | err |= __get_user(regs->pc, &funcptr->text); | 324 | err |= __get_user(regs->pc, &funcptr->text); |
325 | err |= __get_user(regs->regs[12], &funcptr->GOT); | 325 | err |= __get_user(regs->regs[12], &funcptr->GOT); |
326 | } else | 326 | } else |
327 | regs->pc = (unsigned long)ka->sa.sa_handler; | 327 | regs->pc = (unsigned long)ksig->ka.sa.sa_handler; |
328 | 328 | ||
329 | if (err) | 329 | if (err) |
330 | goto give_sigsegv; | 330 | return -EFAULT; |
331 | 331 | ||
332 | set_fs(USER_DS); | 332 | set_fs(USER_DS); |
333 | 333 | ||
@@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
335 | current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); | 335 | current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); |
336 | 336 | ||
337 | return 0; | 337 | return 0; |
338 | |||
339 | give_sigsegv: | ||
340 | force_sigsegv(sig, current); | ||
341 | return -EFAULT; | ||
342 | } | 338 | } |
343 | 339 | ||
344 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 340 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, |
345 | sigset_t *set, struct pt_regs *regs) | 341 | struct pt_regs *regs) |
346 | { | 342 | { |
347 | struct rt_sigframe __user *frame; | 343 | struct rt_sigframe __user *frame; |
348 | int err = 0; | 344 | int err = 0, sig = ksig->sig; |
349 | int signal; | 345 | int signal; |
350 | 346 | ||
351 | frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); | 347 | frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame)); |
352 | 348 | ||
353 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 349 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
354 | goto give_sigsegv; | 350 | return -EFAULT; |
355 | 351 | ||
356 | signal = current_thread_info()->exec_domain | 352 | signal = current_thread_info()->exec_domain |
357 | && current_thread_info()->exec_domain->signal_invmap | 353 | && current_thread_info()->exec_domain->signal_invmap |
@@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
359 | ? current_thread_info()->exec_domain->signal_invmap[sig] | 355 | ? current_thread_info()->exec_domain->signal_invmap[sig] |
360 | : sig; | 356 | : sig; |
361 | 357 | ||
362 | err |= copy_siginfo_to_user(&frame->info, info); | 358 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
363 | 359 | ||
364 | /* Create the ucontext. */ | 360 | /* Create the ucontext. */ |
365 | err |= __put_user(0, &frame->uc.uc_flags); | 361 | err |= __put_user(0, &frame->uc.uc_flags); |
@@ -371,8 +367,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
371 | 367 | ||
372 | /* Set up to return from userspace. If provided, use a stub | 368 | /* Set up to return from userspace. If provided, use a stub |
373 | already in userspace. */ | 369 | already in userspace. */ |
374 | if (ka->sa.sa_flags & SA_RESTORER) { | 370 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
375 | regs->pr = (unsigned long) ka->sa.sa_restorer; | 371 | regs->pr = (unsigned long) ksig->ka.sa.sa_restorer; |
376 | #ifdef CONFIG_VSYSCALL | 372 | #ifdef CONFIG_VSYSCALL |
377 | } else if (likely(current->mm->context.vdso)) { | 373 | } else if (likely(current->mm->context.vdso)) { |
378 | regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); | 374 | regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); |
@@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
392 | } | 388 | } |
393 | 389 | ||
394 | if (err) | 390 | if (err) |
395 | goto give_sigsegv; | 391 | return -EFAULT; |
396 | 392 | ||
397 | /* Set up registers for signal handler */ | 393 | /* Set up registers for signal handler */ |
398 | regs->regs[15] = (unsigned long) frame; | 394 | regs->regs[15] = (unsigned long) frame; |
@@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
402 | 398 | ||
403 | if (current->personality & FDPIC_FUNCPTRS) { | 399 | if (current->personality & FDPIC_FUNCPTRS) { |
404 | struct fdpic_func_descriptor __user *funcptr = | 400 | struct fdpic_func_descriptor __user *funcptr = |
405 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; | 401 | (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler; |
406 | 402 | ||
407 | err |= __get_user(regs->pc, &funcptr->text); | 403 | err |= __get_user(regs->pc, &funcptr->text); |
408 | err |= __get_user(regs->regs[12], &funcptr->GOT); | 404 | err |= __get_user(regs->regs[12], &funcptr->GOT); |
409 | } else | 405 | } else |
410 | regs->pc = (unsigned long)ka->sa.sa_handler; | 406 | regs->pc = (unsigned long)ksig->ka.sa.sa_handler; |
411 | 407 | ||
412 | if (err) | 408 | if (err) |
413 | goto give_sigsegv; | 409 | return -EFAULT; |
414 | 410 | ||
415 | set_fs(USER_DS); | 411 | set_fs(USER_DS); |
416 | 412 | ||
@@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
418 | current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); | 414 | current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); |
419 | 415 | ||
420 | return 0; | 416 | return 0; |
421 | |||
422 | give_sigsegv: | ||
423 | force_sigsegv(sig, current); | ||
424 | return -EFAULT; | ||
425 | } | 417 | } |
426 | 418 | ||
427 | static inline void | 419 | static inline void |
@@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, | |||
455 | * OK, we're invoking a handler | 447 | * OK, we're invoking a handler |
456 | */ | 448 | */ |
457 | static void | 449 | static void |
458 | handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | 450 | handle_signal(struct ksignal *ksig, struct pt_regs *regs, unsigned int save_r0) |
459 | struct pt_regs *regs, unsigned int save_r0) | ||
460 | { | 451 | { |
461 | sigset_t *oldset = sigmask_to_save(); | 452 | sigset_t *oldset = sigmask_to_save(); |
462 | int ret; | 453 | int ret; |
463 | 454 | ||
464 | /* Set up the stack frame */ | 455 | /* Set up the stack frame */ |
465 | if (ka->sa.sa_flags & SA_SIGINFO) | 456 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
466 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 457 | ret = setup_rt_frame(ksig, oldset, regs); |
467 | else | 458 | else |
468 | ret = setup_frame(sig, ka, oldset, regs); | 459 | ret = setup_frame(ksig, oldset, regs); |
469 | 460 | ||
470 | if (ret) | 461 | signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); |
471 | return; | ||
472 | signal_delivered(sig, info, ka, regs, | ||
473 | test_thread_flag(TIF_SINGLESTEP)); | ||
474 | } | 462 | } |
475 | 463 | ||
476 | /* | 464 | /* |
@@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
484 | */ | 472 | */ |
485 | static void do_signal(struct pt_regs *regs, unsigned int save_r0) | 473 | static void do_signal(struct pt_regs *regs, unsigned int save_r0) |
486 | { | 474 | { |
487 | siginfo_t info; | 475 | struct ksignal ksig; |
488 | int signr; | ||
489 | struct k_sigaction ka; | ||
490 | 476 | ||
491 | /* | 477 | /* |
492 | * We want the common case to go fast, which | 478 | * We want the common case to go fast, which |
@@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
497 | if (!user_mode(regs)) | 483 | if (!user_mode(regs)) |
498 | return; | 484 | return; |
499 | 485 | ||
500 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 486 | if (get_signal(&ksig)) { |
501 | if (signr > 0) { | 487 | handle_syscall_restart(save_r0, regs, &ksig.ka.sa); |
502 | handle_syscall_restart(save_r0, regs, &ka.sa); | ||
503 | 488 | ||
504 | /* Whee! Actually deliver the signal. */ | 489 | /* Whee! Actually deliver the signal. */ |
505 | handle_signal(signr, &ka, &info, regs, save_r0); | 490 | handle_signal(&ksig, regs, save_r0); |
506 | return; | 491 | return; |
507 | } | 492 | } |
508 | 493 | ||