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

Commit ea3b25e1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull timer-related user access updates from Al Viro:
 "Continuation of timers-related stuff (there had been more, but my
  parts of that series are already merged via timers/core). This is more
  of y2038 work by Deepa Dinamani, partially disrupted by the
  unification of native and compat timers-related syscalls"

* 'timers-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  posix_clocks: Use get_itimerspec64() and put_itimerspec64()
  timerfd: Use get_itimerspec64() and put_itimerspec64()
  nanosleep: Use get_timespec64() and put_timespec64()
  posix-timers: Use get_timespec64() and put_timespec64()
  posix-stubs: Conditionally include COMPAT_SYS_NI defines
  time: introduce {get,put}_itimerspec64
  time: add get_timespec64 and put_timespec64
parents 89fbf538 725816e8
Loading
Loading
Loading
Loading
+21 −22
Original line number Diff line number Diff line
@@ -169,7 +169,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
}

static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
			 const struct itimerspec *ktmr)
			 const struct itimerspec64 *ktmr)
{
	enum hrtimer_mode htmode;
	ktime_t texp;
@@ -178,10 +178,10 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
	htmode = (flags & TFD_TIMER_ABSTIME) ?
		HRTIMER_MODE_ABS: HRTIMER_MODE_REL;

	texp = timespec_to_ktime(ktmr->it_value);
	texp = timespec64_to_ktime(ktmr->it_value);
	ctx->expired = 0;
	ctx->ticks = 0;
	ctx->tintv = timespec_to_ktime(ktmr->it_interval);
	ctx->tintv = timespec64_to_ktime(ktmr->it_interval);

	if (isalarm(ctx)) {
		alarm_init(&ctx->t.alarm,
@@ -432,16 +432,15 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
}

static int do_timerfd_settime(int ufd, int flags, 
		const struct itimerspec *new,
		struct itimerspec *old)
		const struct itimerspec64 *new,
		struct itimerspec64 *old)
{
	struct fd f;
	struct timerfd_ctx *ctx;
	int ret;

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

	ret = timerfd_fget(ufd, &f);
@@ -487,8 +486,8 @@ static int do_timerfd_settime(int ufd, int flags,
			hrtimer_forward_now(&ctx->t.tmr, ctx->tintv);
	}

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

	/*
	 * Re-program the timer to the new value ...
@@ -500,7 +499,7 @@ static int do_timerfd_settime(int ufd, int flags,
	return ret;
}

static int do_timerfd_gettime(int ufd, struct itimerspec *t)
static int do_timerfd_gettime(int ufd, struct itimerspec64 *t)
{
	struct fd f;
	struct timerfd_ctx *ctx;
@@ -525,8 +524,8 @@ static int do_timerfd_gettime(int ufd, struct itimerspec *t)
			hrtimer_restart(&ctx->t.tmr);
		}
	}
	t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
	t->it_interval = ktime_to_timespec(ctx->tintv);
	t->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx));
	t->it_interval = ktime_to_timespec64(ctx->tintv);
	spin_unlock_irq(&ctx->wqh.lock);
	fdput(f);
	return 0;
@@ -536,15 +535,15 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
		const struct itimerspec __user *, utmr,
		struct itimerspec __user *, otmr)
{
	struct itimerspec new, old;
	struct itimerspec64 new, old;
	int ret;

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

	return ret;
@@ -552,11 +551,11 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,

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

#ifdef CONFIG_COMPAT
@@ -564,15 +563,15 @@ COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
		const struct compat_itimerspec __user *, utmr,
		struct compat_itimerspec __user *, otmr)
{
	struct itimerspec new, old;
	struct itimerspec64 new, old;
	int ret;

	if (get_compat_itimerspec(&new, utmr))
	if (get_compat_itimerspec64(&new, utmr))
		return -EFAULT;
	ret = do_timerfd_settime(ufd, flags, &new, &old);
	if (ret)
		return ret;
	if (otmr && put_compat_itimerspec(otmr, &old))
	if (otmr && put_compat_itimerspec64(&old, otmr))
		return -EFAULT;
	return ret;
}
@@ -580,10 +579,10 @@ COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd,
		struct compat_itimerspec __user *, otmr)
{
	struct itimerspec kotmr;
	struct itimerspec64 kotmr;
	int ret = do_timerfd_gettime(ufd, &kotmr);
	if (ret)
		return ret;
	return put_compat_itimerspec(otmr, &kotmr) ? -EFAULT: 0;
	return put_compat_itimerspec64(&kotmr, otmr) ? -EFAULT : 0;
}
#endif
+6 −0
Original line number Diff line number Diff line
@@ -164,6 +164,12 @@ extern int compat_get_timespec(struct timespec *, const void __user *);
extern int compat_put_timespec(const struct timespec *, void __user *);
extern int compat_get_timeval(struct timeval *, const void __user *);
extern int compat_put_timeval(const struct timeval *, void __user *);
extern int compat_get_timespec64(struct timespec64 *, const void __user *);
extern int compat_put_timespec64(const struct timespec64 *, void __user *);
extern int get_compat_itimerspec64(struct itimerspec64 *its,
			const struct compat_itimerspec __user *uits);
extern int put_compat_itimerspec64(const struct itimerspec64 *its,
			struct compat_itimerspec __user *uits);

/*
 * This function convert a timespec if necessary and returns a *user
+1 −1
Original line number Diff line number Diff line
@@ -453,7 +453,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,

/* Precise sleep: */

extern int nanosleep_copyout(struct restart_block *, struct timespec *);
extern int nanosleep_copyout(struct restart_block *, struct timespec64 *);
extern long hrtimer_nanosleep(const struct timespec64 *rqtp,
			      const enum hrtimer_mode mode,
			      const clockid_t clockid);
+0 −1
Original line number Diff line number Diff line
@@ -113,5 +113,4 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);

void posixtimer_rearm(struct siginfo *info);

#endif
+18 −0
Original line number Diff line number Diff line
@@ -8,6 +8,15 @@

extern struct timezone sys_tz;

int get_timespec64(struct timespec64 *ts,
		const struct timespec __user *uts);
int put_timespec64(const struct timespec64 *ts,
		struct timespec __user *uts);
int get_itimerspec64(struct itimerspec64 *it,
			const struct itimerspec __user *uit);
int put_itimerspec64(const struct itimerspec64 *it,
			struct itimerspec __user *uit);

#define TIME_T_MAX	(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

static inline int timespec_equal(const struct timespec *a,
@@ -270,4 +279,13 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
	a->tv_nsec = ns;
}

static inline bool itimerspec64_valid(const struct itimerspec64 *its)
{
	if (!timespec64_valid(&(its->it_interval)) ||
		!timespec64_valid(&(its->it_value)))
		return false;

	return true;
}

#endif
Loading