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

Commit 9d94b9e2 authored by Al Viro's avatar Al Viro
Browse files

switch timerfd compat syscalls to COMPAT_SYSCALL_DEFINE



... and move them over to fs/timerfd.c.  Cleaner and easier
that way...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 90caf58d
Loading
Loading
Loading
Loading
+0 −41
Original line number Diff line number Diff line
@@ -1737,47 +1737,6 @@ asmlinkage long compat_sys_signalfd(int ufd,
}
#endif /* CONFIG_SIGNALFD */

#ifdef CONFIG_TIMERFD

asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
				   const struct compat_itimerspec __user *utmr,
				   struct compat_itimerspec __user *otmr)
{
	int error;
	struct itimerspec t;
	struct itimerspec __user *ut;

	if (get_compat_itimerspec(&t, utmr))
		return -EFAULT;
	ut = compat_alloc_user_space(2 * sizeof(struct itimerspec));
	if (copy_to_user(&ut[0], &t, sizeof(t)))
		return -EFAULT;
	error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]);
	if (!error && otmr)
		error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) ||
			 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;

	return error;
}

asmlinkage long compat_sys_timerfd_gettime(int ufd,
				   struct compat_itimerspec __user *otmr)
{
	int error;
	struct itimerspec t;
	struct itimerspec __user *ut;

	ut = compat_alloc_user_space(sizeof(struct itimerspec));
	error = sys_timerfd_gettime(ufd, ut);
	if (!error)
		error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) ||
			 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;

	return error;
}

#endif /* CONFIG_TIMERFD */

#ifdef CONFIG_FHANDLE
/*
 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
+66 −19
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/anon_inodes.h>
#include <linux/timerfd.h>
#include <linux/syscalls.h>
#include <linux/compat.h>
#include <linux/rcupdate.h>

struct timerfd_ctx {
@@ -278,21 +279,17 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
	return ufd;
}

SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
		const struct itimerspec __user *, utmr,
		struct itimerspec __user *, otmr)
static int do_timerfd_settime(int ufd, int flags, 
		const struct itimerspec *new,
		struct itimerspec *old)
{
	struct fd f;
	struct timerfd_ctx *ctx;
	struct itimerspec ktmr, kotmr;
	int ret;

	if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
		return -EFAULT;

	if ((flags & ~TFD_SETTIME_FLAGS) ||
	    !timespec_valid(&ktmr.it_value) ||
	    !timespec_valid(&ktmr.it_interval))
	    !timespec_valid(&new->it_value) ||
	    !timespec_valid(&new->it_interval))
		return -EINVAL;

	ret = timerfd_fget(ufd, &f);
@@ -323,27 +320,23 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
	if (ctx->expired && ctx->tintv.tv64)
		hrtimer_forward_now(&ctx->tmr, ctx->tintv);

	kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
	kotmr.it_interval = ktime_to_timespec(ctx->tintv);
	old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
	old->it_interval = ktime_to_timespec(ctx->tintv);

	/*
	 * Re-program the timer to the new value ...
	 */
	ret = timerfd_setup(ctx, flags, &ktmr);
	ret = timerfd_setup(ctx, flags, new);

	spin_unlock_irq(&ctx->wqh.lock);
	fdput(f);
	if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr)))
		return -EFAULT;

	return ret;
}

SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
static int do_timerfd_gettime(int ufd, struct itimerspec *t)
{
	struct fd f;
	struct timerfd_ctx *ctx;
	struct itimerspec kotmr;
	int ret = timerfd_fget(ufd, &f);
	if (ret)
		return ret;
@@ -356,11 +349,65 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
			hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1;
		hrtimer_restart(&ctx->tmr);
	}
	kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
	kotmr.it_interval = ktime_to_timespec(ctx->tintv);
	t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
	t->it_interval = ktime_to_timespec(ctx->tintv);
	spin_unlock_irq(&ctx->wqh.lock);
	fdput(f);
	return 0;
}

SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
		const struct itimerspec __user *, utmr,
		struct itimerspec __user *, otmr)
{
	struct itimerspec new, old;
	int ret;

	if (copy_from_user(&new, utmr, sizeof(new)))
		return -EFAULT;
	ret = do_timerfd_settime(ufd, flags, &new, &old);
	if (ret)
		return ret;
	if (otmr && copy_to_user(otmr, &old, sizeof(old)))
		return -EFAULT;

	return ret;
}

SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
{
	struct itimerspec kotmr;
	int ret = do_timerfd_gettime(ufd, &kotmr);
	if (ret)
		return ret;
	return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
}

#ifdef COMPAT
COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
		const struct itimerspec __user *, utmr,
		struct itimerspec __user *, otmr)
{
	struct itimerspec new, old;
	int ret;

	if (get_compat_itimerspec(&new, utmr))
		return -EFAULT;
	ret = do_timerfd_settime(ufd, flags, &new, &old);
	if (ret)
		return ret;
	if (otmr && put_compat_itimerspec(otmr, &old))
		return -EFAULT;
	return ret;
}

COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd,
		struct itimerspec __user *, otmr)
{
	struct itimerspec kotmr;
	int ret = do_timerfd_gettime(ufd, &kotmr);
	if (ret)
		return ret;
	return put_compat_itimerspec(otmr, &t) ? -EFAULT: 0;
}
#endif