The sigsuspend system call overrides the signal mask just like all of the other users of set_user_sigmask, so convert it to use the same helpers. Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> --- kernel/signal.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/kernel/signal.c b/kernel/signal.c index 6f72cff043f0..bfa36320a4f7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2932,6 +2932,15 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset) } EXPORT_SYMBOL(sigprocmask); +static int set_sigmask(sigset_t *kmask) +{ + set_restore_sigmask(); + current->saved_sigmask = current->blocked; + set_current_blocked(kmask); + + return 0; +} + /* * The api helps set app-provided sigmasks. * @@ -2952,11 +2961,7 @@ int set_user_sigmask(const sigset_t __user *umask, size_t sigsetsize) if (copy_from_user(&kmask, umask, sizeof(sigset_t))) return -EFAULT; - set_restore_sigmask(); - current->saved_sigmask = current->blocked; - set_current_blocked(&kmask); - - return 0; + return set_sigmask(&kmask); } #ifdef CONFIG_COMPAT @@ -2972,11 +2977,7 @@ int set_compat_user_sigmask(const compat_sigset_t __user *umask, if (get_compat_sigset(&kmask, umask)) return -EFAULT; - set_restore_sigmask(); - current->saved_sigmask = current->blocked; - set_current_blocked(&kmask); - - return 0; + return set_sigmask(&kmask); } #endif @@ -4409,14 +4410,10 @@ SYSCALL_DEFINE0(pause) static int sigsuspend(sigset_t *set) { - current->saved_sigmask = current->blocked; - set_current_blocked(set); - while (!signal_pending(current)) { __set_current_state(TASK_INTERRUPTIBLE); schedule(); } - set_restore_sigmask(); return -ERESTARTNOHAND; } @@ -4430,12 +4427,10 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) { sigset_t newset; - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) + set_user_sigmask(unewset, sigsetsize); + if (!unewset) return -EFAULT; + return sigsuspend(&newset); } @@ -4444,12 +4439,10 @@ COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_ { sigset_t newset; - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (get_compat_sigset(&newset, unewset)) + set_compat_user_sigmask(unewset, sigsetsize); + if (!unewset) return -EFAULT; + return sigsuspend(&newset); } #endif @@ -4459,6 +4452,7 @@ SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) { sigset_t blocked; siginitset(&blocked, mask); + set_sigmask(&blocked); return sigsuspend(&blocked); } #endif @@ -4467,6 +4461,7 @@ SYSCALL_DEFINE3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask) { sigset_t blocked; siginitset(&blocked, mask); + set_sigmask(&blocked); return sigsuspend(&blocked); } #endif -- 2.21.0.dirty