diff options
Diffstat (limited to 'arch/alpha/kernel/signal.c')
-rw-r--r-- | arch/alpha/kernel/signal.c | 69 |
1 files changed, 26 insertions, 43 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 74b05e6ed441..10ab2d74ecbb 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 34 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
35 | 35 | ||
36 | asmlinkage void ret_from_sys_call(void); | 36 | asmlinkage void ret_from_sys_call(void); |
37 | static void do_signal(struct pt_regs *, struct switch_stack *, | ||
38 | unsigned long, unsigned long); | ||
39 | |||
40 | 37 | ||
41 | /* | 38 | /* |
42 | * The OSF/1 sigprocmask calling sequence is different from the | 39 | * The OSF/1 sigprocmask calling sequence is different from the |
@@ -367,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
367 | oldsp = rdusp(); | 364 | oldsp = rdusp(); |
368 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); | 365 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); |
369 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 366 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
370 | goto give_sigsegv; | 367 | return -EFAULT; |
371 | 368 | ||
372 | err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); | 369 | err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); |
373 | if (err) | 370 | if (err) |
374 | goto give_sigsegv; | 371 | return -EFAULT; |
375 | 372 | ||
376 | /* Set up to return from userspace. If provided, use a stub | 373 | /* Set up to return from userspace. If provided, use a stub |
377 | already in userspace. */ | 374 | already in userspace. */ |
@@ -387,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
387 | 384 | ||
388 | /* Check that everything was written properly. */ | 385 | /* Check that everything was written properly. */ |
389 | if (err) | 386 | if (err) |
390 | goto give_sigsegv; | 387 | return err; |
391 | 388 | ||
392 | /* "Return" to the handler */ | 389 | /* "Return" to the handler */ |
393 | regs->r26 = r26; | 390 | regs->r26 = r26; |
@@ -401,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
401 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | 398 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", |
402 | current->comm, current->pid, frame, regs->pc, regs->r26); | 399 | current->comm, current->pid, frame, regs->pc, regs->r26); |
403 | #endif | 400 | #endif |
404 | |||
405 | return 0; | 401 | return 0; |
406 | |||
407 | give_sigsegv: | ||
408 | force_sigsegv(sig, current); | ||
409 | return -EFAULT; | ||
410 | } | 402 | } |
411 | 403 | ||
412 | static int | 404 | static int |
@@ -419,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
419 | oldsp = rdusp(); | 411 | oldsp = rdusp(); |
420 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); | 412 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); |
421 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 413 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
422 | goto give_sigsegv; | 414 | return -EFAULT; |
423 | 415 | ||
424 | err |= copy_siginfo_to_user(&frame->info, info); | 416 | err |= copy_siginfo_to_user(&frame->info, info); |
425 | 417 | ||
@@ -434,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
434 | set->sig[0], oldsp); | 426 | set->sig[0], oldsp); |
435 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 427 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
436 | if (err) | 428 | if (err) |
437 | goto give_sigsegv; | 429 | return -EFAULT; |
438 | 430 | ||
439 | /* Set up to return from userspace. If provided, use a stub | 431 | /* Set up to return from userspace. If provided, use a stub |
440 | already in userspace. */ | 432 | already in userspace. */ |
@@ -450,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
450 | } | 442 | } |
451 | 443 | ||
452 | if (err) | 444 | if (err) |
453 | goto give_sigsegv; | 445 | return -EFAULT; |
454 | 446 | ||
455 | /* "Return" to the handler */ | 447 | /* "Return" to the handler */ |
456 | regs->r26 = r26; | 448 | regs->r26 = r26; |
@@ -466,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
466 | #endif | 458 | #endif |
467 | 459 | ||
468 | return 0; | 460 | return 0; |
469 | |||
470 | give_sigsegv: | ||
471 | force_sigsegv(sig, current); | ||
472 | return -EFAULT; | ||
473 | } | 461 | } |
474 | 462 | ||
475 | 463 | ||
476 | /* | 464 | /* |
477 | * OK, we're invoking a handler. | 465 | * OK, we're invoking a handler. |
478 | */ | 466 | */ |
479 | static inline int | 467 | static inline void |
480 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | 468 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, |
481 | sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) | 469 | struct pt_regs * regs, struct switch_stack *sw) |
482 | { | 470 | { |
471 | sigset_t *oldset = ¤t->blocked; | ||
483 | int ret; | 472 | int ret; |
484 | 473 | ||
474 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
475 | oldset = ¤t->saved_sigmask; | ||
476 | |||
485 | if (ka->sa.sa_flags & SA_SIGINFO) | 477 | if (ka->sa.sa_flags & SA_SIGINFO) |
486 | ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); | 478 | ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); |
487 | else | 479 | else |
488 | ret = setup_frame(sig, ka, oldset, regs, sw); | 480 | ret = setup_frame(sig, ka, oldset, regs, sw); |
489 | 481 | ||
490 | if (ret == 0) | 482 | if (ret) { |
491 | block_sigmask(ka, sig); | 483 | force_sigsegv(sig, current); |
492 | 484 | return; | |
493 | return ret; | 485 | } |
486 | block_sigmask(ka, sig); | ||
487 | /* A signal was successfully delivered, and the | ||
488 | saved sigmask was stored on the signal frame, | ||
489 | and will be restored by sigreturn. So we can | ||
490 | simply clear the restore sigmask flag. */ | ||
491 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
494 | } | 492 | } |
495 | 493 | ||
496 | static inline void | 494 | static inline void |
@@ -538,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
538 | int signr; | 536 | int signr; |
539 | unsigned long single_stepping = ptrace_cancel_bpt(current); | 537 | unsigned long single_stepping = ptrace_cancel_bpt(current); |
540 | struct k_sigaction ka; | 538 | struct k_sigaction ka; |
541 | sigset_t *oldset; | ||
542 | |||
543 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
544 | oldset = ¤t->saved_sigmask; | ||
545 | else | ||
546 | oldset = ¤t->blocked; | ||
547 | 539 | ||
548 | /* This lets the debugger run, ... */ | 540 | /* This lets the debugger run, ... */ |
549 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 541 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
@@ -555,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
555 | /* Whee! Actually deliver the signal. */ | 547 | /* Whee! Actually deliver the signal. */ |
556 | if (r0) | 548 | if (r0) |
557 | syscall_restart(r0, r19, regs, &ka); | 549 | syscall_restart(r0, r19, regs, &ka); |
558 | if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { | 550 | handle_signal(signr, &ka, &info, regs, sw); |
559 | /* A signal was successfully delivered, and the | ||
560 | saved sigmask was stored on the signal frame, | ||
561 | and will be restored by sigreturn. So we can | ||
562 | simply clear the restore sigmask flag. */ | ||
563 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
564 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
565 | } | ||
566 | if (single_stepping) | 551 | if (single_stepping) |
567 | ptrace_set_bpt(current); /* re-set bpt */ | 552 | ptrace_set_bpt(current); /* re-set bpt */ |
568 | return; | 553 | return; |
@@ -587,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
587 | } | 572 | } |
588 | 573 | ||
589 | /* If there's no signal to deliver, we just restore the saved mask. */ | 574 | /* If there's no signal to deliver, we just restore the saved mask. */ |
590 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 575 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) |
591 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 576 | set_current_blocked(¤t->saved_sigmask); |
592 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
593 | } | ||
594 | 577 | ||
595 | if (single_stepping) | 578 | if (single_stepping) |
596 | ptrace_set_bpt(current); /* re-set breakpoint */ | 579 | ptrace_set_bpt(current); /* re-set breakpoint */ |
@@ -601,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, | |||
601 | unsigned long thread_info_flags, | 584 | unsigned long thread_info_flags, |
602 | unsigned long r0, unsigned long r19) | 585 | unsigned long r0, unsigned long r19) |
603 | { | 586 | { |
604 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 587 | if (thread_info_flags & _TIF_SIGPENDING) |
605 | do_signal(regs, sw, r0, r19); | 588 | do_signal(regs, sw, r0, r19); |
606 | 589 | ||
607 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |