aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2011-04-27 15:18:10 -0400
committerOleg Nesterov <oleg@redhat.com>2011-04-28 07:01:38 -0400
commitbb7efee2ca63b08795ffb3cda96fc89d2e641b79 (patch)
tree05e05d78f815d9fb8f8963860d2287189a17d7b1 /kernel/signal.c
parente9bd3f0faa90084f188830d77723bafe422e486b (diff)
signal: cleanup sys_rt_sigprocmask()
sys_rt_sigprocmask() looks unnecessarily complicated, simplify it. We can just read current->blocked lockless unconditionally before anything else and then copy-to-user it if needed. At worst we copy 4 words on mips. We could copy-to-user the old mask first and simplify the code even more, but the patch tries to keep the current behaviour: we change current->block even if copy_to_user(oset) fails. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Matt Fleming <matt.fleming@linux.intel.com> Acked-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c38
1 files changed, 16 insertions, 22 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 8aa3a2e226af..bb9200070ea0 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2364,40 +2364,34 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
2364 * @oset: previous value of signal mask if non-null 2364 * @oset: previous value of signal mask if non-null
2365 * @sigsetsize: size of sigset_t type 2365 * @sigsetsize: size of sigset_t type
2366 */ 2366 */
2367SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, set, 2367SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset,
2368 sigset_t __user *, oset, size_t, sigsetsize) 2368 sigset_t __user *, oset, size_t, sigsetsize)
2369{ 2369{
2370 int error = -EINVAL;
2371 sigset_t old_set, new_set; 2370 sigset_t old_set, new_set;
2371 int error;
2372 2372
2373 /* XXX: Don't preclude handling different sized sigset_t's. */ 2373 /* XXX: Don't preclude handling different sized sigset_t's. */
2374 if (sigsetsize != sizeof(sigset_t)) 2374 if (sigsetsize != sizeof(sigset_t))
2375 goto out; 2375 return -EINVAL;
2376 2376
2377 if (set) { 2377 old_set = current->blocked;
2378 error = -EFAULT; 2378
2379 if (copy_from_user(&new_set, set, sizeof(*set))) 2379 if (nset) {
2380 goto out; 2380 if (copy_from_user(&new_set, nset, sizeof(sigset_t)))
2381 return -EFAULT;
2381 sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); 2382 sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
2382 2383
2383 error = sigprocmask(how, &new_set, &old_set); 2384 error = sigprocmask(how, &new_set, NULL);
2384 if (error) 2385 if (error)
2385 goto out; 2386 return error;
2386 if (oset) 2387 }
2387 goto set_old;
2388 } else if (oset) {
2389 spin_lock_irq(&current->sighand->siglock);
2390 old_set = current->blocked;
2391 spin_unlock_irq(&current->sighand->siglock);
2392 2388
2393 set_old: 2389 if (oset) {
2394 error = -EFAULT; 2390 if (copy_to_user(oset, &old_set, sizeof(sigset_t)))
2395 if (copy_to_user(oset, &old_set, sizeof(*oset))) 2391 return -EFAULT;
2396 goto out;
2397 } 2392 }
2398 error = 0; 2393
2399out: 2394 return 0;
2400 return error;
2401} 2395}
2402 2396
2403long do_sigpending(void __user *set, unsigned long sigsetsize) 2397long do_sigpending(void __user *set, unsigned long sigsetsize)