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/parisc | |
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/parisc')
-rw-r--r-- | arch/parisc/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/signal.c | 47 | ||||
-rw-r--r-- | arch/parisc/kernel/signal32.c | 2 |
4 files changed, 14 insertions, 41 deletions
diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 83ae7dd4d99e..22b4726dee49 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h | |||
@@ -74,7 +74,7 @@ struct thread_info { | |||
74 | #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) | 74 | #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) |
75 | 75 | ||
76 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ | 76 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ |
77 | _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) | 77 | _TIF_NEED_RESCHED) |
78 | 78 | ||
79 | #endif /* __KERNEL__ */ | 79 | #endif /* __KERNEL__ */ |
80 | 80 | ||
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index c7fbc96472f3..18670a078849 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -924,7 +924,7 @@ intr_check_sig: | |||
924 | /* As above */ | 924 | /* As above */ |
925 | mfctl %cr30,%r1 | 925 | mfctl %cr30,%r1 |
926 | LDREG TI_FLAGS(%r1),%r19 | 926 | LDREG TI_FLAGS(%r1),%r19 |
927 | ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r20 | 927 | ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r20 |
928 | and,COND(<>) %r19, %r20, %r0 | 928 | and,COND(<>) %r19, %r20, %r0 |
929 | b,n intr_restore /* skip past if we've nothing to do */ | 929 | b,n intr_restore /* skip past if we've nothing to do */ |
930 | 930 | ||
@@ -2032,7 +2032,7 @@ syscall_check_resched: | |||
2032 | .import do_signal,code | 2032 | .import do_signal,code |
2033 | syscall_check_sig: | 2033 | syscall_check_sig: |
2034 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 | 2034 | LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 |
2035 | ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r26 | 2035 | ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r26 |
2036 | and,COND(<>) %r19, %r26, %r0 | 2036 | and,COND(<>) %r19, %r26, %r0 |
2037 | b,n syscall_restore /* skip past if we've nothing to do */ | 2037 | b,n syscall_restore /* skip past if we've nothing to do */ |
2038 | 2038 | ||
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index e7a7cd3e1120..594459bde14e 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -48,9 +48,6 @@ | |||
48 | #define DBG(LEVEL, ...) | 48 | #define DBG(LEVEL, ...) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | |||
52 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
53 | |||
54 | /* gcc will complain if a pointer is cast to an integer of different | 51 | /* gcc will complain if a pointer is cast to an integer of different |
55 | * size. If you really need to do this (and we do for an ELF32 user | 52 | * size. If you really need to do this (and we do for an ELF32 user |
56 | * application in an ELF64 kernel) then you have to do a cast to an | 53 | * application in an ELF64 kernel) then you have to do a cast to an |
@@ -131,7 +128,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
131 | goto give_sigsegv; | 128 | goto give_sigsegv; |
132 | } | 129 | } |
133 | 130 | ||
134 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
135 | set_current_blocked(&set); | 131 | set_current_blocked(&set); |
136 | 132 | ||
137 | /* Good thing we saved the old gr[30], eh? */ | 133 | /* Good thing we saved the old gr[30], eh? */ |
@@ -443,8 +439,9 @@ give_sigsegv: | |||
443 | 439 | ||
444 | static long | 440 | static long |
445 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 441 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
446 | sigset_t *oldset, struct pt_regs *regs, int in_syscall) | 442 | struct pt_regs *regs, int in_syscall) |
447 | { | 443 | { |
444 | sigset_t *oldset = sigmask_to_save(); | ||
448 | DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", | 445 | DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", |
449 | sig, ka, info, oldset, regs); | 446 | sig, ka, info, oldset, regs); |
450 | 447 | ||
@@ -452,12 +449,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
452 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) | 449 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) |
453 | return 0; | 450 | return 0; |
454 | 451 | ||
455 | block_sigmask(ka, sig); | 452 | signal_delivered(sig, info, ka, regs, |
456 | |||
457 | tracehook_signal_handler(sig, info, ka, regs, | ||
458 | test_thread_flag(TIF_SINGLESTEP) || | 453 | test_thread_flag(TIF_SINGLESTEP) || |
459 | test_thread_flag(TIF_BLOCKSTEP)); | 454 | test_thread_flag(TIF_BLOCKSTEP)); |
460 | 455 | ||
456 | DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", | ||
457 | regs->gr[28]); | ||
458 | |||
461 | return 1; | 459 | return 1; |
462 | } | 460 | } |
463 | 461 | ||
@@ -568,28 +566,17 @@ do_signal(struct pt_regs *regs, long in_syscall) | |||
568 | siginfo_t info; | 566 | siginfo_t info; |
569 | struct k_sigaction ka; | 567 | struct k_sigaction ka; |
570 | int signr; | 568 | int signr; |
571 | sigset_t *oldset; | ||
572 | 569 | ||
573 | DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", | 570 | DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", |
574 | oldset, regs, regs->sr[7], in_syscall); | 571 | regs, regs->sr[7], in_syscall); |
575 | 572 | ||
576 | /* Everyone else checks to see if they are in kernel mode at | 573 | /* Everyone else checks to see if they are in kernel mode at |
577 | this point and exits if that's the case. I'm not sure why | 574 | this point and exits if that's the case. I'm not sure why |
578 | we would be called in that case, but for some reason we | 575 | we would be called in that case, but for some reason we |
579 | are. */ | 576 | are. */ |
580 | 577 | ||
581 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
582 | oldset = ¤t->saved_sigmask; | ||
583 | else | ||
584 | oldset = ¤t->blocked; | ||
585 | |||
586 | DBG(1,"do_signal: oldset %08lx / %08lx\n", | ||
587 | oldset->sig[0], oldset->sig[1]); | ||
588 | |||
589 | |||
590 | /* May need to force signal if handle_signal failed to deliver */ | 578 | /* May need to force signal if handle_signal failed to deliver */ |
591 | while (1) { | 579 | while (1) { |
592 | |||
593 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 580 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
594 | DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); | 581 | DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); |
595 | 582 | ||
@@ -603,14 +590,8 @@ do_signal(struct pt_regs *regs, long in_syscall) | |||
603 | /* Whee! Actually deliver the signal. If the | 590 | /* Whee! Actually deliver the signal. If the |
604 | delivery failed, we need to continue to iterate in | 591 | delivery failed, we need to continue to iterate in |
605 | this loop so we can deliver the SIGSEGV... */ | 592 | this loop so we can deliver the SIGSEGV... */ |
606 | if (handle_signal(signr, &info, &ka, oldset, | 593 | if (handle_signal(signr, &info, &ka, regs, in_syscall)) |
607 | regs, in_syscall)) { | ||
608 | DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", | ||
609 | regs->gr[28]); | ||
610 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
611 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
612 | return; | 594 | return; |
613 | } | ||
614 | } | 595 | } |
615 | /* end of while(1) looping forever if we can't force a signal */ | 596 | /* end of while(1) looping forever if we can't force a signal */ |
616 | 597 | ||
@@ -621,18 +602,12 @@ do_signal(struct pt_regs *regs, long in_syscall) | |||
621 | DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", | 602 | DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", |
622 | regs->gr[28]); | 603 | regs->gr[28]); |
623 | 604 | ||
624 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 605 | restore_saved_sigmask(); |
625 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
626 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
627 | } | ||
628 | |||
629 | return; | ||
630 | } | 606 | } |
631 | 607 | ||
632 | void do_notify_resume(struct pt_regs *regs, long in_syscall) | 608 | void do_notify_resume(struct pt_regs *regs, long in_syscall) |
633 | { | 609 | { |
634 | if (test_thread_flag(TIF_SIGPENDING) || | 610 | if (test_thread_flag(TIF_SIGPENDING)) |
635 | test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
636 | do_signal(regs, in_syscall); | 611 | do_signal(regs, in_syscall); |
637 | 612 | ||
638 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | 613 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { |
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index e14132430762..fd49aeda9eb8 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c | |||
@@ -47,8 +47,6 @@ | |||
47 | #define DBG(LEVEL, ...) | 47 | #define DBG(LEVEL, ...) |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
51 | |||
52 | inline void | 50 | inline void |
53 | sigset_32to64(sigset_t *s64, compat_sigset_t *s32) | 51 | sigset_32to64(sigset_t *s64, compat_sigset_t *s32) |
54 | { | 52 | { |