Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+25 −25
Original line number Diff line number Diff line
@@ -256,10 +256,8 @@ static const struct file_operations signalfd_fops = {
	.llseek		= noop_llseek,
};

static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
			int flags)
static int do_signalfd4(int ufd, sigset_t *mask, int flags)
{
	sigset_t sigmask;
	struct signalfd_ctx *ctx;

	/* Check the SFD_* constants for consistency.  */
@@ -269,18 +267,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
	if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
		return -EINVAL;

	if (sizemask != sizeof(sigset_t) ||
	    copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
		return -EINVAL;
	sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
	signotset(&sigmask);
	sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
	signotset(mask);

	if (ufd == -1) {
		ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
		if (!ctx)
			return -ENOMEM;

		ctx->sigmask = sigmask;
		ctx->sigmask = *mask;

		/*
		 * 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,
			return -EINVAL;
		}
		spin_lock_irq(&current->sighand->siglock);
		ctx->sigmask = sigmask;
		ctx->sigmask = *mask;
		spin_unlock_irq(&current->sighand->siglock);

		wake_up(&current->sighand->signalfd_wqh);
@@ -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,
		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,
		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
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)
{
	sigset_t tmp;
	sigset_t __user *ksigmask;
	sigset_t mask;

	if (sigsetsize != sizeof(compat_sigset_t))
		return -EINVAL;
	if (get_compat_sigset(&tmp, sigmask))
		return -EFAULT;
	ksigmask = compat_alloc_user_space(sizeof(sigset_t));
	if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
	if (get_compat_sigset(&mask, user_mask))
		return -EFAULT;

	return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
	return do_signalfd4(ufd, &mask, flags);
}

COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
		     const compat_sigset_t __user *, sigmask,
		     const compat_sigset_t __user *, user_mask,
		     compat_size_t, sigsetsize,
		     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,
		     const compat_sigset_t __user *,sigmask,
		     const compat_sigset_t __user *, user_mask,
		     compat_size_t, sigsetsize)
{
	return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0);
	return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
}
#endif