diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 14:53:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 14:53:44 -0400 |
commit | 86c47b70f62a7072d441ba212aab33c2f82627c2 (patch) | |
tree | d03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/arm | |
parent | 1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff) | |
parent | 44fbbb3dc687c9709a6f2236197316e5c79ab1eb (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of signal handling patches from Al Viro:
"This time it's mostly helpers and conversions to them; there's a lot
of stuff remaining in the tree, but that'll either go in -rc2
(isolated bug fixes, ideally via arch maintainers' trees) or will sit
there until the next cycle."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal:
x86: get rid of calling do_notify_resume() when returning to kernel mode
blackfin: check __get_user() return value
whack-a-mole with TIF_FREEZE
FRV: Optimise the system call exit path in entry.S [ver #2]
FRV: Shrink TIF_WORK_MASK [ver #2]
FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions
new helper: signal_delivered()
powerpc: get rid of restore_sigmask()
most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set
set_restore_sigmask() is never called without SIGPENDING (and never should be)
TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set
don't call try_to_freeze() from do_signal()
pull clearing RESTORE_SIGMASK into block_sigmask()
sh64: failure to build sigframe != signal without handler
openrisc: tracehook_signal_handler() is supposed to be called on success
new helper: sigmask_to_save()
new helper: restore_saved_sigmask()
new helpers: {clear,test,test_and_clear}_restore_sigmask()
HAVE_RESTORE_SIGMASK is defined on all architectures now
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/kernel/signal.c | 47 |
1 files changed, 8 insertions, 39 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 63f327dd5198..fd2392a17ac1 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -22,8 +22,6 @@ | |||
22 | 22 | ||
23 | #include "signal.h" | 23 | #include "signal.h" |
24 | 24 | ||
25 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
26 | |||
27 | /* | 25 | /* |
28 | * For ARM syscalls, we encode the syscall number into the instruction. | 26 | * For ARM syscalls, we encode the syscall number into the instruction. |
29 | */ | 27 | */ |
@@ -210,10 +208,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) | |||
210 | int err; | 208 | int err; |
211 | 209 | ||
212 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); | 210 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); |
213 | if (err == 0) { | 211 | if (err == 0) |
214 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
215 | set_current_blocked(&set); | 212 | set_current_blocked(&set); |
216 | } | ||
217 | 213 | ||
218 | __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); | 214 | __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); |
219 | __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); | 215 | __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); |
@@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | |||
528 | /* | 524 | /* |
529 | * OK, we're invoking a handler | 525 | * OK, we're invoking a handler |
530 | */ | 526 | */ |
531 | static int | 527 | static void |
532 | handle_signal(unsigned long sig, struct k_sigaction *ka, | 528 | handle_signal(unsigned long sig, struct k_sigaction *ka, |
533 | siginfo_t *info, sigset_t *oldset, | 529 | siginfo_t *info, struct pt_regs *regs) |
534 | struct pt_regs * regs) | ||
535 | { | 530 | { |
536 | struct thread_info *thread = current_thread_info(); | 531 | struct thread_info *thread = current_thread_info(); |
537 | struct task_struct *tsk = current; | 532 | struct task_struct *tsk = current; |
533 | sigset_t *oldset = sigmask_to_save(); | ||
538 | int usig = sig; | 534 | int usig = sig; |
539 | int ret; | 535 | int ret; |
540 | 536 | ||
@@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
559 | 555 | ||
560 | if (ret != 0) { | 556 | if (ret != 0) { |
561 | force_sigsegv(sig, tsk); | 557 | force_sigsegv(sig, tsk); |
562 | return ret; | 558 | return; |
563 | } | 559 | } |
564 | 560 | signal_delivered(sig, info, ka, regs, 0); | |
565 | /* | ||
566 | * Block the signal if we were successful. | ||
567 | */ | ||
568 | block_sigmask(ka, sig); | ||
569 | |||
570 | tracehook_signal_handler(sig, info, ka, regs, 0); | ||
571 | |||
572 | return 0; | ||
573 | } | 561 | } |
574 | 562 | ||
575 | /* | 563 | /* |
@@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
617 | */ | 605 | */ |
618 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 606 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
619 | if (signr > 0) { | 607 | if (signr > 0) { |
620 | sigset_t *oldset; | ||
621 | |||
622 | /* | 608 | /* |
623 | * Depending on the signal settings we may need to revert the | 609 | * Depending on the signal settings we may need to revert the |
624 | * decision to restart the system call. But skip this if a | 610 | * decision to restart the system call. But skip this if a |
@@ -635,20 +621,7 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
635 | clear_thread_flag(TIF_SYSCALL_RESTARTSYS); | 621 | clear_thread_flag(TIF_SYSCALL_RESTARTSYS); |
636 | } | 622 | } |
637 | 623 | ||
638 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 624 | handle_signal(signr, &ka, &info, regs); |
639 | oldset = ¤t->saved_sigmask; | ||
640 | else | ||
641 | oldset = ¤t->blocked; | ||
642 | if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { | ||
643 | /* | ||
644 | * A signal was successfully delivered; the saved | ||
645 | * sigmask will have been stored in the signal frame, | ||
646 | * and will be restored by sigreturn, so we can simply | ||
647 | * clear the TIF_RESTORE_SIGMASK flag. | ||
648 | */ | ||
649 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
650 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
651 | } | ||
652 | return; | 625 | return; |
653 | } | 626 | } |
654 | 627 | ||
@@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
663 | set_thread_flag(TIF_SYSCALL_RESTARTSYS); | 636 | set_thread_flag(TIF_SYSCALL_RESTARTSYS); |
664 | } | 637 | } |
665 | 638 | ||
666 | /* If there's no signal to deliver, we just put the saved sigmask | 639 | restore_saved_sigmask(); |
667 | * back. | ||
668 | */ | ||
669 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
670 | set_current_blocked(¤t->saved_sigmask); | ||
671 | } | 640 | } |
672 | 641 | ||
673 | asmlinkage void | 642 | asmlinkage void |