Commit 5ed0127f authored by Al Viro's avatar Al Viro

signalfd: lift sigmask copyin and size checks to callers of do_signalfd4()

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 87a3002a
...@@ -256,10 +256,8 @@ static const struct file_operations signalfd_fops = { ...@@ -256,10 +256,8 @@ static const struct file_operations signalfd_fops = {
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, static int do_signalfd4(int ufd, sigset_t *mask, int flags)
int flags)
{ {
sigset_t sigmask;
struct signalfd_ctx *ctx; struct signalfd_ctx *ctx;
/* Check the SFD_* constants for consistency. */ /* Check the SFD_* constants for consistency. */
...@@ -269,18 +267,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, ...@@ -269,18 +267,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK)) if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
return -EINVAL; return -EINVAL;
if (sizemask != sizeof(sigset_t) || sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
copy_from_user(&sigmask, user_mask, sizeof(sigmask))) signotset(mask);
return -EINVAL;
sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
signotset(&sigmask);
if (ufd == -1) { if (ufd == -1) {
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) if (!ctx)
return -ENOMEM; return -ENOMEM;
ctx->sigmask = sigmask; ctx->sigmask = *mask;
/* /*
* When we call this, the initialization must be complete, since * When we call this, the initialization must be complete, since
...@@ -300,7 +295,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, ...@@ -300,7 +295,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
return -EINVAL; return -EINVAL;
} }
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
ctx->sigmask = sigmask; ctx->sigmask = *mask;
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
wake_up(&current->sighand->signalfd_wqh); wake_up(&current->sighand->signalfd_wqh);
...@@ -313,46 +308,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask, ...@@ -313,46 +308,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask, int, flags) size_t, sizemask, int, flags)
{ {
return do_signalfd4(ufd, user_mask, sizemask, flags); sigset_t mask;
if (sizemask != sizeof(sigset_t) ||
copy_from_user(&mask, user_mask, sizeof(mask)))
return -EINVAL;
return do_signalfd4(ufd, &mask, flags);
} }
SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask, SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask) size_t, sizemask)
{ {
return do_signalfd4(ufd, user_mask, sizemask, 0); sigset_t mask;
if (sizemask != sizeof(sigset_t) ||
copy_from_user(&mask, user_mask, sizeof(mask)))
return -EINVAL;
return do_signalfd4(ufd, &mask, 0);
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
static long do_compat_signalfd4(int ufd, static long do_compat_signalfd4(int ufd,
const compat_sigset_t __user *sigmask, const compat_sigset_t __user *user_mask,
compat_size_t sigsetsize, int flags) compat_size_t sigsetsize, int flags)
{ {
sigset_t tmp; sigset_t mask;
sigset_t __user *ksigmask;
if (sigsetsize != sizeof(compat_sigset_t)) if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL; return -EINVAL;
if (get_compat_sigset(&tmp, sigmask)) if (get_compat_sigset(&mask, user_mask))
return -EFAULT;
ksigmask = compat_alloc_user_space(sizeof(sigset_t));
if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
return -EFAULT; return -EFAULT;
return do_signalfd4(ufd, &mask, flags);
return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
} }
COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
const compat_sigset_t __user *, sigmask, const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize, compat_size_t, sigsetsize,
int, flags) int, flags)
{ {
return do_compat_signalfd4(ufd, sigmask, sigsetsize, flags); return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
} }
COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd, COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
const compat_sigset_t __user *,sigmask, const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize) compat_size_t, sigsetsize)
{ {
return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0); return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
} }
#endif #endif
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