aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
commit86c47b70f62a7072d441ba212aab33c2f82627c2 (patch)
treed03988bd2226966352bb7f3c2e82ff545353d2c4 /kernel
parent1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff)
parent44fbbb3dc687c9709a6f2236197316e5c79ab1eb (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 'kernel')
-rw-r--r--kernel/signal.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 08dfbd748cd2..677102789cf2 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2368,24 +2368,34 @@ relock:
2368} 2368}
2369 2369
2370/** 2370/**
2371 * block_sigmask - add @ka's signal mask to current->blocked 2371 * signal_delivered -
2372 * @ka: action for @signr 2372 * @sig: number of signal being delivered
2373 * @signr: signal that has been successfully delivered 2373 * @info: siginfo_t of signal being delivered
2374 * @ka: sigaction setting that chose the handler
2375 * @regs: user register state
2376 * @stepping: nonzero if debugger single-step or block-step in use
2374 * 2377 *
2375 * This function should be called when a signal has succesfully been 2378 * This function should be called when a signal has succesfully been
2376 * delivered. It adds the mask of signals for @ka to current->blocked 2379 * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
2377 * so that they are blocked during the execution of the signal 2380 * is always blocked, and the signal itself is blocked unless %SA_NODEFER
2378 * handler. In addition, @signr will be blocked unless %SA_NODEFER is 2381 * is set in @ka->sa.sa_flags. Tracing is notified.
2379 * set in @ka->sa.sa_flags.
2380 */ 2382 */
2381void block_sigmask(struct k_sigaction *ka, int signr) 2383void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
2384 struct pt_regs *regs, int stepping)
2382{ 2385{
2383 sigset_t blocked; 2386 sigset_t blocked;
2384 2387
2388 /* A signal was successfully delivered, and the
2389 saved sigmask was stored on the signal frame,
2390 and will be restored by sigreturn. So we can
2391 simply clear the restore sigmask flag. */
2392 clear_restore_sigmask();
2393
2385 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask); 2394 sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
2386 if (!(ka->sa.sa_flags & SA_NODEFER)) 2395 if (!(ka->sa.sa_flags & SA_NODEFER))
2387 sigaddset(&blocked, signr); 2396 sigaddset(&blocked, sig);
2388 set_current_blocked(&blocked); 2397 set_current_blocked(&blocked);
2398 tracehook_signal_handler(sig, info, ka, regs, stepping);
2389} 2399}
2390 2400
2391/* 2401/*
@@ -2518,7 +2528,16 @@ static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset)
2518 * It is wrong to change ->blocked directly, this helper should be used 2528 * It is wrong to change ->blocked directly, this helper should be used
2519 * to ensure the process can't miss a shared signal we are going to block. 2529 * to ensure the process can't miss a shared signal we are going to block.
2520 */ 2530 */
2521void set_current_blocked(const sigset_t *newset) 2531void set_current_blocked(sigset_t *newset)
2532{
2533 struct task_struct *tsk = current;
2534 sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP));
2535 spin_lock_irq(&tsk->sighand->siglock);
2536 __set_task_blocked(tsk, newset);
2537 spin_unlock_irq(&tsk->sighand->siglock);
2538}
2539
2540void __set_current_blocked(const sigset_t *newset)
2522{ 2541{
2523 struct task_struct *tsk = current; 2542 struct task_struct *tsk = current;
2524 2543
@@ -2558,7 +2577,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
2558 return -EINVAL; 2577 return -EINVAL;
2559 } 2578 }
2560 2579
2561 set_current_blocked(&newset); 2580 __set_current_blocked(&newset);
2562 return 0; 2581 return 0;
2563} 2582}
2564 2583
@@ -3132,7 +3151,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
3132 return -EINVAL; 3151 return -EINVAL;
3133 } 3152 }
3134 3153
3135 set_current_blocked(&new_blocked); 3154 __set_current_blocked(&new_blocked);
3136 } 3155 }
3137 3156
3138 if (oset) { 3157 if (oset) {
@@ -3196,7 +3215,6 @@ SYSCALL_DEFINE1(ssetmask, int, newmask)
3196 int old = current->blocked.sig[0]; 3215 int old = current->blocked.sig[0];
3197 sigset_t newset; 3216 sigset_t newset;
3198 3217
3199 siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP)));
3200 set_current_blocked(&newset); 3218 set_current_blocked(&newset);
3201 3219
3202 return old; 3220 return old;
@@ -3235,11 +3253,8 @@ SYSCALL_DEFINE0(pause)
3235 3253
3236#endif 3254#endif
3237 3255
3238#ifdef HAVE_SET_RESTORE_SIGMASK
3239int sigsuspend(sigset_t *set) 3256int sigsuspend(sigset_t *set)
3240{ 3257{
3241 sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
3242
3243 current->saved_sigmask = current->blocked; 3258 current->saved_sigmask = current->blocked;
3244 set_current_blocked(set); 3259 set_current_blocked(set);
3245 3260
@@ -3248,7 +3263,6 @@ int sigsuspend(sigset_t *set)
3248 set_restore_sigmask(); 3263 set_restore_sigmask();
3249 return -ERESTARTNOHAND; 3264 return -ERESTARTNOHAND;
3250} 3265}
3251#endif
3252 3266
3253#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND 3267#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
3254/** 3268/**