Commit bb7efee2 authored by Oleg Nesterov's avatar Oleg Nesterov

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: default avatarOleg Nesterov <oleg@redhat.com>
Reviewed-by: default avatarMatt Fleming <matt.fleming@linux.intel.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
parent e9bd3f0f
...@@ -2364,40 +2364,34 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset) ...@@ -2364,40 +2364,34 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
* @oset: previous value of signal mask if non-null * @oset: previous value of signal mask if non-null
* @sigsetsize: size of sigset_t type * @sigsetsize: size of sigset_t type
*/ */
SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, set, SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset,
sigset_t __user *, oset, size_t, sigsetsize) sigset_t __user *, oset, size_t, sigsetsize)
{ {
int error = -EINVAL;
sigset_t old_set, new_set; sigset_t old_set, new_set;
int error;
/* XXX: Don't preclude handling different sized sigset_t's. */ /* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t)) if (sigsetsize != sizeof(sigset_t))
goto out; return -EINVAL;
if (set) { old_set = current->blocked;
error = -EFAULT;
if (copy_from_user(&new_set, set, sizeof(*set))) if (nset) {
goto out; if (copy_from_user(&new_set, nset, sizeof(sigset_t)))
return -EFAULT;
sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
error = sigprocmask(how, &new_set, &old_set); error = sigprocmask(how, &new_set, NULL);
if (error) if (error)
goto out; return error;
if (oset) }
goto set_old;
} else if (oset) {
spin_lock_irq(&current->sighand->siglock);
old_set = current->blocked;
spin_unlock_irq(&current->sighand->siglock);
set_old: if (oset) {
error = -EFAULT; if (copy_to_user(oset, &old_set, sizeof(sigset_t)))
if (copy_to_user(oset, &old_set, sizeof(*oset))) return -EFAULT;
goto out;
} }
error = 0;
out: return 0;
return error;
} }
long do_sigpending(void __user *set, unsigned long sigsetsize) long do_sigpending(void __user *set, unsigned long sigsetsize)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment