linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHSET] sanitizing compat nanosleep and other timer-related syscalls
@ 2017-06-07  8:41 Al Viro
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
  0 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:41 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

	The series is on top of tip.git#timers/core; the first half
massages {clock_,}nanosleep(), the rest deals with other
timer-related compat syscalls.
	As it is, nanosleep() has rather convoluted logics for
copying the timespec to userland.  It can happen in the syscall
itself, or in restart callback triggered on restart.  Naturally,
there is quite a bit of shared code between those; after all,
restart callbacks mimic what would've been a plain syscall
restart, if not for the need to recalculate timeouts.  However,
copying the timespec to userland is *not* a part of shared code -
it's duplicated in sys_nanosleep() and hrtimer_nanosleep_restart(),
and similar for clock_nanosleep().  Moving that copyout into
hrtimer_nanosleep() and its ilk simplifies life.
	What's more, that allows to deal with another bit of
nastiness - compat side of nanosleep(2) has to play very sick
games.  It calls sys_nanosleep() under set_fs(KERNEL_DS) and
passes it a pointer to on-stack (native) timespec.  Then it
converts that to 32bit timespec and copies it to userland;
so far, so good, but if we are going to hit a restart, we can't
leave the restart callback (and arguments for it) as-is -
after all, the pointer to "userland" timespec actually points
to kernel stack frame, long gone by the time we get to restart.
So we flip the restart callback to one of our own and stash
the real userland pointer for it.  When that callback is finally
called, it plays with restart args again and calls the native
callback under KERNEL_DS, followed by the same dance as in
the compat syscall itself.  For clock_nanosleep() it's even
more convoluted...
	All that mess goes away if we teach hrtimer_nanosleep()
to handle both the native and compat copyout.  All we need is
to turn the (userland pointer to native timespec, userland pointer
to compat timespec) pair in restart_block into a tagged union
and add a helper used by hrtimer_nanosleep() (and clock_...
counterparts thereof), doing the actual copyout.  Massage to
get there is longer than I would like, but the code is convoluted
enough to make doing that in a single step too scary.
	The second half is a plain and simple "move compat syscall
towards the native one, get rid of set_fs() by doing what the
native one would with different copyin/copyout" stuff; that avoids
double copying and set_fs() games in cases where we used to play
those and allows to make the guts static in cases when we didn't.
Either way, compat syscalls are better off next to the native
ones.

	Please, review.  The patches will go in followups to this
mail; for those who prefer to use git tree, it is visible in
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git#timers-compat
(the first half - in #timers-nanosleep in the same repo).

Al Viro (16):
      move copyout of timespec into do_cpu_nanosleep()
      move copyout and freeze handling into alarmtimer_do_nsleep()
      hrtimer_nanosleep(): pass rmtp in restart_block
      move copyout to do_nanosleel()
      clock_nanosleep(): stash rmtp into restart_block
      nanosleep/clock_nanosleep: teach to do compat copyouts
      {clock_,}nanosleep(2): merge timespec copyout logics into a new helper
      kill ->nsleep_restart()
      move adjtimex-related compat syscalls to native counterparts
      take compat timer_settime(2) to native one
      take compat timer_gettime(2) to native one
      move compat itimer syscalls to native ones
      clock_gettime/clock_settime/clock_getres: move to native syscalls
      timer_create(): move compat to native, get rid of set_fs()
      time()/stime(): move compat to native
      gettimeofday()/settimeofday(): move compat to native

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep()
  2017-06-07  8:41 [PATCHSET] sanitizing compat nanosleep and other timer-related syscalls Al Viro
@ 2017-06-07  8:42 ` Al Viro
  2017-06-07  8:42   ` [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep() Al Viro
                     ` (16 more replies)
  0 siblings, 17 replies; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/time/posix-cpu-timers.c | 62 ++++++++++++++++++------------------------
 1 file changed, 27 insertions(+), 35 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index cb4a4eb44279..ef1f2bdc896e 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1226,9 +1226,10 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 }
 
 static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
-			    struct timespec64 *rqtp, struct itimerspec64 *it)
+			    struct timespec64 *rqtp)
 {
 	struct k_itimer timer;
+	struct itimerspec64 it;
 	int error;
 
 	/*
@@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	timer.it_process = current;
 	if (!error) {
 		static struct itimerspec64 zero_it;
+		struct restart_block *restart = &current->restart_block;
+		struct timespec __user *rmtp;
 
-		memset(it, 0, sizeof *it);
-		it->it_value = *rqtp;
+		memset(&it, 0, sizeof it);
+		it.it_value = *rqtp;
 
 		spin_lock_irq(&timer.it_lock);
-		error = posix_cpu_timer_set(&timer, flags, it, NULL);
+		error = posix_cpu_timer_set(&timer, flags, &it, NULL);
 		if (error) {
 			spin_unlock_irq(&timer.it_lock);
 			return error;
@@ -1277,7 +1280,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		 * We were interrupted by a signal.
 		 */
 		*rqtp = ns_to_timespec64(timer.it.cpu.expires);
-		error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
 		if (!error) {
 			/*
 			 * Timer is now unarmed, deletion can not fail.
@@ -1297,7 +1300,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 			spin_unlock_irq(&timer.it_lock);
 		}
 
-		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
+		if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
 			/*
 			 * It actually did fire already.
 			 */
@@ -1305,6 +1308,17 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		}
 
 		error = -ERESTART_RESTARTBLOCK;
+		/*
+		 * Report back to the user the time still remaining.
+		 */
+		rmtp = restart->nanosleep.rmtp;
+		if (rmtp) {
+			struct timespec ts;
+			ts = timespec64_to_timespec(it.it_value);
+			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
+				return -EFAULT;
+		}
+		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 
 	return error;
@@ -1316,10 +1330,13 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 			    struct timespec64 *rqtp, struct timespec __user *rmtp)
 {
 	struct restart_block *restart_block = &current->restart_block;
-	struct itimerspec64 it;
-	struct timespec ts;
 	int error;
 
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+
+	restart_block->nanosleep.rmtp = rmtp;
+
 	/*
 	 * Diagnose required errors first.
 	 */
@@ -1328,23 +1345,15 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 	     CPUCLOCK_PID(which_clock) == task_pid_vnr(current)))
 		return -EINVAL;
 
-	error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
+	error = do_cpu_nanosleep(which_clock, flags, rqtp);
 
 	if (error == -ERESTART_RESTARTBLOCK) {
 
 		if (flags & TIMER_ABSTIME)
 			return -ERESTARTNOHAND;
-		/*
-		 * Report back to the user the time still remaining.
-		 */
-		ts = timespec64_to_timespec(it.it_value);
-		if (rmtp && copy_to_user(rmtp, &ts, sizeof(*rmtp)))
-			return -EFAULT;
 
 		restart_block->fn = posix_cpu_nsleep_restart;
 		restart_block->nanosleep.clockid = which_clock;
-		restart_block->nanosleep.rmtp = rmtp;
-		restart_block->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 	return error;
 }
@@ -1352,28 +1361,11 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
 	clockid_t which_clock = restart_block->nanosleep.clockid;
-	struct itimerspec64 it;
 	struct timespec64 t;
-	struct timespec tmp;
-	int error;
 
 	t = ns_to_timespec64(restart_block->nanosleep.expires);
 
-	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
-
-	if (error == -ERESTART_RESTARTBLOCK) {
-		struct timespec __user *rmtp = restart_block->nanosleep.rmtp;
-		/*
-		 * Report back to the user the time still remaining.
-		 */
-		 tmp = timespec64_to_timespec(it.it_value);
-		if (rmtp && copy_to_user(rmtp, &tmp, sizeof(*rmtp)))
-			return -EFAULT;
-
-		restart_block->nanosleep.expires = timespec64_to_ns(&t);
-	}
-	return error;
-
+	return do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t);
 }
 
 #define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:04     ` [tip:timers/core] alarmtimer: Move " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 03/16] hrtimer_nanosleep(): pass rmtp in restart_block Al Viro
                     ` (15 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/time/alarmtimer.c | 102 +++++++++++++++--------------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index d8a7a7e214de..ac6e9bc6cc59 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -688,8 +688,10 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
  *
  * Sets the alarm timer and sleeps until it is fired or interrupted.
  */
-static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
+static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
+				enum alarmtimer_type type)
 {
+	struct timespec __user *rmtp;
 	alarm->data = (void *)current;
 	do {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -702,36 +704,26 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
 
 	__set_current_state(TASK_RUNNING);
 
-	return (alarm->data == NULL);
-}
-
-
-/**
- * update_rmtp - Update remaining timespec value
- * @exp: expiration time
- * @type: timer type
- * @rmtp: user pointer to remaining timepsec value
- *
- * Helper function that fills in rmtp value with time between
- * now and the exp value
- */
-static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
-			struct timespec __user *rmtp)
-{
-	struct timespec rmt;
-	ktime_t rem;
-
-	rem = ktime_sub(exp, alarm_bases[type].gettime());
-
-	if (rem <= 0)
+	if (!alarm->data)
 		return 0;
-	rmt = ktime_to_timespec(rem);
 
-	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-		return -EFAULT;
+	if (freezing(current))
+		alarmtimer_freezerset(absexp, type);
+	rmtp = current->restart_block.nanosleep.rmtp;
+	if (rmtp) {
+		struct timespec rmt;
+		ktime_t rem;
 
-	return 1;
+		rem = ktime_sub(absexp, alarm_bases[type].gettime());
 
+		if (rem <= 0)
+			return 0;
+		rmt = ktime_to_timespec(rem);
+
+		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+			return -EFAULT;
+	}
+	return -ERESTART_RESTARTBLOCK;
 }
 
 /**
@@ -743,32 +735,12 @@ static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
 static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
 {
 	enum  alarmtimer_type type = restart->nanosleep.clockid;
-	ktime_t exp;
-	struct timespec __user  *rmtp;
+	ktime_t exp = restart->nanosleep.expires;
 	struct alarm alarm;
-	int ret = 0;
 
-	exp = restart->nanosleep.expires;
 	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
 
-	if (alarmtimer_do_nsleep(&alarm, exp))
-		goto out;
-
-	if (freezing(current))
-		alarmtimer_freezerset(exp, type);
-
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(exp, type, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
-
-	/* The other values in restart are already filled in */
-	ret = -ERESTART_RESTARTBLOCK;
-out:
-	return ret;
+	return alarmtimer_do_nsleep(&alarm, exp, type);
 }
 
 /**
@@ -785,11 +757,16 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 			      struct timespec __user *rmtp)
 {
 	enum  alarmtimer_type type = clock2alarm(which_clock);
-	struct restart_block *restart;
+	struct restart_block *restart = &current->restart_block;
 	struct alarm alarm;
 	ktime_t exp;
 	int ret = 0;
 
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+
+	restart->nanosleep.rmtp = rmtp;
+
 	if (!alarmtimer_get_rtcdev())
 		return -ENOTSUPP;
 
@@ -808,32 +785,17 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 		exp = ktime_add(now, exp);
 	}
 
-	if (alarmtimer_do_nsleep(&alarm, exp))
-		goto out;
-
-	if (freezing(current))
-		alarmtimer_freezerset(exp, type);
+	ret = alarmtimer_do_nsleep(&alarm, exp, type);
+	if (ret != -ERESTART_RESTARTBLOCK)
+		return ret;
 
 	/* abs timers don't set remaining time or restart */
-	if (flags == TIMER_ABSTIME) {
-		ret = -ERESTARTNOHAND;
-		goto out;
-	}
-
-	if (rmtp) {
-		ret = update_rmtp(exp, type, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
+	if (flags == TIMER_ABSTIME)
+		return -ERESTARTNOHAND;
 
-	restart = &current->restart_block;
 	restart->fn = alarm_timer_nsleep_restart;
 	restart->nanosleep.clockid = type;
 	restart->nanosleep.expires = exp;
-	restart->nanosleep.rmtp = rmtp;
-	ret = -ERESTART_RESTARTBLOCK;
-
-out:
 	return ret;
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/16] hrtimer_nanosleep(): pass rmtp in restart_block
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
  2017-06-07  8:42   ` [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep() Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:05     ` [tip:timers/core] hrtimer_nanosleep(): Pass " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 04/16] move copyout to do_nanosleel() Al Viro
                     ` (14 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/hrtimer.h    |  1 -
 kernel/compat.c            |  6 +++---
 kernel/time/hrtimer.c      | 11 ++++++-----
 kernel/time/posix-stubs.c  |  5 ++++-
 kernel/time/posix-timers.c |  5 ++++-
 5 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 8c5b10eb7265..b80c34f6fd4b 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -453,7 +453,6 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
 
 /* Precise sleep: */
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
-			      struct timespec __user *rmtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
 extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
diff --git a/kernel/compat.c b/kernel/compat.c
index 933bcb31ae10..cc9ba9d29b47 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -253,9 +253,9 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
 
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep(&tu64,
-				rmtp ? (struct timespec __user *)&rmt : NULL,
-				HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+	current->restart_block.nanosleep.rmtp =
+				rmtp ? (struct timespec __user *)&rmt : NULL;
+	ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 	set_fs(oldfs);
 
 	/*
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index ac053bb5296e..4ae777f159de 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1503,10 +1503,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 	return ret;
 }
 
-long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,
+long hrtimer_nanosleep(struct timespec64 *rqtp,
 		       const enum hrtimer_mode mode, const clockid_t clockid)
 {
-	struct restart_block *restart;
+	struct restart_block *restart = &current->restart_block;
+	struct timespec __user *rmtp;
 	struct hrtimer_sleeper t;
 	int ret = 0;
 	u64 slack;
@@ -1526,16 +1527,15 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,
 		goto out;
 	}
 
+	rmtp = restart->nanosleep.rmtp;
 	if (rmtp) {
 		ret = update_rmtp(&t.timer, rmtp);
 		if (ret <= 0)
 			goto out;
 	}
 
-	restart = &current->restart_block;
 	restart->fn = hrtimer_nanosleep_restart;
 	restart->nanosleep.clockid = t.timer.base->clockid;
-	restart->nanosleep.rmtp = rmtp;
 	restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
 
 	ret = -ERESTART_RESTARTBLOCK;
@@ -1557,7 +1557,8 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
-	return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+	current->restart_block.nanosleep.rmtp = rmtp;
+	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
 /*
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c0cd53eb018a..156a5e6f3bd2 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -115,7 +115,10 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		t64 = timespec_to_timespec64(t);
 		if (!timespec64_valid(&t64))
 			return -EINVAL;
-		return hrtimer_nanosleep(&t64, rmtp, flags & TIMER_ABSTIME ?
+		if (flags & TIMER_ABSTIME)
+			rmtp = NULL;
+		current->restart_block.nanosleep.rmtp = rmtp;
+		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 					 which_clock);
 	default:
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 6e7a70b1bf37..5108023a5f3b 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1028,7 +1028,10 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 static int common_nsleep(const clockid_t which_clock, int flags,
 			 struct timespec64 *tsave, struct timespec __user *rmtp)
 {
-	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.rmtp = rmtp;
+	return hrtimer_nanosleep(tsave, flags & TIMER_ABSTIME ?
 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 				 which_clock);
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/16] move copyout to do_nanosleel()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
  2017-06-07  8:42   ` [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep() Al Viro
  2017-06-07  8:42   ` [PATCH 03/16] hrtimer_nanosleep(): pass rmtp in restart_block Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:05     ` [tip:timers/core] hrtimer: Move copyout of remaining time to do_nanosleep() tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 05/16] clock_nanosleep(): stash rmtp into restart_block Al Viro
                     ` (13 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/time/hrtimer.c | 62 +++++++++++++++++----------------------------------
 1 file changed, 20 insertions(+), 42 deletions(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 4ae777f159de..baa7b846b6e3 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1441,6 +1441,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
+	struct timespec __user *rmtp;
 	hrtimer_init_sleeper(t, current);
 
 	do {
@@ -1457,48 +1458,33 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 
 	__set_current_state(TASK_RUNNING);
 
-	return t->task == NULL;
-}
-
-static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
-{
-	struct timespec rmt;
-	ktime_t rem;
-
-	rem = hrtimer_expires_remaining(timer);
-	if (rem <= 0)
+	if (!t->task)
 		return 0;
-	rmt = ktime_to_timespec(rem);
 
-	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-		return -EFAULT;
-
-	return 1;
+	rmtp = current->restart_block.nanosleep.rmtp;
+	if (rmtp) {
+		struct timespec rmt;
+		ktime_t rem = hrtimer_expires_remaining(&t->timer);
+		if (rem <= 0)
+			return 0;
+		rmt = ktime_to_timespec(rem);
+
+		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+			return -EFAULT;
+	}
+	return -ERESTART_RESTARTBLOCK;
 }
 
 long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
 	struct hrtimer_sleeper t;
-	struct timespec __user  *rmtp;
-	int ret = 0;
+	int ret;
 
 	hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid,
 				HRTIMER_MODE_ABS);
 	hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
 
-	if (do_nanosleep(&t, HRTIMER_MODE_ABS))
-		goto out;
-
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(&t.timer, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
-	/* The other values in restart are already filled in */
-	ret = -ERESTART_RESTARTBLOCK;
-out:
+	ret = do_nanosleep(&t, HRTIMER_MODE_ABS);
 	destroy_hrtimer_on_stack(&t.timer);
 	return ret;
 }
@@ -1506,8 +1492,7 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 long hrtimer_nanosleep(struct timespec64 *rqtp,
 		       const enum hrtimer_mode mode, const clockid_t clockid)
 {
-	struct restart_block *restart = &current->restart_block;
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
 	struct hrtimer_sleeper t;
 	int ret = 0;
 	u64 slack;
@@ -1518,7 +1503,8 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
 
 	hrtimer_init_on_stack(&t.timer, clockid, mode);
 	hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack);
-	if (do_nanosleep(&t, mode))
+	ret = do_nanosleep(&t, mode);
+	if (ret != -ERESTART_RESTARTBLOCK)
 		goto out;
 
 	/* Absolute timers do not update the rmtp value and restart: */
@@ -1527,18 +1513,10 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
 		goto out;
 	}
 
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(&t.timer, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
+	restart = &current->restart_block;
 	restart->fn = hrtimer_nanosleep_restart;
 	restart->nanosleep.clockid = t.timer.base->clockid;
 	restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
-
-	ret = -ERESTART_RESTARTBLOCK;
 out:
 	destroy_hrtimer_on_stack(&t.timer);
 	return ret;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/16] clock_nanosleep(): stash rmtp into restart_block
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (2 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 04/16] move copyout to do_nanosleel() Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:06     ` [tip:timers/core] posix-timers: Store rmtp into restart_block in sys_clock_nanosleep() tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts Al Viro
                     ` (12 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

... instead of doing that in every ->nsleep() instance

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/time/alarmtimer.c       |  8 +-------
 kernel/time/posix-cpu-timers.c | 12 +++---------
 kernel/time/posix-timers.c     | 10 +++++-----
 kernel/time/posix-timers.h     |  2 +-
 4 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index ac6e9bc6cc59..d859a3601ddd 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -753,8 +753,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
  * Handles clock_nanosleep calls against _ALARM clockids
  */
 static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
-			      struct timespec64 *tsreq,
-			      struct timespec __user *rmtp)
+			      struct timespec64 *tsreq)
 {
 	enum  alarmtimer_type type = clock2alarm(which_clock);
 	struct restart_block *restart = &current->restart_block;
@@ -762,11 +761,6 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 	ktime_t exp;
 	int ret = 0;
 
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-
-	restart->nanosleep.rmtp = rmtp;
-
 	if (!alarmtimer_get_rtcdev())
 		return -ENOTSUPP;
 
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ef1f2bdc896e..f999b3ebba7e 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1327,16 +1327,11 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 static long posix_cpu_nsleep_restart(struct restart_block *restart_block);
 
 static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-			    struct timespec64 *rqtp, struct timespec __user *rmtp)
+			    struct timespec64 *rqtp)
 {
 	struct restart_block *restart_block = &current->restart_block;
 	int error;
 
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-
-	restart_block->nanosleep.rmtp = rmtp;
-
 	/*
 	 * Diagnose required errors first.
 	 */
@@ -1387,10 +1382,9 @@ static int process_cpu_timer_create(struct k_itimer *timer)
 	return posix_cpu_timer_create(timer);
 }
 static int process_cpu_nsleep(const clockid_t which_clock, int flags,
-			      struct timespec64 *rqtp,
-			      struct timespec __user *rmtp)
+			      struct timespec64 *rqtp)
 {
-	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
+	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
 }
 static long process_cpu_nsleep_restart(struct restart_block *restart_block)
 {
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 5108023a5f3b..f39ed4bdcc5a 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1026,11 +1026,8 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
  * nanosleep for monotonic and realtime clocks
  */
 static int common_nsleep(const clockid_t which_clock, int flags,
-			 struct timespec64 *tsave, struct timespec __user *rmtp)
+			 struct timespec64 *tsave)
 {
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-	current->restart_block.nanosleep.rmtp = rmtp;
 	return hrtimer_nanosleep(tsave, flags & TIMER_ABSTIME ?
 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 				 which_clock);
@@ -1055,8 +1052,11 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 	t64 = timespec_to_timespec64(t);
 	if (!timespec64_valid(&t64))
 		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.rmtp = rmtp;
 
-	return kc->nsleep(which_clock, flags, &t64, rmtp);
+	return kc->nsleep(which_clock, flags, &t64);
 }
 
 /*
diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h
index b086f5ba2f5b..bfd9e15c6ce0 100644
--- a/kernel/time/posix-timers.h
+++ b/kernel/time/posix-timers.h
@@ -10,7 +10,7 @@ struct k_clock {
 	int	(*clock_adj)(const clockid_t which_clock, struct timex *tx);
 	int	(*timer_create)(struct k_itimer *timer);
 	int	(*nsleep)(const clockid_t which_clock, int flags,
-			  struct timespec64 *, struct timespec __user *);
+			  struct timespec64 *);
 	long	(*nsleep_restart)(struct restart_block *restart_block);
 	int	(*timer_set)(struct k_itimer *timr, int flags,
 			     struct itimerspec64 *new_setting,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (3 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 05/16] clock_nanosleep(): stash rmtp into restart_block Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-07 10:07     ` Peter Zijlstra
  2017-06-13 22:06     ` [tip:timers/core] time/posix-timers: Move the compat copyouts to the nanosleep implementations tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 07/16] {clock_,}nanosleep(2): merge timespec copyout logics into a new helper Al Viro
                     ` (11 subsequent siblings)
  16 siblings, 2 replies; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Turn restart_block.nanosleep.{rmtp,compat_rmtp} into a tagged union
(kind = 1 -> native, kind = 2 -> compat, kind = 0 -> nothing) and
make the places doing actual copyout handle compat as well as
native (that will become a helper in the next commit).  Result:
compat wrappers, messing with reassignments, etc. are gone.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/posix-timers.h   |   2 -
 include/linux/restart_block.h  |   7 ++-
 kernel/compat.c                | 131 -----------------------------------------
 kernel/time/alarmtimer.c       |  16 +++--
 kernel/time/hrtimer.c          |  38 ++++++++++--
 kernel/time/posix-cpu-timers.c |  18 ++++--
 kernel/time/posix-stubs.c      |  29 ++++++++-
 kernel/time/posix-timers.c     |  32 +++++++---
 8 files changed, 115 insertions(+), 158 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 667095dbcd37..29f1b7f09ced 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -110,8 +110,6 @@ void posix_cpu_timers_exit_group(struct task_struct *task);
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
 			   u64 *newval, u64 *oldval);
 
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
 
 void posixtimer_rearm(struct siginfo *info);
diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
index 0d905d8ec553..4509944bd953 100644
--- a/include/linux/restart_block.h
+++ b/include/linux/restart_block.h
@@ -29,10 +29,13 @@ struct restart_block {
 		/* For nanosleep */
 		struct {
 			clockid_t clockid;
-			struct timespec __user *rmtp;
+			int kind;
+			union {
+				struct timespec __user *rmtp;
 #ifdef CONFIG_COMPAT
-			struct compat_timespec __user *compat_rmtp;
+				struct compat_timespec __user *compat_rmtp;
 #endif
+			};
 			u64 expires;
 		} nanosleep;
 		/* For poll */
diff --git a/kernel/compat.c b/kernel/compat.c
index cc9ba9d29b47..23afa26f574b 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -213,82 +213,6 @@ int compat_convert_timespec(struct timespec __user **kts,
 	return 0;
 }
 
-static long compat_nanosleep_restart(struct restart_block *restart)
-{
-	struct compat_timespec __user *rmtp;
-	struct timespec rmt;
-	mm_segment_t oldfs;
-	long ret;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		rmtp = restart->nanosleep.compat_rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	struct timespec tu, rmt;
-	struct timespec64 tu64;
-	mm_segment_t oldfs;
-	long ret;
-
-	if (compat_get_timespec(&tu, rqtp))
-		return -EFAULT;
-
-	tu64 = timespec_to_timespec64(tu);
-	if (!timespec64_valid(&tu64))
-		return -EINVAL;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	current->restart_block.nanosleep.rmtp =
-				rmtp ? (struct timespec __user *)&rmt : NULL;
-	ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
-	set_fs(oldfs);
-
-	/*
-	 * hrtimer_nanosleep() can only return 0 or
-	 * -ERESTART_RESTARTBLOCK here because:
-	 *
-	 * - we call it with HRTIMER_MODE_REL and therefor exclude the
-	 *   -ERESTARTNOHAND return path.
-	 *
-	 * - we supply the rmtp argument from the task stack (due to
-	 *   the necessary compat conversion. So the update cannot
-	 *   fail, which excludes the -EFAULT return path as well. If
-	 *   it fails nevertheless we have a bigger problem and wont
-	 *   reach this place anymore.
-	 *
-	 * - if the return value is 0, we do not have to update rmtp
-	 *    because there is no remaining time.
-	 *
-	 * We check for -ERESTART_RESTARTBLOCK nevertheless if the
-	 * core implementation decides to return random nonsense.
-	 */
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		struct restart_block *restart = &current->restart_block;
-
-		restart->fn = compat_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 static inline long get_compat_itimerval(struct itimerval *o,
 		struct compat_itimerval __user *i)
 {
@@ -821,61 +745,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 	return err;
 }
 
-static long compat_clock_nanosleep_restart(struct restart_block *restart)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec tu;
-	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = clock_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&tu, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
-		       struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec in, out;
-	struct restart_block *restart;
-
-	if (compat_get_timespec(&in, rqtp))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_nanosleep(which_clock, flags,
-				  (struct timespec __user *) &in,
-				  (struct timespec __user *) &out);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&out, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart = &current->restart_block;
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index d859a3601ddd..868083ae7434 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -27,6 +27,7 @@
 #include <linux/posix-timers.h>
 #include <linux/workqueue.h>
 #include <linux/freezer.h>
+#include <linux/compat.h>
 
 #include "posix-timers.h"
 
@@ -691,7 +692,7 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
 static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 				enum alarmtimer_type type)
 {
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
 	alarm->data = (void *)current;
 	do {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -709,8 +710,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 
 	if (freezing(current))
 		alarmtimer_freezerset(absexp, type);
-	rmtp = current->restart_block.nanosleep.rmtp;
-	if (rmtp) {
+	restart = &current->restart_block;
+	if (restart->nanosleep.kind) {
 		struct timespec rmt;
 		ktime_t rem;
 
@@ -720,7 +721,14 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+		if (restart->nanosleep.kind == 2) {
+			if (compat_put_timespec(&rmt,
+						restart->nanosleep.compat_rmtp))
+				return -EFAULT;
+		} else
+#endif
+		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
 			return -EFAULT;
 	}
 	return -ERESTART_RESTARTBLOCK;
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index baa7b846b6e3..5534606e3985 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -51,6 +51,7 @@
 #include <linux/sched/debug.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
+#include <linux/compat.h>
 
 #include <linux/uaccess.h>
 
@@ -1441,7 +1442,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
 	hrtimer_init_sleeper(t, current);
 
 	do {
@@ -1461,15 +1462,22 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 	if (!t->task)
 		return 0;
 
-	rmtp = current->restart_block.nanosleep.rmtp;
-	if (rmtp) {
+	restart = &current->restart_block;
+	if (restart->nanosleep.kind) {
 		struct timespec rmt;
 		ktime_t rem = hrtimer_expires_remaining(&t->timer);
 		if (rem <= 0)
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+		if (restart->nanosleep.kind == 2) {
+			if (compat_put_timespec(&rmt,
+						restart->nanosleep.compat_rmtp))
+				return -EFAULT;
+		} else
+#endif
+		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
 			return -EFAULT;
 	}
 	return -ERESTART_RESTARTBLOCK;
@@ -1535,10 +1543,32 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
+	current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
 	current->restart_block.nanosleep.rmtp = rmtp;
 	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
+{
+	struct timespec tu;
+	struct timespec64 tu64;
+
+	if (compat_get_timespec(&tu, rqtp))
+		return -EFAULT;
+
+	tu64 = timespec_to_timespec64(tu);
+	if (!timespec64_valid(&tu64))
+		return -EINVAL;
+
+	current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+	current->restart_block.nanosleep.compat_rmtp = rmtp;
+	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+}
+#endif
+
 /*
  * Functions related to boot-time initialization:
  */
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index f999b3ebba7e..b88bc3fc56c5 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -12,6 +12,7 @@
 #include <trace/events/timer.h>
 #include <linux/tick.h>
 #include <linux/workqueue.h>
+#include <linux/compat.h>
 
 #include "posix-timers.h"
 
@@ -1243,8 +1244,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	timer.it_process = current;
 	if (!error) {
 		static struct itimerspec64 zero_it;
-		struct restart_block *restart = &current->restart_block;
-		struct timespec __user *rmtp;
+		struct restart_block *restart;
 
 		memset(&it, 0, sizeof it);
 		it.it_value = *rqtp;
@@ -1311,11 +1311,19 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		/*
 		 * Report back to the user the time still remaining.
 		 */
-		rmtp = restart->nanosleep.rmtp;
-		if (rmtp) {
+		restart = &current->restart_block;
+		if (restart->nanosleep.kind) {
 			struct timespec ts;
 			ts = timespec64_to_timespec(it.it_value);
-			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+			if (restart->nanosleep.kind == 2) {
+				if (compat_put_timespec(&ts,
+						restart->nanosleep.compat_rmtp))
+					return -EFAULT;
+			} else
+#endif
+			if (copy_to_user(restart->nanosleep.rmtp, &ts,
+					sizeof(ts)))
 				return -EFAULT;
 		}
 		restart->nanosleep.expires = timespec64_to_ns(rqtp);
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 156a5e6f3bd2..2fe2322d1243 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -17,6 +17,7 @@
 #include <linux/ktime.h>
 #include <linux/timekeeping.h>
 #include <linux/posix-timers.h>
+#include <linux/compat.h>
 
 asmlinkage long sys_ni_posix_timers(void)
 {
@@ -117,6 +118,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 			return -EINVAL;
 		if (flags & TIMER_ABSTIME)
 			rmtp = NULL;
+		current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
 		current->restart_block.nanosleep.rmtp = rmtp;
 		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
@@ -127,8 +129,31 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 }
 
 #ifdef CONFIG_COMPAT
-long clock_nanosleep_restart(struct restart_block *restart_block)
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
 {
-	return hrtimer_nanosleep_restart(restart_block);
+	struct timespec64 t64;
+	struct timespec t;
+
+	switch (which_clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+	case CLOCK_BOOTTIME:
+		if (compat_get_timespec(&t, rqtp))
+			return -EFAULT;
+		t64 = timespec_to_timespec64(t);
+		if (!timespec64_valid(&t64))
+			return -EINVAL;
+		if (flags & TIMER_ABSTIME)
+			rmtp = NULL;
+		current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+		current->restart_block.nanosleep.compat_rmtp = rmtp;
+		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
+					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+					 which_clock);
+	default:
+		return -EINVAL;
+	}
 }
 #endif
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index f39ed4bdcc5a..b729e1c0b57d 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -49,6 +49,7 @@
 #include <linux/workqueue.h>
 #include <linux/export.h>
 #include <linux/hashtable.h>
+#include <linux/compat.h>
 
 #include "timekeeping.h"
 #include "posix-timers.h"
@@ -1054,25 +1055,40 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		return -EINVAL;
 	if (flags & TIMER_ABSTIME)
 		rmtp = NULL;
+	current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
 	current->restart_block.nanosleep.rmtp = rmtp;
 
 	return kc->nsleep(which_clock, flags, &t64);
 }
 
-/*
- * This will restart clock_nanosleep. This is required only by
- * compat_clock_nanosleep_restart for now.
- */
-long clock_nanosleep_restart(struct restart_block *restart_block)
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
 {
-	clockid_t which_clock = restart_block->nanosleep.clockid;
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 t64;
+	struct timespec t;
 
-	if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
+	if (!kc)
 		return -EINVAL;
+	if (!kc->nsleep)
+		return -ENANOSLEEP_NOTSUP;
+
+	if (compat_get_timespec(&t, rqtp))
+		return -EFAULT;
 
-	return kc->nsleep_restart(restart_block);
+	t64 = timespec_to_timespec64(t);
+	if (!timespec64_valid(&t64))
+		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+	current->restart_block.nanosleep.compat_rmtp = rmtp;
+
+	return kc->nsleep(which_clock, flags, &t64);
 }
+#endif
 
 static const struct k_clock clock_realtime = {
 	.clock_getres		= posix_get_hrtimer_res,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/16] {clock_,}nanosleep(2): merge timespec copyout logics into a new helper
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (4 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:07     ` [tip:timers/core] hrtimers/posix-timers: Merge nanosleep " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 08/16] kill ->nsleep_restart() Al Viro
                     ` (10 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/hrtimer.h        |  2 ++
 kernel/time/alarmtimer.c       | 10 +---------
 kernel/time/hrtimer.c          | 24 +++++++++++++++---------
 kernel/time/posix-cpu-timers.c | 13 ++-----------
 4 files changed, 20 insertions(+), 29 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index b80c34f6fd4b..38b968f3df4e 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -452,6 +452,8 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
 }
 
 /* Precise sleep: */
+
+extern int nanosleep_copyout(struct restart_block *, struct timespec *);
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 868083ae7434..80154e795535 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -721,15 +721,7 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-#ifdef CONFIG_COMPAT
-		if (restart->nanosleep.kind == 2) {
-			if (compat_put_timespec(&rmt,
-						restart->nanosleep.compat_rmtp))
-				return -EFAULT;
-		} else
-#endif
-		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
-			return -EFAULT;
+		return nanosleep_copyout(restart, &rmt);
 	}
 	return -ERESTART_RESTARTBLOCK;
 }
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 5534606e3985..6c19995e977e 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1440,6 +1440,20 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
+int nanosleep_copyout(struct restart_block *restart, struct timespec *ts)
+{
+	BUG_ON(!restart->nanosleep.kind);
+#ifdef CONFIG_COMPAT
+	if (restart->nanosleep.kind == 2) {
+		if (compat_put_timespec(ts, restart->nanosleep.compat_rmtp))
+			return -EFAULT;
+	} else
+#endif
+	if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec)))
+		return -EFAULT;
+	return -ERESTART_RESTARTBLOCK;
+}
+
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
 	struct restart_block *restart;
@@ -1470,15 +1484,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-#ifdef CONFIG_COMPAT
-		if (restart->nanosleep.kind == 2) {
-			if (compat_put_timespec(&rmt,
-						restart->nanosleep.compat_rmtp))
-				return -EFAULT;
-		} else
-#endif
-		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
-			return -EFAULT;
+		return nanosleep_copyout(restart, &rmt);
 	}
 	return -ERESTART_RESTARTBLOCK;
 }
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index b88bc3fc56c5..ba0d7e34616b 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1312,21 +1312,12 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		 * Report back to the user the time still remaining.
 		 */
 		restart = &current->restart_block;
+		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 		if (restart->nanosleep.kind) {
 			struct timespec ts;
 			ts = timespec64_to_timespec(it.it_value);
-#ifdef CONFIG_COMPAT
-			if (restart->nanosleep.kind == 2) {
-				if (compat_put_timespec(&ts,
-						restart->nanosleep.compat_rmtp))
-					return -EFAULT;
-			} else
-#endif
-			if (copy_to_user(restart->nanosleep.rmtp, &ts,
-					sizeof(ts)))
-				return -EFAULT;
+			error = nanosleep_copyout(restart, &ts);
 		}
-		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 
 	return error;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/16] kill ->nsleep_restart()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (5 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 07/16] {clock_,}nanosleep(2): merge timespec copyout logics into a new helper Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:08     ` [tip:timers/core] posix-timers: Kill ->nsleep_restart() tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 09/16] move adjtimex-related compat syscalls to native counterparts Al Viro
                     ` (9 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/hrtimer.h        | 1 -
 kernel/time/hrtimer.c          | 2 +-
 kernel/time/posix-cpu-timers.c | 6 ------
 kernel/time/posix-timers.c     | 4 ----
 kernel/time/posix-timers.h     | 1 -
 5 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 38b968f3df4e..d83b7ed1cb0e 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -457,7 +457,6 @@ extern int nanosleep_copyout(struct restart_block *, struct timespec *);
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
-extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
 
 extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
 				 struct task_struct *tsk);
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 6c19995e977e..5dd4b3a34495 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1489,7 +1489,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 	return -ERESTART_RESTARTBLOCK;
 }
 
-long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+static long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
 	struct hrtimer_sleeper t;
 	int ret;
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ba0d7e34616b..f6c5f77b944d 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1385,10 +1385,6 @@ static int process_cpu_nsleep(const clockid_t which_clock, int flags,
 {
 	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
 }
-static long process_cpu_nsleep_restart(struct restart_block *restart_block)
-{
-	return -EINVAL;
-}
 static int thread_cpu_clock_getres(const clockid_t which_clock,
 				   struct timespec64 *tp)
 {
@@ -1411,7 +1407,6 @@ const struct k_clock clock_posix_cpu = {
 	.clock_get	= posix_cpu_clock_get,
 	.timer_create	= posix_cpu_timer_create,
 	.nsleep		= posix_cpu_nsleep,
-	.nsleep_restart	= posix_cpu_nsleep_restart,
 	.timer_set	= posix_cpu_timer_set,
 	.timer_del	= posix_cpu_timer_del,
 	.timer_get	= posix_cpu_timer_get,
@@ -1423,7 +1418,6 @@ const struct k_clock clock_process = {
 	.clock_get	= process_cpu_clock_get,
 	.timer_create	= process_cpu_timer_create,
 	.nsleep		= process_cpu_nsleep,
-	.nsleep_restart	= process_cpu_nsleep_restart,
 };
 
 const struct k_clock clock_thread = {
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index b729e1c0b57d..922acf713cc0 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1096,7 +1096,6 @@ static const struct k_clock clock_realtime = {
 	.clock_set		= posix_clock_realtime_set,
 	.clock_adj		= posix_clock_realtime_adj,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1112,7 +1111,6 @@ static const struct k_clock clock_monotonic = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_ktime_get_ts,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1143,7 +1141,6 @@ static const struct k_clock clock_tai = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_get_tai,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1159,7 +1156,6 @@ static const struct k_clock clock_boottime = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_get_boottime,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h
index bfd9e15c6ce0..5e69bb85629f 100644
--- a/kernel/time/posix-timers.h
+++ b/kernel/time/posix-timers.h
@@ -11,7 +11,6 @@ struct k_clock {
 	int	(*timer_create)(struct k_itimer *timer);
 	int	(*nsleep)(const clockid_t which_clock, int flags,
 			  struct timespec64 *);
-	long	(*nsleep_restart)(struct restart_block *restart_block);
 	int	(*timer_set)(struct k_itimer *timr, int flags,
 			     struct itimerspec64 *new_setting,
 			     struct itimerspec64 *old_setting);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/16] move adjtimex-related compat syscalls to native counterparts
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (6 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 08/16] kill ->nsleep_restart() Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:08     ` [tip:timers/core] ntp: Move adjtimex related " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 10/16] take compat timer_settime(2) to native one Al Viro
                     ` (8 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Get rid of set_fs() mess and sanitize compat_{get,put}_timex(),
while we are at it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/compat.h     |   4 ++
 kernel/compat.c            | 141 +++++++++++++++++----------------------------
 kernel/time/posix-stubs.c  |   2 +
 kernel/time/posix-timers.c |  27 +++++++++
 kernel/time/time.c         |  24 +++++++-
 5 files changed, 108 insertions(+), 90 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index 1c5f3152cbb5..ecb8dd261d36 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -128,6 +128,10 @@ struct compat_timex {
 	compat_int_t:32; compat_int_t:32; compat_int_t:32;
 };
 
+struct timex;
+int compat_get_timex(struct timex *, const struct compat_timex __user *);
+int compat_put_timex(struct compat_timex __user *, const struct timex *);
+
 #define _COMPAT_NSIG_WORDS	(_COMPAT_NSIG / _COMPAT_NSIG_BPW)
 
 typedef struct {
diff --git a/kernel/compat.c b/kernel/compat.c
index 23afa26f574b..97087b333543 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -30,60 +30,64 @@
 
 #include <linux/uaccess.h>
 
-static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
+int compat_get_timex(struct timex *txc, const struct compat_timex __user *utp)
 {
-	memset(txc, 0, sizeof(struct timex));
-
-	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
-			__get_user(txc->modes, &utp->modes) ||
-			__get_user(txc->offset, &utp->offset) ||
-			__get_user(txc->freq, &utp->freq) ||
-			__get_user(txc->maxerror, &utp->maxerror) ||
-			__get_user(txc->esterror, &utp->esterror) ||
-			__get_user(txc->status, &utp->status) ||
-			__get_user(txc->constant, &utp->constant) ||
-			__get_user(txc->precision, &utp->precision) ||
-			__get_user(txc->tolerance, &utp->tolerance) ||
-			__get_user(txc->time.tv_sec, &utp->time.tv_sec) ||
-			__get_user(txc->time.tv_usec, &utp->time.tv_usec) ||
-			__get_user(txc->tick, &utp->tick) ||
-			__get_user(txc->ppsfreq, &utp->ppsfreq) ||
-			__get_user(txc->jitter, &utp->jitter) ||
-			__get_user(txc->shift, &utp->shift) ||
-			__get_user(txc->stabil, &utp->stabil) ||
-			__get_user(txc->jitcnt, &utp->jitcnt) ||
-			__get_user(txc->calcnt, &utp->calcnt) ||
-			__get_user(txc->errcnt, &utp->errcnt) ||
-			__get_user(txc->stbcnt, &utp->stbcnt))
+	struct compat_timex tx32;
+
+	if (copy_from_user(&tx32, utp, sizeof(struct compat_timex)))
 		return -EFAULT;
 
+	txc->modes = tx32.modes;
+	txc->offset = tx32.offset;
+	txc->freq = tx32.freq;
+	txc->maxerror = tx32.maxerror;
+	txc->esterror = tx32.esterror;
+	txc->status = tx32.status;
+	txc->constant = tx32.constant;
+	txc->precision = tx32.precision;
+	txc->tolerance = tx32.tolerance;
+	txc->time.tv_sec = tx32.time.tv_sec;
+	txc->time.tv_usec = tx32.time.tv_usec;
+	txc->tick = tx32.tick;
+	txc->ppsfreq = tx32.ppsfreq;
+	txc->jitter = tx32.jitter;
+	txc->shift = tx32.shift;
+	txc->stabil = tx32.stabil;
+	txc->jitcnt = tx32.jitcnt;
+	txc->calcnt = tx32.calcnt;
+	txc->errcnt = tx32.errcnt;
+	txc->stbcnt = tx32.stbcnt;
+
 	return 0;
 }
 
-static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
-{
-	if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
-			__put_user(txc->modes, &utp->modes) ||
-			__put_user(txc->offset, &utp->offset) ||
-			__put_user(txc->freq, &utp->freq) ||
-			__put_user(txc->maxerror, &utp->maxerror) ||
-			__put_user(txc->esterror, &utp->esterror) ||
-			__put_user(txc->status, &utp->status) ||
-			__put_user(txc->constant, &utp->constant) ||
-			__put_user(txc->precision, &utp->precision) ||
-			__put_user(txc->tolerance, &utp->tolerance) ||
-			__put_user(txc->time.tv_sec, &utp->time.tv_sec) ||
-			__put_user(txc->time.tv_usec, &utp->time.tv_usec) ||
-			__put_user(txc->tick, &utp->tick) ||
-			__put_user(txc->ppsfreq, &utp->ppsfreq) ||
-			__put_user(txc->jitter, &utp->jitter) ||
-			__put_user(txc->shift, &utp->shift) ||
-			__put_user(txc->stabil, &utp->stabil) ||
-			__put_user(txc->jitcnt, &utp->jitcnt) ||
-			__put_user(txc->calcnt, &utp->calcnt) ||
-			__put_user(txc->errcnt, &utp->errcnt) ||
-			__put_user(txc->stbcnt, &utp->stbcnt) ||
-			__put_user(txc->tai, &utp->tai))
+int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc)
+{
+	struct compat_timex tx32;
+
+	memset(&tx32, 0, sizeof(struct compat_timex));
+	tx32.modes = txc->modes;
+	tx32.offset = txc->offset;
+	tx32.freq = txc->freq;
+	tx32.maxerror = txc->maxerror;
+	tx32.esterror = txc->esterror;
+	tx32.status = txc->status;
+	tx32.constant = txc->constant;
+	tx32.precision = txc->precision;
+	tx32.tolerance = txc->tolerance;
+	tx32.time.tv_sec = txc->time.tv_sec;
+	tx32.time.tv_usec = txc->time.tv_usec;
+	tx32.tick = txc->tick;
+	tx32.ppsfreq = txc->ppsfreq;
+	tx32.jitter = txc->jitter;
+	tx32.shift = txc->shift;
+	tx32.stabil = txc->stabil;
+	tx32.jitcnt = txc->jitcnt;
+	tx32.calcnt = txc->calcnt;
+	tx32.errcnt = txc->errcnt;
+	tx32.stbcnt = txc->stbcnt;
+	tx32.tai = txc->tai;
+	if (copy_to_user(utp, &tx32, sizeof(struct compat_timex)))
 		return -EFAULT;
 	return 0;
 }
@@ -705,29 +709,6 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
 	return err;
 }
 
-COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
-		       struct compat_timex __user *, utp)
-{
-	struct timex txc;
-	mm_segment_t oldfs;
-	int err, ret;
-
-	err = compat_get_timex(&txc, utp);
-	if (err)
-		return err;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
-	set_fs(oldfs);
-
-	err = compat_put_timex(utp, &txc);
-	if (err)
-		return err;
-
-	return ret;
-}
-
 COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 		       struct compat_timespec __user *, tp)
 {
@@ -944,24 +925,6 @@ COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
 
 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
 
-COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
-{
-	struct timex txc;
-	int err, ret;
-
-	err = compat_get_timex(&txc, utp);
-	if (err)
-		return err;
-
-	ret = do_adjtimex(&txc);
-
-	err = compat_put_timex(utp, &txc);
-	if (err)
-		return err;
-
-	return ret;
-}
-
 #ifdef CONFIG_NUMA
 COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
 		       compat_uptr_t __user *, pages32,
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 2fe2322d1243..9b1c8f71d164 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -28,6 +28,7 @@ asmlinkage long sys_ni_posix_timers(void)
 }
 
 #define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
+#define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
 
 SYS_NI(timer_create);
 SYS_NI(timer_gettime);
@@ -40,6 +41,7 @@ SYS_NI(setitimer);
 #ifdef __ARCH_WANT_SYS_ALARM
 SYS_NI(alarm);
 #endif
+COMPAT_SYS_NI(clock_adjtime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 922acf713cc0..d08a2fdeabf9 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1003,6 +1003,33 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
 	return err;
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
+		       struct compat_timex __user *, utp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timex ktx;
+	int err;
+
+	if (!kc)
+		return -EINVAL;
+	if (!kc->clock_adj)
+		return -EOPNOTSUPP;
+
+	err = compat_get_timex(&ktx, utp);
+	if (err)
+		return err;
+
+	err = kc->clock_adj(which_clock, &ktx);
+
+	if (err >= 0)
+		err = compat_put_timex(utp, &ktx);
+
+	return err;
+}
+#endif
+
 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 		struct timespec __user *, tp)
 {
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 49c73c6ed648..400662f16c5a 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -39,6 +39,7 @@
 #include <linux/ptrace.h>
 
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 #include <asm/unistd.h>
 
 #include <generated/timeconst.h>
@@ -224,12 +225,33 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
 	 * structure. But bear in mind that the structures
 	 * may change
 	 */
-	if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
+	if (copy_from_user(&txc, txc_p, sizeof(struct timex)))
 		return -EFAULT;
 	ret = do_adjtimex(&txc);
 	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
+{
+	struct timex txc;
+	int err, ret;
+
+	err = compat_get_timex(&txc, utp);
+	if (err)
+		return err;
+
+	ret = do_adjtimex(&txc);
+
+	err = compat_put_timex(utp, &txc);
+	if (err)
+		return err;
+
+	return ret;
+}
+#endif
+
 /*
  * Convert jiffies to milliseconds and back.
  *
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/16] take compat timer_settime(2) to native one
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (7 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 09/16] move adjtimex-related compat syscalls to native counterparts Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:09     ` [tip:timers/core] posix-timers: Take " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 11/16] take compat timer_gettime(2) " Al Viro
                     ` (7 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

... and get rid of set_fs() in there

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c            | 23 -------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 83 ++++++++++++++++++++++++++++++++++------------
 3 files changed, 62 insertions(+), 45 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 97087b333543..df39e2e00c47 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -635,29 +635,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
-		       struct compat_itimerspec __user *, new,
-		       struct compat_itimerspec __user *, old)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct itimerspec newts, oldts;
-
-	if (!new)
-		return -EINVAL;
-	if (get_compat_itimerspec(&newts, new))
-		return -EFAULT;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_settime(timer_id, flags,
-				(struct itimerspec __user *) &newts,
-				(struct itimerspec __user *) &oldts);
-	set_fs(oldfs);
-	if (!err && old && put_compat_itimerspec(old, &oldts))
-		return -EFAULT;
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 		       struct compat_itimerspec __user *, setting)
 {
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 9b1c8f71d164..e65c468c20b5 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -42,6 +42,7 @@ SYS_NI(setitimer);
 SYS_NI(alarm);
 #endif
 COMPAT_SYS_NI(clock_adjtime);
+COMPAT_SYS_NI(timer_settime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index d08a2fdeabf9..c1564486ad59 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -806,28 +806,17 @@ int common_timer_set(struct k_itimer *timr, int flags,
 	return 0;
 }
 
-/* Set a POSIX.1b interval timer */
-SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
-		const struct itimerspec __user *, new_setting,
-		struct itimerspec __user *, old_setting)
+static int do_timer_settime(timer_t timer_id, int flags,
+		struct itimerspec64 *new_spec64,
+		struct itimerspec64 *old_spec64)
 {
-	struct itimerspec64 new_spec64, old_spec64;
-	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
-	struct itimerspec new_spec, old_spec;
 	struct k_itimer *timr;
 	unsigned long flag;
 	const struct k_clock *kc;
 	int error = 0;
 
-	if (!new_setting)
-		return -EINVAL;
-
-	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
-		return -EFAULT;
-	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
-
-	if (!timespec64_valid(&new_spec64.it_interval) ||
-	    !timespec64_valid(&new_spec64.it_value))
+	if (!timespec64_valid(&new_spec64->it_interval) ||
+	    !timespec64_valid(&new_spec64->it_value))
 		return -EINVAL;
 retry:
 	timr = lock_timer(timer_id, &flag);
@@ -838,22 +827,72 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
 	if (WARN_ON_ONCE(!kc || !kc->timer_set))
 		error = -EINVAL;
 	else
-		error = kc->timer_set(timr, flags, &new_spec64, rtn);
+		error = kc->timer_set(timr, flags, new_spec64, old_spec64);
 
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
-		rtn = NULL;	// We already got the old time...
+		old_spec64 = NULL;	// We already got the old time...
 		goto retry;
 	}
 
-	old_spec = itimerspec64_to_itimerspec(&old_spec64);
-	if (old_setting && !error &&
-	    copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
-		error = -EFAULT;
+	return error;
+}
+
+/* Set a POSIX.1b interval timer */
+SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
+		const struct itimerspec __user *, new_setting,
+		struct itimerspec __user *, old_setting)
+{
+	struct itimerspec64 new_spec64, old_spec64;
+	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
+	struct itimerspec new_spec;
+	int error = 0;
+
+	if (!new_setting)
+		return -EINVAL;
+
+	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
+		return -EFAULT;
+	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
+
+	error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
+	if (!error && old_setting) {
+		struct itimerspec old_spec;
+		old_spec = itimerspec64_to_itimerspec(&old_spec64);
+		if (copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
+			error = -EFAULT;
+	}
 
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
+		       struct compat_itimerspec __user *, new,
+		       struct compat_itimerspec __user *, old)
+{
+	struct itimerspec64 new_spec64, old_spec64;
+	struct itimerspec64 *rtn = old ? &old_spec64 : NULL;
+	struct itimerspec new_spec;
+	int error = 0;
+
+	if (!new)
+		return -EINVAL;
+	if (get_compat_itimerspec(&new_spec, new))
+		return -EFAULT;
+
+	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
+	error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
+	if (!error && old) {
+		struct itimerspec old_spec;
+		old_spec = itimerspec64_to_itimerspec(&old_spec64);
+		if (put_compat_itimerspec(old, &old_spec))
+			error = -EFAULT;
+	}
+	return error;
+}
+#endif
+
 int common_timer_del(struct k_itimer *timer)
 {
 	const struct k_clock *kc = timer->kclock;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 11/16] take compat timer_gettime(2) to native one
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (8 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 10/16] take compat timer_settime(2) to native one Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:09     ` [tip:timers/core] posix-timers: Take " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 12/16] move compat itimer syscalls to native ones Al Viro
                     ` (6 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

... and get rid of set_fs() in there

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c            | 17 -----------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 44 +++++++++++++++++++++++++++++++++++---------
 3 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index df39e2e00c47..1fb8cf7e691e 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -635,23 +635,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
-		       struct compat_itimerspec __user *, setting)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct itimerspec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_gettime(timer_id,
-				(struct itimerspec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && put_compat_itimerspec(setting, &ts))
-		return -EFAULT;
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
 		       struct compat_timespec __user *, tp)
 {
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index e65c468c20b5..c6d3cde2edc6 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -43,6 +43,7 @@ SYS_NI(alarm);
 #endif
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
+COMPAT_SYS_NI(timer_gettime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index c1564486ad59..489ef1b6cd65 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -689,11 +689,9 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
 }
 
 /* Get the time remaining on a POSIX.1b interval timer. */
-SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
-		struct itimerspec __user *, setting)
+static int do_timer_gettime(timer_t timer_id,
+		struct itimerspec64 *setting)
 {
-	struct itimerspec64 cur_setting64;
-	struct itimerspec cur_setting;
 	struct k_itimer *timr;
 	const struct k_clock *kc;
 	unsigned long flags;
@@ -703,21 +701,49 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 	if (!timr)
 		return -EINVAL;
 
-	memset(&cur_setting64, 0, sizeof(cur_setting64));
+	memset(setting, 0, sizeof(*setting));
 	kc = timr->kclock;
 	if (WARN_ON_ONCE(!kc || !kc->timer_get))
 		ret = -EINVAL;
 	else
-		kc->timer_get(timr, &cur_setting64);
+		kc->timer_get(timr, setting);
 
 	unlock_timer(timr, flags);
+	return ret;
+}
 
-	cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
-	if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
-		return -EFAULT;
+/* Get the time remaining on a POSIX.1b interval timer. */
+SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
+		struct itimerspec __user *, setting)
+{
+	struct itimerspec64 cur_setting64;
 
+	int ret = do_timer_gettime(timer_id, &cur_setting64);
+	if (!ret) {
+		struct itimerspec cur_setting;
+		cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
+		if (copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
+		       struct compat_itimerspec __user *, setting)
+{
+	struct itimerspec64 cur_setting64;
+
+	int ret = do_timer_gettime(timer_id, &cur_setting64);
+	if (!ret) {
+		struct itimerspec cur_setting;
+		cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
+		if (put_compat_itimerspec(setting, &cur_setting))
+			ret = -EFAULT;
+	}
 	return ret;
 }
+#endif
 
 /*
  * Get the number of overruns of a POSIX.1b interval timer.  This is to
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 12/16] move compat itimer syscalls to native ones
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (9 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 11/16] take compat timer_gettime(2) " Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:10     ` [tip:timers/core] itimers: Move " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 13/16] clock_gettime/clock_settime/clock_getres: move to native syscalls Al Viro
                     ` (5 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

get rid of set_fs(), sanitize compat copyin/copyout.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 include/linux/compat.h    |  4 +++
 kernel/compat.c           | 71 +++++++++++------------------------------------
 kernel/time/itimer.c      | 36 ++++++++++++++++++++++++
 kernel/time/posix-stubs.c |  2 ++
 4 files changed, 58 insertions(+), 55 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index ecb8dd261d36..425563c7647b 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -94,6 +94,10 @@ struct compat_itimerval {
 	struct compat_timeval	it_value;
 };
 
+struct itimerval;
+int get_compat_itimerval(struct itimerval *, const struct compat_itimerval __user *);
+int put_compat_itimerval(struct compat_itimerval __user *, const struct itimerval *);
+
 struct compat_tms {
 	compat_clock_t		tms_utime;
 	compat_clock_t		tms_stime;
diff --git a/kernel/compat.c b/kernel/compat.c
index 1fb8cf7e691e..61e3be4cbd2a 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -217,65 +217,26 @@ int compat_convert_timespec(struct timespec __user **kts,
 	return 0;
 }
 
-static inline long get_compat_itimerval(struct itimerval *o,
-		struct compat_itimerval __user *i)
+int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
 {
-	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
-		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
-		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
-		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
-}
-
-static inline long put_compat_itimerval(struct compat_itimerval __user *o,
-		struct itimerval *i)
-{
-	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
-		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
-		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
-		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
-}
-
-asmlinkage long sys_ni_posix_timers(void);
-
-COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
-		struct compat_itimerval __user *, it)
-{
-	struct itimerval kit;
-	int error;
-
-	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
-		return sys_ni_posix_timers();
-
-	error = do_getitimer(which, &kit);
-	if (!error && put_compat_itimerval(it, &kit))
-		error = -EFAULT;
-	return error;
+	struct compat_itimerval v32;
+	if (copy_from_user(&v32, i, sizeof(struct compat_itimerval)))
+		return -EFAULT;
+	o->it_interval.tv_sec = v32.it_interval.tv_sec;
+	o->it_interval.tv_usec = v32.it_interval.tv_usec;
+	o->it_value.tv_sec = v32.it_value.tv_sec;
+	o->it_value.tv_usec = v32.it_value.tv_usec;
+	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
-		struct compat_itimerval __user *, in,
-		struct compat_itimerval __user *, out)
+int put_compat_itimerval(struct compat_itimerval __user *o, const struct itimerval *i)
 {
-	struct itimerval kin, kout;
-	int error;
-
-	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
-		return sys_ni_posix_timers();
-
-	if (in) {
-		if (get_compat_itimerval(&kin, in))
-			return -EFAULT;
-	} else
-		memset(&kin, 0, sizeof(kin));
-
-	error = do_setitimer(which, &kin, out ? &kout : NULL);
-	if (error || !out)
-		return error;
-	if (put_compat_itimerval(out, &kout))
-		return -EFAULT;
-	return 0;
+	struct compat_itimerval v32;
+	v32.it_interval.tv_sec = i->it_interval.tv_sec;
+	v32.it_interval.tv_usec = i->it_interval.tv_usec;
+	v32.it_value.tv_sec = i->it_value.tv_sec;
+	v32.it_value.tv_usec = i->it_value.tv_usec;
+	return copy_to_user(o, &v32, sizeof(struct compat_itimerval)) ? -EFAULT : 0;
 }
 
 static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c
index 087d6a1279b8..b23c48dde3da 100644
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -15,6 +15,7 @@
 #include <linux/posix-timers.h>
 #include <linux/hrtimer.h>
 #include <trace/events/timer.h>
+#include <linux/compat.h>
 
 #include <linux/uaccess.h>
 
@@ -116,6 +117,18 @@ SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value)
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
+		struct compat_itimerval __user *, it)
+{
+	struct itimerval kit;
+	int error = do_getitimer(which, &kit);
+	if (!error && put_compat_itimerval(it, &kit))
+		error = -EFAULT;
+	return error;
+}
+#endif
+
 
 /*
  * The timer is automagically restarted, when interval != 0
@@ -294,3 +307,26 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
 		return -EFAULT;
 	return 0;
 }
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
+		struct compat_itimerval __user *, in,
+		struct compat_itimerval __user *, out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_compat_itimerval(&kin, in))
+			return -EFAULT;
+	} else
+		memset(&kin, 0, sizeof(kin));
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+	if (put_compat_itimerval(out, &kout))
+		return -EFAULT;
+	return 0;
+}
+#endif
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c6d3cde2edc6..369df2f9a9ff 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -44,6 +44,8 @@ SYS_NI(alarm);
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
 COMPAT_SYS_NI(timer_gettime);
+COMPAT_SYS_NI(getitimer);
+COMPAT_SYS_NI(setitimer);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 13/16] clock_gettime/clock_settime/clock_getres: move to native syscalls
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (10 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 12/16] move compat itimer syscalls to native ones Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:10     ` [tip:timers/core] posix-timers: Move compat versions of clock_gettime/settime/getres tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 14/16] timer_create(): move compat to native, get rid of set_fs() Al Viro
                     ` (4 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c            | 51 -----------------------------------
 kernel/time/posix-stubs.c  | 52 ++++++++++++++++++++++++++++++++++++
 kernel/time/posix-timers.c | 66 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 114 insertions(+), 55 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 61e3be4cbd2a..e19ea2f06212 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -596,57 +596,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	if (compat_get_timespec(&ts, tp))
-		return -EFAULT;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_settime(which_clock,
-				(struct timespec __user *) &ts);
-	set_fs(oldfs);
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_gettime(which_clock,
-				(struct timespec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && compat_put_timespec(&ts, tp))
-		return -EFAULT;
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_getres(which_clock,
-			       (struct timespec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && tp && compat_put_timespec(&ts, tp))
-		return -EFAULT;
-	return err;
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 369df2f9a9ff..ce45ab06fb3e 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -135,6 +135,58 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 }
 
 #ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
+		struct compat_timespec __user *, tp)
+{
+	struct timespec64 new_tp64;
+	struct timespec new_tp;
+
+	if (which_clock != CLOCK_REALTIME)
+		return -EINVAL;
+	if (compat_get_timespec(&new_tp, tp))
+		return -EFAULT;
+
+	new_tp64 = timespec_to_timespec64(new_tp);
+	return do_sys_settimeofday64(&new_tp64, NULL);
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
+		struct compat_timespec __user *,tp)
+{
+	struct timespec64 kernel_tp64;
+	struct timespec kernel_tp;
+
+	switch (which_clock) {
+	case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break;
+	case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break;
+	case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break;
+	default: return -EINVAL;
+	}
+
+	kernel_tp = timespec64_to_timespec(kernel_tp64);
+	if (compat_put_timespec(&kernel_tp, tp))
+		return -EFAULT;
+	return 0;
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct compat_timespec __user *, tp)
+{
+	struct timespec rtn_tp = {
+		.tv_sec = 0,
+		.tv_nsec = hrtimer_resolution,
+	};
+
+	switch (which_clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+	case CLOCK_BOOTTIME:
+		if (compat_put_timespec(&rtn_tp, tp))
+			return -EFAULT;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 		       struct compat_timespec __user *, rqtp,
 		       struct compat_timespec __user *, rmtp)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 489ef1b6cd65..5c2b566f1a5c 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1068,8 +1068,66 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
 	return err;
 }
 
+SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
+		struct timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 rtn_tp64;
+	struct timespec rtn_tp;
+	int error;
+
+	if (!kc)
+		return -EINVAL;
+
+	error = kc->clock_getres(which_clock, &rtn_tp64);
+	rtn_tp = timespec64_to_timespec(rtn_tp64);
+
+	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+		error = -EFAULT;
+
+	return error;
+}
+
 #ifdef CONFIG_COMPAT
 
+COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 new_tp64;
+	struct timespec new_tp;
+
+	if (!kc || !kc->clock_set)
+		return -EINVAL;
+
+	if (compat_get_timespec(&new_tp, tp))
+		return -EFAULT;
+
+	new_tp64 = timespec_to_timespec64(new_tp);
+
+	return kc->clock_set(which_clock, &new_tp64);
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 kernel_tp64;
+	struct timespec kernel_tp;
+	int error;
+
+	if (!kc)
+		return -EINVAL;
+
+	error = kc->clock_get(which_clock, &kernel_tp64);
+	kernel_tp = timespec64_to_timespec(kernel_tp64);
+
+	if (!error && compat_put_timespec(&kernel_tp, tp))
+		error = -EFAULT;
+
+	return error;
+}
+
 COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
 		       struct compat_timex __user *, utp)
 {
@@ -1093,10 +1151,9 @@ COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
 
 	return err;
 }
-#endif
 
-SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
-		struct timespec __user *, tp)
+COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
 {
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec64 rtn_tp64;
@@ -1109,11 +1166,12 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 	error = kc->clock_getres(which_clock, &rtn_tp64);
 	rtn_tp = timespec64_to_timespec(rtn_tp64);
 
-	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+	if (!error && tp && compat_put_timespec(&rtn_tp, tp))
 		error = -EFAULT;
 
 	return error;
 }
+#endif
 
 /*
  * nanosleep for monotonic and realtime clocks
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 14/16] timer_create(): move compat to native, get rid of set_fs()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (11 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 13/16] clock_gettime/clock_settime/clock_getres: move to native syscalls Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:11     ` [tip:timers/core] posix-timers: Move compat_timer_create() " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 15/16] time()/stime(): move compat to native Al Viro
                     ` (3 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c            | 18 ---------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 57 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 41 insertions(+), 35 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index e19ea2f06212..92ba0afafddc 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -578,24 +578,6 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
 	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
-		       struct compat_sigevent __user *, timer_event_spec,
-		       timer_t __user *, created_timer_id)
-{
-	struct sigevent __user *event = NULL;
-
-	if (timer_event_spec) {
-		struct sigevent kevent;
-
-		event = compat_alloc_user_space(sizeof(*event));
-		if (get_compat_sigevent(&kevent, timer_event_spec) ||
-		    copy_to_user(event, &kevent, sizeof(*event)))
-			return -EFAULT;
-	}
-
-	return sys_timer_create(which_clock, event, created_timer_id);
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index ce45ab06fb3e..c0c18701a4da 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -41,6 +41,7 @@ SYS_NI(setitimer);
 #ifdef __ARCH_WANT_SYS_ALARM
 SYS_NI(alarm);
 #endif
+COMPAT_SYS_NI(timer_create);
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
 COMPAT_SYS_NI(timer_gettime);
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 5c2b566f1a5c..014e6ff8982e 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -490,14 +490,13 @@ static int common_timer_create(struct k_itimer *new_timer)
 
 /* Create a POSIX.1b interval timer. */
 
-SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
-		struct sigevent __user *, timer_event_spec,
-		timer_t __user *, created_timer_id)
+static int do_timer_create(clockid_t which_clock,
+		struct sigevent *event,
+		timer_t __user *created_timer_id)
 {
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct k_itimer *new_timer;
 	int error, new_timer_id;
-	sigevent_t event;
 	int it_id_set = IT_ID_NOT_SET;
 
 	if (!kc)
@@ -522,29 +521,25 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 	new_timer->kclock = kc;
 	new_timer->it_overrun = -1;
 
-	if (timer_event_spec) {
-		if (copy_from_user(&event, timer_event_spec, sizeof (event))) {
-			error = -EFAULT;
-			goto out;
-		}
+	if (event) {
 		rcu_read_lock();
-		new_timer->it_pid = get_pid(good_sigevent(&event));
+		new_timer->it_pid = get_pid(good_sigevent(event));
 		rcu_read_unlock();
 		if (!new_timer->it_pid) {
 			error = -EINVAL;
 			goto out;
 		}
+		new_timer->it_sigev_notify     = event->sigev_notify;
+		new_timer->sigq->info.si_signo = event->sigev_signo;
+		new_timer->sigq->info.si_value = event->sigev_value;
 	} else {
-		memset(&event.sigev_value, 0, sizeof(event.sigev_value));
-		event.sigev_notify = SIGEV_SIGNAL;
-		event.sigev_signo = SIGALRM;
-		event.sigev_value.sival_int = new_timer->it_id;
+		new_timer->it_sigev_notify     = SIGEV_SIGNAL;
+		new_timer->sigq->info.si_signo = SIGALRM;
+		memset(&new_timer->sigq->info.si_value, 0, sizeof(sigval_t));
+		new_timer->sigq->info.si_value.sival_int = new_timer->it_id;
 		new_timer->it_pid = get_pid(task_tgid(current));
 	}
 
-	new_timer->it_sigev_notify     = event.sigev_notify;
-	new_timer->sigq->info.si_signo = event.sigev_signo;
-	new_timer->sigq->info.si_value = event.sigev_value;
 	new_timer->sigq->info.si_tid   = new_timer->it_id;
 	new_timer->sigq->info.si_code  = SI_TIMER;
 
@@ -575,6 +570,34 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 	return error;
 }
 
+SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
+		struct sigevent __user *, timer_event_spec,
+		timer_t __user *, created_timer_id)
+{
+	if (timer_event_spec) {
+		sigevent_t event;
+		if (copy_from_user(&event, timer_event_spec, sizeof (event)))
+			return -EFAULT;
+		return do_timer_create(which_clock, &event, created_timer_id);
+	}
+	return do_timer_create(which_clock, NULL, created_timer_id);
+}
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
+		       struct compat_sigevent __user *, timer_event_spec,
+		       timer_t __user *, created_timer_id)
+{
+	if (timer_event_spec) {
+		sigevent_t event;
+		if (get_compat_sigevent(&event, timer_event_spec))
+			return -EFAULT;
+		return do_timer_create(which_clock, &event, created_timer_id);
+	}
+	return do_timer_create(which_clock, NULL, created_timer_id);
+}
+#endif
+
 /*
  * Locking issues: We need to protect the result of the id look up until
  * we get the timer locked down so it is not deleted under us.  The
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 15/16] time()/stime(): move compat to native
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (12 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 14/16] timer_create(): move compat to native, get rid of set_fs() Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:11     ` [tip:timers/core] time: Move compat_time()/stime() " tip-bot for Al Viro
  2017-06-07  8:42   ` [PATCH 16/16] gettimeofday()/settimeofday(): move compat " Al Viro
                     ` (2 subsequent siblings)
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c    | 40 ----------------------------------------
 kernel/time/time.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 92ba0afafddc..a56aa5777987 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -737,46 +737,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 	return ret;
 }
 
-#ifdef __ARCH_WANT_COMPAT_SYS_TIME
-
-/* compat_time_t is a 32 bit "long" and needs to get converted. */
-
-COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
-{
-	compat_time_t i;
-	struct timeval tv;
-
-	do_gettimeofday(&tv);
-	i = tv.tv_sec;
-
-	if (tloc) {
-		if (put_user(i,tloc))
-			return -EFAULT;
-	}
-	force_successful_syscall_return();
-	return i;
-}
-
-COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
-{
-	struct timespec tv;
-	int err;
-
-	if (get_user(tv.tv_sec, tptr))
-		return -EFAULT;
-
-	tv.tv_nsec = 0;
-
-	err = security_settime(&tv, NULL);
-	if (err)
-		return err;
-
-	do_settimeofday(&tv);
-	return 0;
-}
-
-#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
-
 #ifdef CONFIG_NUMA
 COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
 		       compat_uptr_t __user *, pages32,
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 400662f16c5a..1d5ebf6a8d9e 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -100,6 +100,48 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr)
 
 #endif /* __ARCH_WANT_SYS_TIME */
 
+#ifdef CONFIG_COMPAT
+#ifdef __ARCH_WANT_COMPAT_SYS_TIME
+
+/* compat_time_t is a 32 bit "long" and needs to get converted. */
+
+COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
+{
+	compat_time_t i;
+	struct timeval tv;
+
+	do_gettimeofday(&tv);
+	i = tv.tv_sec;
+
+	if (tloc) {
+		if (put_user(i,tloc))
+			return -EFAULT;
+	}
+	force_successful_syscall_return();
+	return i;
+}
+
+COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
+{
+	struct timespec tv;
+	int err;
+
+	if (get_user(tv.tv_sec, tptr))
+		return -EFAULT;
+
+	tv.tv_nsec = 0;
+
+	err = security_settime(&tv, NULL);
+	if (err)
+		return err;
+
+	do_settimeofday(&tv);
+	return 0;
+}
+
+#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
+#endif
+
 SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
 		struct timezone __user *, tz)
 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 16/16] gettimeofday()/settimeofday(): move compat to native
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (13 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 15/16] time()/stime(): move compat to native Al Viro
@ 2017-06-07  8:42   ` Al Viro
  2017-06-13 22:12     ` [tip:timers/core] time: Move compat_gettimeofday()/settimeofday() " tip-bot for Al Viro
  2017-06-12 23:08   ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Thomas Gleixner
  2017-06-13 22:04   ` [tip:timers/core] posix-cpu-timers: Move " tip-bot for Al Viro
  16 siblings, 1 reply; 36+ messages in thread
From: Al Viro @ 2017-06-07  8:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: Thomas Gleixner

From: Al Viro <viro@zeniv.linux.org.uk>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 kernel/compat.c    | 38 --------------------------------------
 kernel/time/time.c | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 38 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index a56aa5777987..40a388994576 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -92,44 +92,6 @@ int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc)
 	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
-		       struct timezone __user *, tz)
-{
-	if (tv) {
-		struct timeval ktv;
-		do_gettimeofday(&ktv);
-		if (compat_put_timeval(&ktv, tv))
-			return -EFAULT;
-	}
-	if (tz) {
-		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
-		       struct timezone __user *, tz)
-{
-	struct timespec64 new_ts;
-	struct timeval user_tv;
-	struct timezone new_tz;
-
-	if (tv) {
-		if (compat_get_timeval(&user_tv, tv))
-			return -EFAULT;
-		new_ts.tv_sec = user_tv.tv_sec;
-		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
-	}
-	if (tz) {
-		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
-			return -EFAULT;
-	}
-
-	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
-}
-
 static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
 {
 	return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 1d5ebf6a8d9e..01dfb07563b6 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -258,6 +258,46 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
 	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
+		       struct timezone __user *, tz)
+{
+	if (tv) {
+		struct timeval ktv;
+		do_gettimeofday(&ktv);
+		if (compat_put_timeval(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
+		       struct timezone __user *, tz)
+{
+	struct timespec64 new_ts;
+	struct timeval user_tv;
+	struct timezone new_tz;
+
+	if (tv) {
+		if (compat_get_timeval(&user_tv, tv))
+			return -EFAULT;
+		new_ts.tv_sec = user_tv.tv_sec;
+		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
+	}
+	if (tz) {
+		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
+}
+#endif
+
 SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
 {
 	struct timex txc;		/* Local copy of parameter */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts
  2017-06-07  8:42   ` [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts Al Viro
@ 2017-06-07 10:07     ` Peter Zijlstra
  2017-06-13 22:06     ` [tip:timers/core] time/posix-timers: Move the compat copyouts to the nanosleep implementations tip-bot for Al Viro
  1 sibling, 0 replies; 36+ messages in thread
From: Peter Zijlstra @ 2017-06-07 10:07 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel, Thomas Gleixner

On Wed, Jun 07, 2017 at 09:42:31AM +0100, Al Viro wrote:
> From: Al Viro <viro@zeniv.linux.org.uk>
> 
> Turn restart_block.nanosleep.{rmtp,compat_rmtp} into a tagged union
> (kind = 1 -> native, kind = 2 -> compat, kind = 0 -> nothing) and
> make the places doing actual copyout handle compat as well as
> native (that will become a helper in the next commit).  Result:
> compat wrappers, messing with reassignments, etc. are gone.

I found something like the below on top slightly easier to read. Ignore
if hated..

---
 include/linux/restart_block.h  | 10 +++++++++-
 kernel/time/alarmtimer.c       |  2 +-
 kernel/time/hrtimer.c          | 23 +++++++++++++++--------
 kernel/time/posix-cpu-timers.c |  2 +-
 kernel/time/posix-stubs.c      |  4 ++--
 kernel/time/posix-timers.c     |  4 ++--
 6 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
index 4509944bd953..0834e4a8ce69 100644
--- a/include/linux/restart_block.h
+++ b/include/linux/restart_block.h
@@ -11,6 +11,14 @@ struct timespec;
 struct compat_timespec;
 struct pollfd;
 
+enum timespec_type {
+	tt_nothing = 0,
+	tt_native  = 1,
+#ifdef CONFIG_COMPAT
+	tt_compat  = 2,
+#endif
+};
+
 /*
  * System call restart block.
  */
@@ -29,7 +37,7 @@ struct restart_block {
 		/* For nanosleep */
 		struct {
 			clockid_t clockid;
-			int kind;
+			enum timespec_type type;
 			union {
 				struct timespec __user *rmtp;
 #ifdef CONFIG_COMPAT
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 80154e795535..734920be9d4b 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -711,7 +711,7 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 	if (freezing(current))
 		alarmtimer_freezerset(absexp, type);
 	restart = &current->restart_block;
-	if (restart->nanosleep.kind) {
+	if (restart->nanosleep.type) {
 		struct timespec rmt;
 		ktime_t rem;
 
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 5dd4b3a34495..e1e06a8b6c43 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1442,15 +1442,22 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
 int nanosleep_copyout(struct restart_block *restart, struct timespec *ts)
 {
-	BUG_ON(!restart->nanosleep.kind);
+	switch(restart->nanosleep.type) {
 #ifdef CONFIG_COMPAT
-	if (restart->nanosleep.kind == 2) {
+	case tt_compat:
 		if (compat_put_timespec(ts, restart->nanosleep.compat_rmtp))
 			return -EFAULT;
-	} else
+		break;
 #endif
-	if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec)))
-		return -EFAULT;
+	case tt_native:
+		if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec)))
+			return -EFAULT;
+		break;
+
+	case tt_nothing:
+		BUG();
+	}
+
 	return -ERESTART_RESTARTBLOCK;
 }
 
@@ -1477,7 +1484,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 		return 0;
 
 	restart = &current->restart_block;
-	if (restart->nanosleep.kind) {
+	if (restart->nanosleep.type) {
 		struct timespec rmt;
 		ktime_t rem = hrtimer_expires_remaining(&t->timer);
 		if (rem <= 0)
@@ -1549,7 +1556,7 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
-	current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
+	current->restart_block.nanosleep.type = rmtp ? tt_native : tt_nothing;
 	current->restart_block.nanosleep.rmtp = rmtp;
 	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
@@ -1569,7 +1576,7 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
-	current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+	current->restart_block.nanosleep.type = rmtp ? tt_compat : tt_nothing;
 	current->restart_block.nanosleep.compat_rmtp = rmtp;
 	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index f6c5f77b944d..929499e6b4ac 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1313,7 +1313,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		 */
 		restart = &current->restart_block;
 		restart->nanosleep.expires = timespec64_to_ns(rqtp);
-		if (restart->nanosleep.kind) {
+		if (restart->nanosleep.type) {
 			struct timespec ts;
 			ts = timespec64_to_timespec(it.it_value);
 			error = nanosleep_copyout(restart, &ts);
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c0c18701a4da..4b54dcf8d517 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -125,7 +125,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 			return -EINVAL;
 		if (flags & TIMER_ABSTIME)
 			rmtp = NULL;
-		current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
+		current->restart_block.nanosleep.type = rmtp ? tt_native : tt_nothing;
 		current->restart_block.nanosleep.rmtp = rmtp;
 		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
@@ -206,7 +206,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 			return -EINVAL;
 		if (flags & TIMER_ABSTIME)
 			rmtp = NULL;
-		current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+		current->restart_block.nanosleep.type = rmtp ? tt_compat : tt_nothing;
 		current->restart_block.nanosleep.compat_rmtp = rmtp;
 		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 014e6ff8982e..3c85d6762690 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1228,7 +1228,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		return -EINVAL;
 	if (flags & TIMER_ABSTIME)
 		rmtp = NULL;
-	current->restart_block.nanosleep.kind = rmtp ? 1 : 0;
+	current->restart_block.nanosleep.type = rmtp ? tt_native : tt_nothing;
 	current->restart_block.nanosleep.rmtp = rmtp;
 
 	return kc->nsleep(which_clock, flags, &t64);
@@ -1256,7 +1256,7 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 		return -EINVAL;
 	if (flags & TIMER_ABSTIME)
 		rmtp = NULL;
-	current->restart_block.nanosleep.kind = rmtp ? 2 : 0;
+	current->restart_block.nanosleep.type = rmtp ? tt_compat : tt_nothing;
 	current->restart_block.nanosleep.compat_rmtp = rmtp;
 
 	return kc->nsleep(which_clock, flags, &t64);

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (14 preceding siblings ...)
  2017-06-07  8:42   ` [PATCH 16/16] gettimeofday()/settimeofday(): move compat " Al Viro
@ 2017-06-12 23:08   ` Thomas Gleixner
  2017-06-13  7:46     ` Thomas Gleixner
  2017-06-13 22:04   ` [tip:timers/core] posix-cpu-timers: Move " tip-bot for Al Viro
  16 siblings, 1 reply; 36+ messages in thread
From: Thomas Gleixner @ 2017-06-12 23:08 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel

On Wed, 7 Jun 2017, Al Viro wrote:
> @@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
>  
>  		error = -ERESTART_RESTARTBLOCK;
> +		/*
> +		 * Report back to the user the time still remaining.
> +		 */
> +		rmtp = restart->nanosleep.rmtp;
> +		if (rmtp) {
> +			struct timespec ts;
> +			ts = timespec64_to_timespec(it.it_value);
> +			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
> +				return -EFAULT;
> +		}
> +		restart->nanosleep.expires = timespec64_to_ns(rqtp);

Hmm, this looks wrong. But that was wrong before this patch already.

The restart code needs the absolute expiry time of the timer, but in case
of flags != ABSTIME rqtp contains the relative expiry time.

So that want's to be fixed first. Need to figure out what's the least ugly
way to do that. I'll have a look tomorrow.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep()
  2017-06-12 23:08   ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Thomas Gleixner
@ 2017-06-13  7:46     ` Thomas Gleixner
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Gleixner @ 2017-06-13  7:46 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-kernel

On Tue, 13 Jun 2017, Thomas Gleixner wrote:
> On Wed, 7 Jun 2017, Al Viro wrote:
> > @@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
> >  
> >  		error = -ERESTART_RESTARTBLOCK;
> > +		/*
> > +		 * Report back to the user the time still remaining.
> > +		 */
> > +		rmtp = restart->nanosleep.rmtp;
> > +		if (rmtp) {
> > +			struct timespec ts;
> > +			ts = timespec64_to_timespec(it.it_value);
> > +			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
> > +				return -EFAULT;
> > +		}
> > +		restart->nanosleep.expires = timespec64_to_ns(rqtp);
> 
> Hmm, this looks wrong. But that was wrong before this patch already.
> 
> The restart code needs the absolute expiry time of the timer, but in case
> of flags != ABSTIME rqtp contains the relative expiry time.
> 
> So that want's to be fixed first. Need to figure out what's the least ugly
> way to do that. I'll have a look tomorrow.

Misread the code. rqtp is updated with the absolute expiry time when a
signal hits. Though with your changes we can simplify that further and
avoid the whole back and forth timespec conversion.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-cpu-timers: Move copyout of timespec into do_cpu_nanosleep()
  2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
                     ` (15 preceding siblings ...)
  2017-06-12 23:08   ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Thomas Gleixner
@ 2017-06-13 22:04   ` tip-bot for Al Viro
  16 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:04 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, hpa, viro, peterz, mingo, viro, john.stultz, linux-kernel

Commit-ID:  86a9c446c13ecd8793ea8599761322aed125d542
Gitweb:     http://git.kernel.org/tip/86a9c446c13ecd8793ea8599761322aed125d542
Author:     Al Viro <viro@ZenIV.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:26 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:40 +0200

posix-cpu-timers: Move copyout of timespec into do_cpu_nanosleep()

The posix-cpu-timer nanosleep() implementation can be simplified by moving
the copy out of the remaining time to do_cpu_nanosleep() which is shared
between the real nanosleep function and the restart function.

The pointer to the timespec64 which is updated has to be stored in the
restart block anyway. Instead of storing it only in the restart case, store
it before calling do_cpu_nanosleep() and copy the remaining time in the
signal exit path.

[ tglx: Added changelog ]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-1-viro@ZenIV.linux.org.uk

---
 kernel/time/posix-cpu-timers.c | 63 +++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 35 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index cb4a4eb..239fff9 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1226,9 +1226,10 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 }
 
 static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
-			    struct timespec64 *rqtp, struct itimerspec64 *it)
+			    struct timespec64 *rqtp)
 {
 	struct k_itimer timer;
+	struct itimerspec64 it;
 	int error;
 
 	/*
@@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	timer.it_process = current;
 	if (!error) {
 		static struct itimerspec64 zero_it;
+		struct restart_block *restart = &current->restart_block;
+		struct timespec __user *rmtp;
 
-		memset(it, 0, sizeof *it);
-		it->it_value = *rqtp;
+		memset(&it, 0, sizeof it);
+		it.it_value = *rqtp;
 
 		spin_lock_irq(&timer.it_lock);
-		error = posix_cpu_timer_set(&timer, flags, it, NULL);
+		error = posix_cpu_timer_set(&timer, flags, &it, NULL);
 		if (error) {
 			spin_unlock_irq(&timer.it_lock);
 			return error;
@@ -1277,7 +1280,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		 * We were interrupted by a signal.
 		 */
 		*rqtp = ns_to_timespec64(timer.it.cpu.expires);
-		error = posix_cpu_timer_set(&timer, 0, &zero_it, it);
+		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
 		if (!error) {
 			/*
 			 * Timer is now unarmed, deletion can not fail.
@@ -1297,7 +1300,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 			spin_unlock_irq(&timer.it_lock);
 		}
 
-		if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
+		if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
 			/*
 			 * It actually did fire already.
 			 */
@@ -1305,6 +1308,18 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		}
 
 		error = -ERESTART_RESTARTBLOCK;
+		/*
+		 * Report back to the user the time still remaining.
+		 */
+		rmtp = restart->nanosleep.rmtp;
+		if (rmtp) {
+			struct timespec ts;
+
+			ts = timespec64_to_timespec(it.it_value);
+			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
+				return -EFAULT;
+		}
+		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 
 	return error;
@@ -1316,10 +1331,13 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 			    struct timespec64 *rqtp, struct timespec __user *rmtp)
 {
 	struct restart_block *restart_block = &current->restart_block;
-	struct itimerspec64 it;
-	struct timespec ts;
 	int error;
 
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+
+	restart_block->nanosleep.rmtp = rmtp;
+
 	/*
 	 * Diagnose required errors first.
 	 */
@@ -1328,23 +1346,15 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 	     CPUCLOCK_PID(which_clock) == task_pid_vnr(current)))
 		return -EINVAL;
 
-	error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
+	error = do_cpu_nanosleep(which_clock, flags, rqtp);
 
 	if (error == -ERESTART_RESTARTBLOCK) {
 
 		if (flags & TIMER_ABSTIME)
 			return -ERESTARTNOHAND;
-		/*
-		 * Report back to the user the time still remaining.
-		 */
-		ts = timespec64_to_timespec(it.it_value);
-		if (rmtp && copy_to_user(rmtp, &ts, sizeof(*rmtp)))
-			return -EFAULT;
 
 		restart_block->fn = posix_cpu_nsleep_restart;
 		restart_block->nanosleep.clockid = which_clock;
-		restart_block->nanosleep.rmtp = rmtp;
-		restart_block->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 	return error;
 }
@@ -1352,28 +1362,11 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
 	clockid_t which_clock = restart_block->nanosleep.clockid;
-	struct itimerspec64 it;
 	struct timespec64 t;
-	struct timespec tmp;
-	int error;
 
 	t = ns_to_timespec64(restart_block->nanosleep.expires);
 
-	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
-
-	if (error == -ERESTART_RESTARTBLOCK) {
-		struct timespec __user *rmtp = restart_block->nanosleep.rmtp;
-		/*
-		 * Report back to the user the time still remaining.
-		 */
-		 tmp = timespec64_to_timespec(it.it_value);
-		if (rmtp && copy_to_user(rmtp, &tmp, sizeof(*rmtp)))
-			return -EFAULT;
-
-		restart_block->nanosleep.expires = timespec64_to_ns(&t);
-	}
-	return error;
-
+	return do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t);
 }
 
 #define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] alarmtimer: Move copyout and freeze handling into alarmtimer_do_nsleep()
  2017-06-07  8:42   ` [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep() Al Viro
@ 2017-06-13 22:04     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:04 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, linux-kernel, viro, tglx, john.stultz, hpa, viro, peterz

Commit-ID:  15f27ce24cb613e6e01ce27c4094c55e55dde5d4
Gitweb:     http://git.kernel.org/tip/15f27ce24cb613e6e01ce27c4094c55e55dde5d4
Author:     Al Viro <viro@ZenIV.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:27 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:40 +0200

alarmtimer: Move copyout and freeze handling into alarmtimer_do_nsleep()

The alarmtimer nanosleep() implementation can be simplified by moving the
copy out of the remaining time to alarmtimer_do_nsleep() which is shared
between the real nanosleep function and the restart function.

The pointer to the timespec64 which is updated has to be stored in the
restart block anyway. Instead of storing it only in the restart case, store
it before calling alarmtimer_do_nsleep() and copy the remaining time in the
signal exit path.

[ tglx: Added changelog ]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-2-viro@ZenIV.linux.org.uk

---
 kernel/time/alarmtimer.c | 102 +++++++++++++++--------------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index d8a7a7e..ac6e9bc 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -688,8 +688,10 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
  *
  * Sets the alarm timer and sleeps until it is fired or interrupted.
  */
-static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
+static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
+				enum alarmtimer_type type)
 {
+	struct timespec __user *rmtp;
 	alarm->data = (void *)current;
 	do {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -702,36 +704,26 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
 
 	__set_current_state(TASK_RUNNING);
 
-	return (alarm->data == NULL);
-}
-
-
-/**
- * update_rmtp - Update remaining timespec value
- * @exp: expiration time
- * @type: timer type
- * @rmtp: user pointer to remaining timepsec value
- *
- * Helper function that fills in rmtp value with time between
- * now and the exp value
- */
-static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
-			struct timespec __user *rmtp)
-{
-	struct timespec rmt;
-	ktime_t rem;
-
-	rem = ktime_sub(exp, alarm_bases[type].gettime());
-
-	if (rem <= 0)
+	if (!alarm->data)
 		return 0;
-	rmt = ktime_to_timespec(rem);
 
-	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-		return -EFAULT;
+	if (freezing(current))
+		alarmtimer_freezerset(absexp, type);
+	rmtp = current->restart_block.nanosleep.rmtp;
+	if (rmtp) {
+		struct timespec rmt;
+		ktime_t rem;
 
-	return 1;
+		rem = ktime_sub(absexp, alarm_bases[type].gettime());
 
+		if (rem <= 0)
+			return 0;
+		rmt = ktime_to_timespec(rem);
+
+		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+			return -EFAULT;
+	}
+	return -ERESTART_RESTARTBLOCK;
 }
 
 /**
@@ -743,32 +735,12 @@ static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
 static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
 {
 	enum  alarmtimer_type type = restart->nanosleep.clockid;
-	ktime_t exp;
-	struct timespec __user  *rmtp;
+	ktime_t exp = restart->nanosleep.expires;
 	struct alarm alarm;
-	int ret = 0;
 
-	exp = restart->nanosleep.expires;
 	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
 
-	if (alarmtimer_do_nsleep(&alarm, exp))
-		goto out;
-
-	if (freezing(current))
-		alarmtimer_freezerset(exp, type);
-
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(exp, type, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
-
-	/* The other values in restart are already filled in */
-	ret = -ERESTART_RESTARTBLOCK;
-out:
-	return ret;
+	return alarmtimer_do_nsleep(&alarm, exp, type);
 }
 
 /**
@@ -785,11 +757,16 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 			      struct timespec __user *rmtp)
 {
 	enum  alarmtimer_type type = clock2alarm(which_clock);
-	struct restart_block *restart;
+	struct restart_block *restart = &current->restart_block;
 	struct alarm alarm;
 	ktime_t exp;
 	int ret = 0;
 
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+
+	restart->nanosleep.rmtp = rmtp;
+
 	if (!alarmtimer_get_rtcdev())
 		return -ENOTSUPP;
 
@@ -808,32 +785,17 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 		exp = ktime_add(now, exp);
 	}
 
-	if (alarmtimer_do_nsleep(&alarm, exp))
-		goto out;
-
-	if (freezing(current))
-		alarmtimer_freezerset(exp, type);
+	ret = alarmtimer_do_nsleep(&alarm, exp, type);
+	if (ret != -ERESTART_RESTARTBLOCK)
+		return ret;
 
 	/* abs timers don't set remaining time or restart */
-	if (flags == TIMER_ABSTIME) {
-		ret = -ERESTARTNOHAND;
-		goto out;
-	}
-
-	if (rmtp) {
-		ret = update_rmtp(exp, type, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
+	if (flags == TIMER_ABSTIME)
+		return -ERESTARTNOHAND;
 
-	restart = &current->restart_block;
 	restart->fn = alarm_timer_nsleep_restart;
 	restart->nanosleep.clockid = type;
 	restart->nanosleep.expires = exp;
-	restart->nanosleep.rmtp = rmtp;
-	ret = -ERESTART_RESTARTBLOCK;
-
-out:
 	return ret;
 }
 

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] hrtimer_nanosleep(): Pass rmtp in restart_block
  2017-06-07  8:42   ` [PATCH 03/16] hrtimer_nanosleep(): pass rmtp in restart_block Al Viro
@ 2017-06-13 22:05     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:05 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, mingo, john.stultz, viro, peterz, hpa, linux-kernel, viro

Commit-ID:  192a82f9003fe8fabd6088aa646e829225a94c55
Gitweb:     http://git.kernel.org/tip/192a82f9003fe8fabd6088aa646e829225a94c55
Author:     Al Viro <viro@ZenIV.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:28 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:40 +0200

hrtimer_nanosleep(): Pass rmtp in restart_block

Store the pointer to the timespec which gets updated with the remaining
time in the restart block and remove the function argument.

[ tglx: Added changelog ]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-3-viro@ZenIV.linux.org.uk

---
 include/linux/hrtimer.h    |  1 -
 kernel/compat.c            |  6 +++---
 kernel/time/hrtimer.c      | 11 ++++++-----
 kernel/time/posix-stubs.c  |  5 ++++-
 kernel/time/posix-timers.c |  5 ++++-
 5 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 8c5b10e..b80c34f 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -453,7 +453,6 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
 
 /* Precise sleep: */
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
-			      struct timespec __user *rmtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
 extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
diff --git a/kernel/compat.c b/kernel/compat.c
index 933bcb3..cc9ba9d 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -253,9 +253,9 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
 
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep(&tu64,
-				rmtp ? (struct timespec __user *)&rmt : NULL,
-				HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+	current->restart_block.nanosleep.rmtp =
+				rmtp ? (struct timespec __user *)&rmt : NULL;
+	ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 	set_fs(oldfs);
 
 	/*
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index ac053bb..4ae777f 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1503,10 +1503,11 @@ out:
 	return ret;
 }
 
-long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,
+long hrtimer_nanosleep(struct timespec64 *rqtp,
 		       const enum hrtimer_mode mode, const clockid_t clockid)
 {
-	struct restart_block *restart;
+	struct restart_block *restart = &current->restart_block;
+	struct timespec __user *rmtp;
 	struct hrtimer_sleeper t;
 	int ret = 0;
 	u64 slack;
@@ -1526,16 +1527,15 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,
 		goto out;
 	}
 
+	rmtp = restart->nanosleep.rmtp;
 	if (rmtp) {
 		ret = update_rmtp(&t.timer, rmtp);
 		if (ret <= 0)
 			goto out;
 	}
 
-	restart = &current->restart_block;
 	restart->fn = hrtimer_nanosleep_restart;
 	restart->nanosleep.clockid = t.timer.base->clockid;
-	restart->nanosleep.rmtp = rmtp;
 	restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
 
 	ret = -ERESTART_RESTARTBLOCK;
@@ -1557,7 +1557,8 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
-	return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+	current->restart_block.nanosleep.rmtp = rmtp;
+	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
 /*
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c0cd53e..156a5e6 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -115,7 +115,10 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		t64 = timespec_to_timespec64(t);
 		if (!timespec64_valid(&t64))
 			return -EINVAL;
-		return hrtimer_nanosleep(&t64, rmtp, flags & TIMER_ABSTIME ?
+		if (flags & TIMER_ABSTIME)
+			rmtp = NULL;
+		current->restart_block.nanosleep.rmtp = rmtp;
+		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
 					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 					 which_clock);
 	default:
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 58c0f60..1a9f59f 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1043,7 +1043,10 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 static int common_nsleep(const clockid_t which_clock, int flags,
 			 struct timespec64 *tsave, struct timespec __user *rmtp)
 {
-	return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.rmtp = rmtp;
+	return hrtimer_nanosleep(tsave, flags & TIMER_ABSTIME ?
 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 				 which_clock);
 }

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] hrtimer: Move copyout of remaining time to do_nanosleep()
  2017-06-07  8:42   ` [PATCH 04/16] move copyout to do_nanosleel() Al Viro
@ 2017-06-13 22:05     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:05 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, viro, john.stultz, hpa, tglx, mingo, viro, peterz

Commit-ID:  a7602681fc63f1a3ddd3da336296c9634c2ff974
Gitweb:     http://git.kernel.org/tip/a7602681fc63f1a3ddd3da336296c9634c2ff974
Author:     Al Viro <viro@ZenIV.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:29 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:41 +0200

hrtimer: Move copyout of remaining time to do_nanosleep()

The hrtimer nanosleep() implementation can be simplified by moving the copy
out of the remaining time to do_nanosleep() which is shared between the
real nanosleep function and the restart function.

The pointer to the timespec64 which is updated is already stored in the
restart block at the call site, so the seperate handling of nanosleep and
restart function can be avoided.

[ tglx: Added changelog ]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-4-viro@ZenIV.linux.org.uk

---
 kernel/time/hrtimer.c | 62 +++++++++++++++++----------------------------------
 1 file changed, 20 insertions(+), 42 deletions(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 4ae777f..baa7b84 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1441,6 +1441,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
+	struct timespec __user *rmtp;
 	hrtimer_init_sleeper(t, current);
 
 	do {
@@ -1457,48 +1458,33 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 
 	__set_current_state(TASK_RUNNING);
 
-	return t->task == NULL;
-}
-
-static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
-{
-	struct timespec rmt;
-	ktime_t rem;
-
-	rem = hrtimer_expires_remaining(timer);
-	if (rem <= 0)
+	if (!t->task)
 		return 0;
-	rmt = ktime_to_timespec(rem);
 
-	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-		return -EFAULT;
-
-	return 1;
+	rmtp = current->restart_block.nanosleep.rmtp;
+	if (rmtp) {
+		struct timespec rmt;
+		ktime_t rem = hrtimer_expires_remaining(&t->timer);
+		if (rem <= 0)
+			return 0;
+		rmt = ktime_to_timespec(rem);
+
+		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+			return -EFAULT;
+	}
+	return -ERESTART_RESTARTBLOCK;
 }
 
 long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
 	struct hrtimer_sleeper t;
-	struct timespec __user  *rmtp;
-	int ret = 0;
+	int ret;
 
 	hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid,
 				HRTIMER_MODE_ABS);
 	hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
 
-	if (do_nanosleep(&t, HRTIMER_MODE_ABS))
-		goto out;
-
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(&t.timer, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
-	/* The other values in restart are already filled in */
-	ret = -ERESTART_RESTARTBLOCK;
-out:
+	ret = do_nanosleep(&t, HRTIMER_MODE_ABS);
 	destroy_hrtimer_on_stack(&t.timer);
 	return ret;
 }
@@ -1506,8 +1492,7 @@ out:
 long hrtimer_nanosleep(struct timespec64 *rqtp,
 		       const enum hrtimer_mode mode, const clockid_t clockid)
 {
-	struct restart_block *restart = &current->restart_block;
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
 	struct hrtimer_sleeper t;
 	int ret = 0;
 	u64 slack;
@@ -1518,7 +1503,8 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
 
 	hrtimer_init_on_stack(&t.timer, clockid, mode);
 	hrtimer_set_expires_range_ns(&t.timer, timespec64_to_ktime(*rqtp), slack);
-	if (do_nanosleep(&t, mode))
+	ret = do_nanosleep(&t, mode);
+	if (ret != -ERESTART_RESTARTBLOCK)
 		goto out;
 
 	/* Absolute timers do not update the rmtp value and restart: */
@@ -1527,18 +1513,10 @@ long hrtimer_nanosleep(struct timespec64 *rqtp,
 		goto out;
 	}
 
-	rmtp = restart->nanosleep.rmtp;
-	if (rmtp) {
-		ret = update_rmtp(&t.timer, rmtp);
-		if (ret <= 0)
-			goto out;
-	}
-
+	restart = &current->restart_block;
 	restart->fn = hrtimer_nanosleep_restart;
 	restart->nanosleep.clockid = t.timer.base->clockid;
 	restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
-
-	ret = -ERESTART_RESTARTBLOCK;
 out:
 	destroy_hrtimer_on_stack(&t.timer);
 	return ret;

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Store rmtp into restart_block in sys_clock_nanosleep()
  2017-06-07  8:42   ` [PATCH 05/16] clock_nanosleep(): stash rmtp into restart_block Al Viro
@ 2017-06-13 22:06     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:06 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: viro, viro, tglx, linux-kernel, peterz, mingo, hpa, john.stultz

Commit-ID:  99e6c0e6ec349575886ca7daffc9cb7ec583176f
Gitweb:     http://git.kernel.org/tip/99e6c0e6ec349575886ca7daffc9cb7ec583176f
Author:     Al Viro <viro@ZenIV.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:30 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:41 +0200

posix-timers: Store rmtp into restart_block in sys_clock_nanosleep()

... instead of doing that in every ->nsleep() instance

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-5-viro@ZenIV.linux.org.uk

---
 kernel/time/alarmtimer.c       |  8 +-------
 kernel/time/posix-cpu-timers.c | 12 +++---------
 kernel/time/posix-timers.c     | 10 +++++-----
 kernel/time/posix-timers.h     |  2 +-
 4 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index ac6e9bc..d859a36 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -753,8 +753,7 @@ static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
  * Handles clock_nanosleep calls against _ALARM clockids
  */
 static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
-			      struct timespec64 *tsreq,
-			      struct timespec __user *rmtp)
+			      struct timespec64 *tsreq)
 {
 	enum  alarmtimer_type type = clock2alarm(which_clock);
 	struct restart_block *restart = &current->restart_block;
@@ -762,11 +761,6 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
 	ktime_t exp;
 	int ret = 0;
 
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-
-	restart->nanosleep.rmtp = rmtp;
-
 	if (!alarmtimer_get_rtcdev())
 		return -ENOTSUPP;
 
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 239fff9..ec6258c 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1328,16 +1328,11 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 static long posix_cpu_nsleep_restart(struct restart_block *restart_block);
 
 static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-			    struct timespec64 *rqtp, struct timespec __user *rmtp)
+			    struct timespec64 *rqtp)
 {
 	struct restart_block *restart_block = &current->restart_block;
 	int error;
 
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-
-	restart_block->nanosleep.rmtp = rmtp;
-
 	/*
 	 * Diagnose required errors first.
 	 */
@@ -1388,10 +1383,9 @@ static int process_cpu_timer_create(struct k_itimer *timer)
 	return posix_cpu_timer_create(timer);
 }
 static int process_cpu_nsleep(const clockid_t which_clock, int flags,
-			      struct timespec64 *rqtp,
-			      struct timespec __user *rmtp)
+			      struct timespec64 *rqtp)
 {
-	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
+	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
 }
 static long process_cpu_nsleep_restart(struct restart_block *restart_block)
 {
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 1a9f59f..a3e5c01 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1041,11 +1041,8 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
  * nanosleep for monotonic and realtime clocks
  */
 static int common_nsleep(const clockid_t which_clock, int flags,
-			 struct timespec64 *tsave, struct timespec __user *rmtp)
+			 struct timespec64 *tsave)
 {
-	if (flags & TIMER_ABSTIME)
-		rmtp = NULL;
-	current->restart_block.nanosleep.rmtp = rmtp;
 	return hrtimer_nanosleep(tsave, flags & TIMER_ABSTIME ?
 				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
 				 which_clock);
@@ -1070,8 +1067,11 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 	t64 = timespec_to_timespec64(t);
 	if (!timespec64_valid(&t64))
 		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.rmtp = rmtp;
 
-	return kc->nsleep(which_clock, flags, &t64, rmtp);
+	return kc->nsleep(which_clock, flags, &t64);
 }
 
 /*
diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h
index b086f5b..bfd9e15 100644
--- a/kernel/time/posix-timers.h
+++ b/kernel/time/posix-timers.h
@@ -10,7 +10,7 @@ struct k_clock {
 	int	(*clock_adj)(const clockid_t which_clock, struct timex *tx);
 	int	(*timer_create)(struct k_itimer *timer);
 	int	(*nsleep)(const clockid_t which_clock, int flags,
-			  struct timespec64 *, struct timespec __user *);
+			  struct timespec64 *);
 	long	(*nsleep_restart)(struct restart_block *restart_block);
 	int	(*timer_set)(struct k_itimer *timr, int flags,
 			     struct itimerspec64 *new_setting,

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] time/posix-timers: Move the compat copyouts to the nanosleep implementations
  2017-06-07  8:42   ` [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts Al Viro
  2017-06-07 10:07     ` Peter Zijlstra
@ 2017-06-13 22:06     ` tip-bot for Al Viro
  1 sibling, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:06 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, tglx, hpa, viro, mingo, linux-kernel, john.stultz

Commit-ID:  edbeda46322fbcb15af2d2d0f2daffb0cd349a5a
Gitweb:     http://git.kernel.org/tip/edbeda46322fbcb15af2d2d0f2daffb0cd349a5a
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:31 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:42 +0200

time/posix-timers: Move the compat copyouts to the nanosleep implementations

Turn restart_block.nanosleep.{rmtp,compat_rmtp} into a tagged union (kind =
1 -> native, kind = 2 -> compat, kind = 0 -> nothing) and make the places
doing actual copyout handle compat as well as native (that will become a
helper in the next commit).  Result: compat wrappers, messing with
reassignments, etc. are gone.

[ tglx: Folded in a variant of Peter Zijlstras enum patch ]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-6-viro@ZenIV.linux.org.uk

---
 include/linux/posix-timers.h   |   2 -
 include/linux/restart_block.h  |  15 ++++-
 kernel/compat.c                | 131 -----------------------------------------
 kernel/time/alarmtimer.c       |  16 +++--
 kernel/time/hrtimer.c          |  42 +++++++++++--
 kernel/time/posix-cpu-timers.c |  20 +++++--
 kernel/time/posix-stubs.c      |  55 +++++++++++++----
 kernel/time/posix-timers.c     |  32 +++++++---
 8 files changed, 142 insertions(+), 171 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 667095d..29f1b7f 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -110,8 +110,6 @@ void posix_cpu_timers_exit_group(struct task_struct *task);
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
 			   u64 *newval, u64 *oldval);
 
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
 
 void posixtimer_rearm(struct siginfo *info);
diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
index 0d905d8..19df8422 100644
--- a/include/linux/restart_block.h
+++ b/include/linux/restart_block.h
@@ -11,6 +11,14 @@ struct timespec;
 struct compat_timespec;
 struct pollfd;
 
+enum timespec_type {
+	TT_NONE		= 0,
+	TT_NATIVE	= 1,
+#ifdef CONFIG_COMPAT
+	TT_COMPAT	= 2,
+#endif
+};
+
 /*
  * System call restart block.
  */
@@ -29,10 +37,13 @@ struct restart_block {
 		/* For nanosleep */
 		struct {
 			clockid_t clockid;
-			struct timespec __user *rmtp;
+			enum timespec_type type;
+			union {
+				struct timespec __user *rmtp;
 #ifdef CONFIG_COMPAT
-			struct compat_timespec __user *compat_rmtp;
+				struct compat_timespec __user *compat_rmtp;
 #endif
+			};
 			u64 expires;
 		} nanosleep;
 		/* For poll */
diff --git a/kernel/compat.c b/kernel/compat.c
index cc9ba9d..23afa26 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -213,82 +213,6 @@ int compat_convert_timespec(struct timespec __user **kts,
 	return 0;
 }
 
-static long compat_nanosleep_restart(struct restart_block *restart)
-{
-	struct compat_timespec __user *rmtp;
-	struct timespec rmt;
-	mm_segment_t oldfs;
-	long ret;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		rmtp = restart->nanosleep.compat_rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	struct timespec tu, rmt;
-	struct timespec64 tu64;
-	mm_segment_t oldfs;
-	long ret;
-
-	if (compat_get_timespec(&tu, rqtp))
-		return -EFAULT;
-
-	tu64 = timespec_to_timespec64(tu);
-	if (!timespec64_valid(&tu64))
-		return -EINVAL;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	current->restart_block.nanosleep.rmtp =
-				rmtp ? (struct timespec __user *)&rmt : NULL;
-	ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
-	set_fs(oldfs);
-
-	/*
-	 * hrtimer_nanosleep() can only return 0 or
-	 * -ERESTART_RESTARTBLOCK here because:
-	 *
-	 * - we call it with HRTIMER_MODE_REL and therefor exclude the
-	 *   -ERESTARTNOHAND return path.
-	 *
-	 * - we supply the rmtp argument from the task stack (due to
-	 *   the necessary compat conversion. So the update cannot
-	 *   fail, which excludes the -EFAULT return path as well. If
-	 *   it fails nevertheless we have a bigger problem and wont
-	 *   reach this place anymore.
-	 *
-	 * - if the return value is 0, we do not have to update rmtp
-	 *    because there is no remaining time.
-	 *
-	 * We check for -ERESTART_RESTARTBLOCK nevertheless if the
-	 * core implementation decides to return random nonsense.
-	 */
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		struct restart_block *restart = &current->restart_block;
-
-		restart->fn = compat_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 static inline long get_compat_itimerval(struct itimerval *o,
 		struct compat_itimerval __user *i)
 {
@@ -821,61 +745,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 	return err;
 }
 
-static long compat_clock_nanosleep_restart(struct restart_block *restart)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec tu;
-	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = clock_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&tu, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
-		       struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec in, out;
-	struct restart_block *restart;
-
-	if (compat_get_timespec(&in, rqtp))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_nanosleep(which_clock, flags,
-				  (struct timespec __user *) &in,
-				  (struct timespec __user *) &out);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&out, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart = &current->restart_block;
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index d859a36..57bcf94 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -27,6 +27,7 @@
 #include <linux/posix-timers.h>
 #include <linux/workqueue.h>
 #include <linux/freezer.h>
+#include <linux/compat.h>
 
 #include "posix-timers.h"
 
@@ -691,7 +692,7 @@ static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
 static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 				enum alarmtimer_type type)
 {
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
 	alarm->data = (void *)current;
 	do {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -709,8 +710,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 
 	if (freezing(current))
 		alarmtimer_freezerset(absexp, type);
-	rmtp = current->restart_block.nanosleep.rmtp;
-	if (rmtp) {
+	restart = &current->restart_block;
+	if (restart->nanosleep.type != TT_NONE) {
 		struct timespec rmt;
 		ktime_t rem;
 
@@ -720,7 +721,14 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+		if (restart->nanosleep.type == TT_COMPAT) {
+			if (compat_put_timespec(&rmt,
+						restart->nanosleep.compat_rmtp))
+				return -EFAULT;
+		} else
+#endif
+		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
 			return -EFAULT;
 	}
 	return -ERESTART_RESTARTBLOCK;
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index baa7b84..5370da8 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -51,6 +51,7 @@
 #include <linux/sched/debug.h>
 #include <linux/timer.h>
 #include <linux/freezer.h>
+#include <linux/compat.h>
 
 #include <linux/uaccess.h>
 
@@ -1441,7 +1442,8 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
-	struct timespec __user *rmtp;
+	struct restart_block *restart;
+
 	hrtimer_init_sleeper(t, current);
 
 	do {
@@ -1461,15 +1463,23 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 	if (!t->task)
 		return 0;
 
-	rmtp = current->restart_block.nanosleep.rmtp;
-	if (rmtp) {
-		struct timespec rmt;
+	restart = &current->restart_block;
+	if (restart->nanosleep.type != TT_NONE) {
 		ktime_t rem = hrtimer_expires_remaining(&t->timer);
+		struct timespec rmt;
+
 		if (rem <= 0)
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-		if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+		if (restart->nanosleep.type == TT_COMPAT) {
+			if (compat_put_timespec(&rmt,
+						restart->nanosleep.compat_rmtp))
+				return -EFAULT;
+		} else
+#endif
+		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
 			return -EFAULT;
 	}
 	return -ERESTART_RESTARTBLOCK;
@@ -1535,10 +1545,32 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
 	if (!timespec64_valid(&tu64))
 		return -EINVAL;
 
+	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
 	current->restart_block.nanosleep.rmtp = rmtp;
 	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
+{
+	struct timespec64 tu64;
+	struct timespec tu;
+
+	if (compat_get_timespec(&tu, rqtp))
+		return -EFAULT;
+
+	tu64 = timespec_to_timespec64(tu);
+	if (!timespec64_valid(&tu64))
+		return -EINVAL;
+
+	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
+	current->restart_block.nanosleep.compat_rmtp = rmtp;
+	return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+}
+#endif
+
 /*
  * Functions related to boot-time initialization:
  */
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ec6258c..1563ca2 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -12,6 +12,7 @@
 #include <trace/events/timer.h>
 #include <linux/tick.h>
 #include <linux/workqueue.h>
+#include <linux/compat.h>
 
 #include "posix-timers.h"
 
@@ -1243,10 +1244,9 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	timer.it_process = current;
 	if (!error) {
 		static struct itimerspec64 zero_it;
-		struct restart_block *restart = &current->restart_block;
-		struct timespec __user *rmtp;
+		struct restart_block *restart;
 
-		memset(&it, 0, sizeof it);
+		memset(&it, 0, sizeof(it));
 		it.it_value = *rqtp;
 
 		spin_lock_irq(&timer.it_lock);
@@ -1311,12 +1311,20 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		/*
 		 * Report back to the user the time still remaining.
 		 */
-		rmtp = restart->nanosleep.rmtp;
-		if (rmtp) {
+		restart = &current->restart_block;
+		if (restart->nanosleep.type != TT_NONE) {
 			struct timespec ts;
 
 			ts = timespec64_to_timespec(it.it_value);
-			if (copy_to_user(rmtp, &ts, sizeof(*rmtp)))
+#ifdef CONFIG_COMPAT
+			if (restart->nanosleep.type == TT_COMPAT) {
+				if (compat_put_timespec(&ts,
+						restart->nanosleep.compat_rmtp))
+					return -EFAULT;
+			} else
+#endif
+			if (copy_to_user(restart->nanosleep.rmtp, &ts,
+					sizeof(ts)))
 				return -EFAULT;
 		}
 		restart->nanosleep.expires = timespec64_to_ns(rqtp);
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 156a5e6..749b76f 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -17,6 +17,7 @@
 #include <linux/ktime.h>
 #include <linux/timekeeping.h>
 #include <linux/posix-timers.h>
+#include <linux/compat.h>
 
 asmlinkage long sys_ni_posix_timers(void)
 {
@@ -110,25 +111,53 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 	case CLOCK_REALTIME:
 	case CLOCK_MONOTONIC:
 	case CLOCK_BOOTTIME:
-		if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
-			return -EFAULT;
-		t64 = timespec_to_timespec64(t);
-		if (!timespec64_valid(&t64))
-			return -EINVAL;
-		if (flags & TIMER_ABSTIME)
-			rmtp = NULL;
-		current->restart_block.nanosleep.rmtp = rmtp;
-		return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
-					 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
-					 which_clock);
+		break;
 	default:
 		return -EINVAL;
 	}
+
+	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
+		return -EFAULT;
+	t64 = timespec_to_timespec64(t);
+	if (!timespec64_valid(&t64))
+		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
+	current->restart_block.nanosleep.rmtp = rmtp;
+	return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
+				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+				 which_clock);
 }
 
 #ifdef CONFIG_COMPAT
-long clock_nanosleep_restart(struct restart_block *restart_block)
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
 {
-	return hrtimer_nanosleep_restart(restart_block);
+	struct timespec64 t64;
+	struct timespec t;
+
+	switch (which_clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+	case CLOCK_BOOTTIME:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (compat_get_timespec(&t, rqtp))
+		return -EFAULT;
+	t64 = timespec_to_timespec64(t);
+	if (!timespec64_valid(&t64))
+		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
+	current->restart_block.nanosleep.compat_rmtp = rmtp;
+	return hrtimer_nanosleep(&t64, flags & TIMER_ABSTIME ?
+				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+				 which_clock);
 }
 #endif
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index a3e5c01..bec86b6 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -49,6 +49,7 @@
 #include <linux/workqueue.h>
 #include <linux/export.h>
 #include <linux/hashtable.h>
+#include <linux/compat.h>
 
 #include "timekeeping.h"
 #include "posix-timers.h"
@@ -1069,25 +1070,40 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		return -EINVAL;
 	if (flags & TIMER_ABSTIME)
 		rmtp = NULL;
+	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
 	current->restart_block.nanosleep.rmtp = rmtp;
 
 	return kc->nsleep(which_clock, flags, &t64);
 }
 
-/*
- * This will restart clock_nanosleep. This is required only by
- * compat_clock_nanosleep_restart for now.
- */
-long clock_nanosleep_restart(struct restart_block *restart_block)
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
 {
-	clockid_t which_clock = restart_block->nanosleep.clockid;
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 t64;
+	struct timespec t;
 
-	if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
+	if (!kc)
 		return -EINVAL;
+	if (!kc->nsleep)
+		return -ENANOSLEEP_NOTSUP;
+
+	if (compat_get_timespec(&t, rqtp))
+		return -EFAULT;
 
-	return kc->nsleep_restart(restart_block);
+	t64 = timespec_to_timespec64(t);
+	if (!timespec64_valid(&t64))
+		return -EINVAL;
+	if (flags & TIMER_ABSTIME)
+		rmtp = NULL;
+	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
+	current->restart_block.nanosleep.compat_rmtp = rmtp;
+
+	return kc->nsleep(which_clock, flags, &t64);
 }
+#endif
 
 static const struct k_clock clock_realtime = {
 	.clock_getres		= posix_get_hrtimer_res,

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] hrtimers/posix-timers: Merge nanosleep timespec copyout logics into a new helper
  2017-06-07  8:42   ` [PATCH 07/16] {clock_,}nanosleep(2): merge timespec copyout logics into a new helper Al Viro
@ 2017-06-13 22:07     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:07 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, hpa, mingo, linux-kernel, peterz, viro, john.stultz

Commit-ID:  ce41aaf47af3d28c4c958e07675a3e0a51f09bd3
Gitweb:     http://git.kernel.org/tip/ce41aaf47af3d28c4c958e07675a3e0a51f09bd3
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:32 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:42 +0200

hrtimers/posix-timers: Merge nanosleep timespec copyout logics into a new helper

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-7-viro@ZenIV.linux.org.uk

---
 include/linux/hrtimer.h        |  2 ++
 kernel/time/alarmtimer.c       | 10 +---------
 kernel/time/hrtimer.c          | 29 ++++++++++++++++++++---------
 kernel/time/posix-cpu-timers.c | 13 ++-----------
 4 files changed, 25 insertions(+), 29 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index b80c34f..38b968f 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -452,6 +452,8 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
 }
 
 /* Precise sleep: */
+
+extern int nanosleep_copyout(struct restart_block *, struct timespec *);
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 57bcf94..7bed4e4 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -721,15 +721,7 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp,
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-#ifdef CONFIG_COMPAT
-		if (restart->nanosleep.type == TT_COMPAT) {
-			if (compat_put_timespec(&rmt,
-						restart->nanosleep.compat_rmtp))
-				return -EFAULT;
-		} else
-#endif
-		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
-			return -EFAULT;
+		return nanosleep_copyout(restart, &rmt);
 	}
 	return -ERESTART_RESTARTBLOCK;
 }
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 5370da8..db2f5f7 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1440,6 +1440,25 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
 
+int nanosleep_copyout(struct restart_block *restart, struct timespec *ts)
+{
+	switch(restart->nanosleep.type) {
+#ifdef CONFIG_COMPAT
+	case TT_COMPAT:
+		if (compat_put_timespec(ts, restart->nanosleep.compat_rmtp))
+			return -EFAULT;
+		break;
+#endif
+	case TT_NATIVE:
+		if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec)))
+			return -EFAULT;
+		break;
+	default:
+		BUG();
+	}
+	return -ERESTART_RESTARTBLOCK;
+}
+
 static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
 {
 	struct restart_block *restart;
@@ -1472,15 +1491,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 			return 0;
 		rmt = ktime_to_timespec(rem);
 
-#ifdef CONFIG_COMPAT
-		if (restart->nanosleep.type == TT_COMPAT) {
-			if (compat_put_timespec(&rmt,
-						restart->nanosleep.compat_rmtp))
-				return -EFAULT;
-		} else
-#endif
-		if (copy_to_user(restart->nanosleep.rmtp, &rmt, sizeof(rmt)))
-			return -EFAULT;
+		return nanosleep_copyout(restart, &rmt);
 	}
 	return -ERESTART_RESTARTBLOCK;
 }
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 1563ca2..993a924 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1312,22 +1312,13 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		 * Report back to the user the time still remaining.
 		 */
 		restart = &current->restart_block;
+		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 		if (restart->nanosleep.type != TT_NONE) {
 			struct timespec ts;
 
 			ts = timespec64_to_timespec(it.it_value);
-#ifdef CONFIG_COMPAT
-			if (restart->nanosleep.type == TT_COMPAT) {
-				if (compat_put_timespec(&ts,
-						restart->nanosleep.compat_rmtp))
-					return -EFAULT;
-			} else
-#endif
-			if (copy_to_user(restart->nanosleep.rmtp, &ts,
-					sizeof(ts)))
-				return -EFAULT;
+			error = nanosleep_copyout(restart, &ts);
 		}
-		restart->nanosleep.expires = timespec64_to_ns(rqtp);
 	}
 
 	return error;

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Kill ->nsleep_restart()
  2017-06-07  8:42   ` [PATCH 08/16] kill ->nsleep_restart() Al Viro
@ 2017-06-13 22:08     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, john.stultz, viro, hpa, linux-kernel, peterz, tglx

Commit-ID:  fb923c4a3c2ee735755d4a93522150fc35d0ecbd
Gitweb:     http://git.kernel.org/tip/fb923c4a3c2ee735755d4a93522150fc35d0ecbd
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:33 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:42 +0200

posix-timers: Kill ->nsleep_restart()

No more users.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-8-viro@ZenIV.linux.org.uk

---
 include/linux/hrtimer.h        | 1 -
 kernel/time/hrtimer.c          | 2 +-
 kernel/time/posix-cpu-timers.c | 6 ------
 kernel/time/posix-timers.c     | 4 ----
 kernel/time/posix-timers.h     | 1 -
 5 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 38b968f..d83b7ed 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -457,7 +457,6 @@ extern int nanosleep_copyout(struct restart_block *, struct timespec *);
 extern long hrtimer_nanosleep(struct timespec64 *rqtp,
 			      const enum hrtimer_mode mode,
 			      const clockid_t clockid);
-extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
 
 extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
 				 struct task_struct *tsk);
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index db2f5f7..45f83cc 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1496,7 +1496,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
 	return -ERESTART_RESTARTBLOCK;
 }
 
-long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
+static long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
 	struct hrtimer_sleeper t;
 	int ret;
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 993a924..515148d 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1386,10 +1386,6 @@ static int process_cpu_nsleep(const clockid_t which_clock, int flags,
 {
 	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
 }
-static long process_cpu_nsleep_restart(struct restart_block *restart_block)
-{
-	return -EINVAL;
-}
 static int thread_cpu_clock_getres(const clockid_t which_clock,
 				   struct timespec64 *tp)
 {
@@ -1412,7 +1408,6 @@ const struct k_clock clock_posix_cpu = {
 	.clock_get	= posix_cpu_clock_get,
 	.timer_create	= posix_cpu_timer_create,
 	.nsleep		= posix_cpu_nsleep,
-	.nsleep_restart	= posix_cpu_nsleep_restart,
 	.timer_set	= posix_cpu_timer_set,
 	.timer_del	= posix_cpu_timer_del,
 	.timer_get	= posix_cpu_timer_get,
@@ -1424,7 +1419,6 @@ const struct k_clock clock_process = {
 	.clock_get	= process_cpu_clock_get,
 	.timer_create	= process_cpu_timer_create,
 	.nsleep		= process_cpu_nsleep,
-	.nsleep_restart	= process_cpu_nsleep_restart,
 };
 
 const struct k_clock clock_thread = {
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index bec86b6..ea4a463 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1111,7 +1111,6 @@ static const struct k_clock clock_realtime = {
 	.clock_set		= posix_clock_realtime_set,
 	.clock_adj		= posix_clock_realtime_adj,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1127,7 +1126,6 @@ static const struct k_clock clock_monotonic = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_ktime_get_ts,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1158,7 +1156,6 @@ static const struct k_clock clock_tai = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_get_tai,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
@@ -1174,7 +1171,6 @@ static const struct k_clock clock_boottime = {
 	.clock_getres		= posix_get_hrtimer_res,
 	.clock_get		= posix_get_boottime,
 	.nsleep			= common_nsleep,
-	.nsleep_restart		= hrtimer_nanosleep_restart,
 	.timer_create		= common_timer_create,
 	.timer_set		= common_timer_set,
 	.timer_get		= common_timer_get,
diff --git a/kernel/time/posix-timers.h b/kernel/time/posix-timers.h
index bfd9e15..5e69bb8 100644
--- a/kernel/time/posix-timers.h
+++ b/kernel/time/posix-timers.h
@@ -11,7 +11,6 @@ struct k_clock {
 	int	(*timer_create)(struct k_itimer *timer);
 	int	(*nsleep)(const clockid_t which_clock, int flags,
 			  struct timespec64 *);
-	long	(*nsleep_restart)(struct restart_block *restart_block);
 	int	(*timer_set)(struct k_itimer *timr, int flags,
 			     struct itimerspec64 *new_setting,
 			     struct itimerspec64 *old_setting);

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] ntp: Move adjtimex related compat syscalls to native counterparts
  2017-06-07  8:42   ` [PATCH 09/16] move adjtimex-related compat syscalls to native counterparts Al Viro
@ 2017-06-13 22:08     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, tglx, john.stultz, mingo, hpa, linux-kernel, viro

Commit-ID:  3a4d44b6162555070194e486ff6b3799a8d323a2
Gitweb:     http://git.kernel.org/tip/3a4d44b6162555070194e486ff6b3799a8d323a2
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:34 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:43 +0200

ntp: Move adjtimex related compat syscalls to native counterparts

Get rid of set_fs() mess and sanitize compat_{get,put}_timex(),
while we are at it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-9-viro@ZenIV.linux.org.uk

---
 include/linux/compat.h     |   4 ++
 kernel/compat.c            | 141 +++++++++++++++++----------------------------
 kernel/time/posix-stubs.c  |   2 +
 kernel/time/posix-timers.c |  27 +++++++++
 kernel/time/time.c         |  24 +++++++-
 5 files changed, 108 insertions(+), 90 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index 1c5f315..ecb8dd2 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -128,6 +128,10 @@ struct compat_timex {
 	compat_int_t:32; compat_int_t:32; compat_int_t:32;
 };
 
+struct timex;
+int compat_get_timex(struct timex *, const struct compat_timex __user *);
+int compat_put_timex(struct compat_timex __user *, const struct timex *);
+
 #define _COMPAT_NSIG_WORDS	(_COMPAT_NSIG / _COMPAT_NSIG_BPW)
 
 typedef struct {
diff --git a/kernel/compat.c b/kernel/compat.c
index 23afa26..97087b3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -30,60 +30,64 @@
 
 #include <linux/uaccess.h>
 
-static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
+int compat_get_timex(struct timex *txc, const struct compat_timex __user *utp)
 {
-	memset(txc, 0, sizeof(struct timex));
-
-	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
-			__get_user(txc->modes, &utp->modes) ||
-			__get_user(txc->offset, &utp->offset) ||
-			__get_user(txc->freq, &utp->freq) ||
-			__get_user(txc->maxerror, &utp->maxerror) ||
-			__get_user(txc->esterror, &utp->esterror) ||
-			__get_user(txc->status, &utp->status) ||
-			__get_user(txc->constant, &utp->constant) ||
-			__get_user(txc->precision, &utp->precision) ||
-			__get_user(txc->tolerance, &utp->tolerance) ||
-			__get_user(txc->time.tv_sec, &utp->time.tv_sec) ||
-			__get_user(txc->time.tv_usec, &utp->time.tv_usec) ||
-			__get_user(txc->tick, &utp->tick) ||
-			__get_user(txc->ppsfreq, &utp->ppsfreq) ||
-			__get_user(txc->jitter, &utp->jitter) ||
-			__get_user(txc->shift, &utp->shift) ||
-			__get_user(txc->stabil, &utp->stabil) ||
-			__get_user(txc->jitcnt, &utp->jitcnt) ||
-			__get_user(txc->calcnt, &utp->calcnt) ||
-			__get_user(txc->errcnt, &utp->errcnt) ||
-			__get_user(txc->stbcnt, &utp->stbcnt))
+	struct compat_timex tx32;
+
+	if (copy_from_user(&tx32, utp, sizeof(struct compat_timex)))
 		return -EFAULT;
 
+	txc->modes = tx32.modes;
+	txc->offset = tx32.offset;
+	txc->freq = tx32.freq;
+	txc->maxerror = tx32.maxerror;
+	txc->esterror = tx32.esterror;
+	txc->status = tx32.status;
+	txc->constant = tx32.constant;
+	txc->precision = tx32.precision;
+	txc->tolerance = tx32.tolerance;
+	txc->time.tv_sec = tx32.time.tv_sec;
+	txc->time.tv_usec = tx32.time.tv_usec;
+	txc->tick = tx32.tick;
+	txc->ppsfreq = tx32.ppsfreq;
+	txc->jitter = tx32.jitter;
+	txc->shift = tx32.shift;
+	txc->stabil = tx32.stabil;
+	txc->jitcnt = tx32.jitcnt;
+	txc->calcnt = tx32.calcnt;
+	txc->errcnt = tx32.errcnt;
+	txc->stbcnt = tx32.stbcnt;
+
 	return 0;
 }
 
-static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
-{
-	if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
-			__put_user(txc->modes, &utp->modes) ||
-			__put_user(txc->offset, &utp->offset) ||
-			__put_user(txc->freq, &utp->freq) ||
-			__put_user(txc->maxerror, &utp->maxerror) ||
-			__put_user(txc->esterror, &utp->esterror) ||
-			__put_user(txc->status, &utp->status) ||
-			__put_user(txc->constant, &utp->constant) ||
-			__put_user(txc->precision, &utp->precision) ||
-			__put_user(txc->tolerance, &utp->tolerance) ||
-			__put_user(txc->time.tv_sec, &utp->time.tv_sec) ||
-			__put_user(txc->time.tv_usec, &utp->time.tv_usec) ||
-			__put_user(txc->tick, &utp->tick) ||
-			__put_user(txc->ppsfreq, &utp->ppsfreq) ||
-			__put_user(txc->jitter, &utp->jitter) ||
-			__put_user(txc->shift, &utp->shift) ||
-			__put_user(txc->stabil, &utp->stabil) ||
-			__put_user(txc->jitcnt, &utp->jitcnt) ||
-			__put_user(txc->calcnt, &utp->calcnt) ||
-			__put_user(txc->errcnt, &utp->errcnt) ||
-			__put_user(txc->stbcnt, &utp->stbcnt) ||
-			__put_user(txc->tai, &utp->tai))
+int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc)
+{
+	struct compat_timex tx32;
+
+	memset(&tx32, 0, sizeof(struct compat_timex));
+	tx32.modes = txc->modes;
+	tx32.offset = txc->offset;
+	tx32.freq = txc->freq;
+	tx32.maxerror = txc->maxerror;
+	tx32.esterror = txc->esterror;
+	tx32.status = txc->status;
+	tx32.constant = txc->constant;
+	tx32.precision = txc->precision;
+	tx32.tolerance = txc->tolerance;
+	tx32.time.tv_sec = txc->time.tv_sec;
+	tx32.time.tv_usec = txc->time.tv_usec;
+	tx32.tick = txc->tick;
+	tx32.ppsfreq = txc->ppsfreq;
+	tx32.jitter = txc->jitter;
+	tx32.shift = txc->shift;
+	tx32.stabil = txc->stabil;
+	tx32.jitcnt = txc->jitcnt;
+	tx32.calcnt = txc->calcnt;
+	tx32.errcnt = txc->errcnt;
+	tx32.stbcnt = txc->stbcnt;
+	tx32.tai = txc->tai;
+	if (copy_to_user(utp, &tx32, sizeof(struct compat_timex)))
 		return -EFAULT;
 	return 0;
 }
@@ -705,29 +709,6 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
 	return err;
 }
 
-COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
-		       struct compat_timex __user *, utp)
-{
-	struct timex txc;
-	mm_segment_t oldfs;
-	int err, ret;
-
-	err = compat_get_timex(&txc, utp);
-	if (err)
-		return err;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
-	set_fs(oldfs);
-
-	err = compat_put_timex(utp, &txc);
-	if (err)
-		return err;
-
-	return ret;
-}
-
 COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 		       struct compat_timespec __user *, tp)
 {
@@ -944,24 +925,6 @@ COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
 
 #endif /* __ARCH_WANT_COMPAT_SYS_TIME */
 
-COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
-{
-	struct timex txc;
-	int err, ret;
-
-	err = compat_get_timex(&txc, utp);
-	if (err)
-		return err;
-
-	ret = do_adjtimex(&txc);
-
-	err = compat_put_timex(utp, &txc);
-	if (err)
-		return err;
-
-	return ret;
-}
-
 #ifdef CONFIG_NUMA
 COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
 		       compat_uptr_t __user *, pages32,
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 749b76f..954d1d8 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -28,6 +28,7 @@ asmlinkage long sys_ni_posix_timers(void)
 }
 
 #define SYS_NI(name)  SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
+#define COMPAT_SYS_NI(name)  SYSCALL_ALIAS(compat_sys_##name, sys_ni_posix_timers)
 
 SYS_NI(timer_create);
 SYS_NI(timer_gettime);
@@ -40,6 +41,7 @@ SYS_NI(setitimer);
 #ifdef __ARCH_WANT_SYS_ALARM
 SYS_NI(alarm);
 #endif
+COMPAT_SYS_NI(clock_adjtime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index ea4a463..b1b6d52 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1018,6 +1018,33 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
 	return err;
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
+		       struct compat_timex __user *, utp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timex ktx;
+	int err;
+
+	if (!kc)
+		return -EINVAL;
+	if (!kc->clock_adj)
+		return -EOPNOTSUPP;
+
+	err = compat_get_timex(&ktx, utp);
+	if (err)
+		return err;
+
+	err = kc->clock_adj(which_clock, &ktx);
+
+	if (err >= 0)
+		err = compat_put_timex(utp, &ktx);
+
+	return err;
+}
+#endif
+
 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 		struct timespec __user *, tp)
 {
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 49c73c6..400662f 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -39,6 +39,7 @@
 #include <linux/ptrace.h>
 
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 #include <asm/unistd.h>
 
 #include <generated/timeconst.h>
@@ -224,12 +225,33 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
 	 * structure. But bear in mind that the structures
 	 * may change
 	 */
-	if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
+	if (copy_from_user(&txc, txc_p, sizeof(struct timex)))
 		return -EFAULT;
 	ret = do_adjtimex(&txc);
 	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
 }
 
+#ifdef CONFIG_COMPAT
+
+COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
+{
+	struct timex txc;
+	int err, ret;
+
+	err = compat_get_timex(&txc, utp);
+	if (err)
+		return err;
+
+	ret = do_adjtimex(&txc);
+
+	err = compat_put_timex(utp, &txc);
+	if (err)
+		return err;
+
+	return ret;
+}
+#endif
+
 /*
  * Convert jiffies to milliseconds and back.
  *

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Take compat timer_settime(2) to native one
  2017-06-07  8:42   ` [PATCH 10/16] take compat timer_settime(2) to native one Al Viro
@ 2017-06-13 22:09     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:09 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: viro, linux-kernel, john.stultz, hpa, mingo, tglx, peterz

Commit-ID:  1acbe7708b0313b33287bb4ffcbf26462ea3c588
Gitweb:     http://git.kernel.org/tip/1acbe7708b0313b33287bb4ffcbf26462ea3c588
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:35 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:43 +0200

posix-timers: Take compat timer_settime(2) to native one

... and get rid of set_fs() in there

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-10-viro@ZenIV.linux.org.uk

---
 kernel/compat.c            | 23 ------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 87 +++++++++++++++++++++++++++++++++-------------
 3 files changed, 64 insertions(+), 47 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 97087b3..df39e2e 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -635,29 +635,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
-		       struct compat_itimerspec __user *, new,
-		       struct compat_itimerspec __user *, old)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct itimerspec newts, oldts;
-
-	if (!new)
-		return -EINVAL;
-	if (get_compat_itimerspec(&newts, new))
-		return -EFAULT;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_settime(timer_id, flags,
-				(struct itimerspec __user *) &newts,
-				(struct itimerspec __user *) &oldts);
-	set_fs(oldfs);
-	if (!err && old && put_compat_itimerspec(old, &oldts))
-		return -EFAULT;
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 		       struct compat_itimerspec __user *, setting)
 {
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 954d1d8..ad263df 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -42,6 +42,7 @@ SYS_NI(setitimer);
 SYS_NI(alarm);
 #endif
 COMPAT_SYS_NI(clock_adjtime);
+COMPAT_SYS_NI(timer_settime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index b1b6d52..a73feac 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -819,31 +819,21 @@ int common_timer_set(struct k_itimer *timr, int flags,
 	return 0;
 }
 
-/* Set a POSIX.1b interval timer */
-SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
-		const struct itimerspec __user *, new_setting,
-		struct itimerspec __user *, old_setting)
+static int do_timer_settime(timer_t timer_id, int flags,
+			    struct itimerspec64 *new_spec64,
+			    struct itimerspec64 *old_spec64)
 {
-	struct itimerspec64 new_spec64, old_spec64;
-	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
-	struct itimerspec new_spec, old_spec;
+	const struct k_clock *kc;
 	struct k_itimer *timr;
 	unsigned long flag;
-	const struct k_clock *kc;
 	int error = 0;
 
-	if (!new_setting)
+	if (!timespec64_valid(&new_spec64->it_interval) ||
+	    !timespec64_valid(&new_spec64->it_value))
 		return -EINVAL;
 
-	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
-		return -EFAULT;
-	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
-
-	if (!timespec64_valid(&new_spec64.it_interval) ||
-	    !timespec64_valid(&new_spec64.it_value))
-		return -EINVAL;
-	if (rtn)
-		memset(rtn, 0, sizeof(*rtn));
+	if (old_spec64)
+		memset(old_spec64, 0, sizeof(*old_spec64));
 retry:
 	timr = lock_timer(timer_id, &flag);
 	if (!timr)
@@ -853,22 +843,71 @@ retry:
 	if (WARN_ON_ONCE(!kc || !kc->timer_set))
 		error = -EINVAL;
 	else
-		error = kc->timer_set(timr, flags, &new_spec64, rtn);
+		error = kc->timer_set(timr, flags, new_spec64, old_spec64);
 
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
-		rtn = NULL;	// We already got the old time...
+		old_spec64 = NULL;	// We already got the old time...
 		goto retry;
 	}
 
-	old_spec = itimerspec64_to_itimerspec(&old_spec64);
-	if (old_setting && !error &&
-	    copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
-		error = -EFAULT;
+	return error;
+}
+
+/* Set a POSIX.1b interval timer */
+SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
+		const struct itimerspec __user *, new_setting,
+		struct itimerspec __user *, old_setting)
+{
+	struct itimerspec64 new_spec64, old_spec64;
+	struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL;
+	struct itimerspec new_spec;
+	int error = 0;
+
+	if (!new_setting)
+		return -EINVAL;
 
+	if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
+		return -EFAULT;
+	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
+
+	error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
+	if (!error && old_setting) {
+		struct itimerspec old_spec;
+		old_spec = itimerspec64_to_itimerspec(&old_spec64);
+		if (copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
+			error = -EFAULT;
+	}
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
+		       struct compat_itimerspec __user *, new,
+		       struct compat_itimerspec __user *, old)
+{
+	struct itimerspec64 new_spec64, old_spec64;
+	struct itimerspec64 *rtn = old ? &old_spec64 : NULL;
+	struct itimerspec new_spec;
+	int error = 0;
+
+	if (!new)
+		return -EINVAL;
+	if (get_compat_itimerspec(&new_spec, new))
+		return -EFAULT;
+
+	new_spec64 = itimerspec_to_itimerspec64(&new_spec);
+	error = do_timer_settime(timer_id, flags, &new_spec64, rtn);
+	if (!error && old) {
+		struct itimerspec old_spec;
+		old_spec = itimerspec64_to_itimerspec(&old_spec64);
+		if (put_compat_itimerspec(old, &old_spec))
+			error = -EFAULT;
+	}
+	return error;
+}
+#endif
+
 int common_timer_del(struct k_itimer *timer)
 {
 	const struct k_clock *kc = timer->kclock;

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Take compat timer_gettime(2) to native one
  2017-06-07  8:42   ` [PATCH 11/16] take compat timer_gettime(2) " Al Viro
@ 2017-06-13 22:09     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:09 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, john.stultz, tglx, hpa, linux-kernel, mingo, viro

Commit-ID:  b0dc12426ec404de99d7e75a12a22d9201d90914
Gitweb:     http://git.kernel.org/tip/b0dc12426ec404de99d7e75a12a22d9201d90914
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:36 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:43 +0200

posix-timers: Take compat timer_gettime(2) to native one

... and get rid of set_fs() in there

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-11-viro@ZenIV.linux.org.uk

---
 kernel/compat.c            | 17 -----------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 43 ++++++++++++++++++++++++++++++++++---------
 3 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index df39e2e..1fb8cf7 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -635,23 +635,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
-		       struct compat_itimerspec __user *, setting)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct itimerspec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_timer_gettime(timer_id,
-				(struct itimerspec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && put_compat_itimerspec(setting, &ts))
-		return -EFAULT;
-	return err;
-}
-
 COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
 		       struct compat_timespec __user *, tp)
 {
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index ad263df..f4a1962 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -43,6 +43,7 @@ SYS_NI(alarm);
 #endif
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
+COMPAT_SYS_NI(timer_gettime);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index a73feac..e82bb1f 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -690,11 +690,8 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
 }
 
 /* Get the time remaining on a POSIX.1b interval timer. */
-SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
-		struct itimerspec __user *, setting)
+static int do_timer_gettime(timer_t timer_id,  struct itimerspec64 *setting)
 {
-	struct itimerspec64 cur_setting64;
-	struct itimerspec cur_setting;
 	struct k_itimer *timr;
 	const struct k_clock *kc;
 	unsigned long flags;
@@ -704,21 +701,49 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 	if (!timr)
 		return -EINVAL;
 
-	memset(&cur_setting64, 0, sizeof(cur_setting64));
+	memset(setting, 0, sizeof(*setting));
 	kc = timr->kclock;
 	if (WARN_ON_ONCE(!kc || !kc->timer_get))
 		ret = -EINVAL;
 	else
-		kc->timer_get(timr, &cur_setting64);
+		kc->timer_get(timr, setting);
 
 	unlock_timer(timr, flags);
+	return ret;
+}
 
-	cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
-	if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
-		return -EFAULT;
+/* Get the time remaining on a POSIX.1b interval timer. */
+SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
+		struct itimerspec __user *, setting)
+{
+	struct itimerspec64 cur_setting64;
 
+	int ret = do_timer_gettime(timer_id, &cur_setting64);
+	if (!ret) {
+		struct itimerspec cur_setting;
+		cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
+		if (copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
+		       struct compat_itimerspec __user *, setting)
+{
+	struct itimerspec64 cur_setting64;
+
+	int ret = do_timer_gettime(timer_id, &cur_setting64);
+	if (!ret) {
+		struct itimerspec cur_setting;
+		cur_setting = itimerspec64_to_itimerspec(&cur_setting64);
+		if (put_compat_itimerspec(setting, &cur_setting))
+			ret = -EFAULT;
+	}
 	return ret;
 }
+#endif
 
 /*
  * Get the number of overruns of a POSIX.1b interval timer.  This is to

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] itimers: Move compat itimer syscalls to native ones
  2017-06-07  8:42   ` [PATCH 12/16] move compat itimer syscalls to native ones Al Viro
@ 2017-06-13 22:10     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, mingo, peterz, hpa, john.stultz, tglx, viro

Commit-ID:  54ad9c46c262ce4a603dc7887e37956896a0211d
Gitweb:     http://git.kernel.org/tip/54ad9c46c262ce4a603dc7887e37956896a0211d
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:37 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:44 +0200

itimers: Move compat itimer syscalls to native ones

get rid of set_fs(), sanitize compat copyin/copyout.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-12-viro@ZenIV.linux.org.uk

---
 include/linux/compat.h    |  4 +++
 kernel/compat.c           | 69 +++++++++++------------------------------------
 kernel/time/itimer.c      | 38 ++++++++++++++++++++++++++
 kernel/time/posix-stubs.c |  2 ++
 4 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index ecb8dd2..425563c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -94,6 +94,10 @@ struct compat_itimerval {
 	struct compat_timeval	it_value;
 };
 
+struct itimerval;
+int get_compat_itimerval(struct itimerval *, const struct compat_itimerval __user *);
+int put_compat_itimerval(struct compat_itimerval __user *, const struct itimerval *);
+
 struct compat_tms {
 	compat_clock_t		tms_utime;
 	compat_clock_t		tms_stime;
diff --git a/kernel/compat.c b/kernel/compat.c
index 1fb8cf7..c349417 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -217,65 +217,28 @@ int compat_convert_timespec(struct timespec __user **kts,
 	return 0;
 }
 
-static inline long get_compat_itimerval(struct itimerval *o,
-		struct compat_itimerval __user *i)
+int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
 {
-	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
-		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
-		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
-		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
-		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
-}
-
-static inline long put_compat_itimerval(struct compat_itimerval __user *o,
-		struct itimerval *i)
-{
-	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
-		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
-		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
-		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
-}
-
-asmlinkage long sys_ni_posix_timers(void);
-
-COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
-		struct compat_itimerval __user *, it)
-{
-	struct itimerval kit;
-	int error;
-
-	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
-		return sys_ni_posix_timers();
+	struct compat_itimerval v32;
 
-	error = do_getitimer(which, &kit);
-	if (!error && put_compat_itimerval(it, &kit))
-		error = -EFAULT;
-	return error;
+	if (copy_from_user(&v32, i, sizeof(struct compat_itimerval)))
+		return -EFAULT;
+	o->it_interval.tv_sec = v32.it_interval.tv_sec;
+	o->it_interval.tv_usec = v32.it_interval.tv_usec;
+	o->it_value.tv_sec = v32.it_value.tv_sec;
+	o->it_value.tv_usec = v32.it_value.tv_usec;
+	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
-		struct compat_itimerval __user *, in,
-		struct compat_itimerval __user *, out)
+int put_compat_itimerval(struct compat_itimerval __user *o, const struct itimerval *i)
 {
-	struct itimerval kin, kout;
-	int error;
+	struct compat_itimerval v32;
 
-	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
-		return sys_ni_posix_timers();
-
-	if (in) {
-		if (get_compat_itimerval(&kin, in))
-			return -EFAULT;
-	} else
-		memset(&kin, 0, sizeof(kin));
-
-	error = do_setitimer(which, &kin, out ? &kout : NULL);
-	if (error || !out)
-		return error;
-	if (put_compat_itimerval(out, &kout))
-		return -EFAULT;
-	return 0;
+	v32.it_interval.tv_sec = i->it_interval.tv_sec;
+	v32.it_interval.tv_usec = i->it_interval.tv_usec;
+	v32.it_value.tv_sec = i->it_value.tv_sec;
+	v32.it_value.tv_usec = i->it_value.tv_usec;
+	return copy_to_user(o, &v32, sizeof(struct compat_itimerval)) ? -EFAULT : 0;
 }
 
 static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c
index 087d6a1..9dd7ff5 100644
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -15,6 +15,7 @@
 #include <linux/posix-timers.h>
 #include <linux/hrtimer.h>
 #include <trace/events/timer.h>
+#include <linux/compat.h>
 
 #include <linux/uaccess.h>
 
@@ -116,6 +117,19 @@ SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value)
 	return error;
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
+		       struct compat_itimerval __user *, it)
+{
+	struct itimerval kit;
+	int error = do_getitimer(which, &kit);
+
+	if (!error && put_compat_itimerval(it, &kit))
+		error = -EFAULT;
+	return error;
+}
+#endif
+
 
 /*
  * The timer is automagically restarted, when interval != 0
@@ -294,3 +308,27 @@ SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value,
 		return -EFAULT;
 	return 0;
 }
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
+		       struct compat_itimerval __user *, in,
+		       struct compat_itimerval __user *, out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_compat_itimerval(&kin, in))
+			return -EFAULT;
+	} else {
+		memset(&kin, 0, sizeof(kin));
+	}
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+	if (put_compat_itimerval(out, &kout))
+		return -EFAULT;
+	return 0;
+}
+#endif
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index f4a1962..7f88517 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -44,6 +44,8 @@ SYS_NI(alarm);
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
 COMPAT_SYS_NI(timer_gettime);
+COMPAT_SYS_NI(getitimer);
+COMPAT_SYS_NI(setitimer);
 
 /*
  * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Move compat versions of clock_gettime/settime/getres
  2017-06-07  8:42   ` [PATCH 13/16] clock_gettime/clock_settime/clock_getres: move to native syscalls Al Viro
@ 2017-06-13 22:10     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: viro, tglx, linux-kernel, john.stultz, hpa, mingo, peterz

Commit-ID:  d822cdcce43f9d4dcddbf9c68f9537d542ccc3c3
Gitweb:     http://git.kernel.org/tip/d822cdcce43f9d4dcddbf9c68f9537d542ccc3c3
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:38 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:44 +0200

posix-timers: Move compat versions of clock_gettime/settime/getres

Move them to the native implementations and get rid of the set_fs() hackery.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-13-viro@ZenIV.linux.org.uk

---
 kernel/compat.c            | 51 -----------------------------------
 kernel/time/posix-stubs.c  | 53 +++++++++++++++++++++++++++++++++++++
 kernel/time/posix-timers.c | 66 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 115 insertions(+), 55 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index c349417..582c38b 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -598,57 +598,6 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
 
-COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	if (compat_get_timespec(&ts, tp))
-		return -EFAULT;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_settime(which_clock,
-				(struct timespec __user *) &ts);
-	set_fs(oldfs);
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_gettime(which_clock,
-				(struct timespec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && compat_put_timespec(&ts, tp))
-		return -EFAULT;
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
-		       struct compat_timespec __user *, tp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec ts;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_getres(which_clock,
-			       (struct timespec __user *) &ts);
-	set_fs(oldfs);
-	if (!err && tp && compat_put_timespec(&ts, tp))
-		return -EFAULT;
-	return err;
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index 7f88517..a375c31 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -137,6 +137,59 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 }
 
 #ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	struct timespec64 new_tp64;
+	struct timespec new_tp;
+
+	if (which_clock != CLOCK_REALTIME)
+		return -EINVAL;
+	if (compat_get_timespec(&new_tp, tp))
+		return -EFAULT;
+
+	new_tp64 = timespec_to_timespec64(new_tp);
+	return do_sys_settimeofday64(&new_tp64, NULL);
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
+		       struct compat_timespec __user *,tp)
+{
+	struct timespec64 kernel_tp64;
+	struct timespec kernel_tp;
+
+	switch (which_clock) {
+	case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break;
+	case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break;
+	case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break;
+	default: return -EINVAL;
+	}
+
+	kernel_tp = timespec64_to_timespec(kernel_tp64);
+	if (compat_put_timespec(&kernel_tp, tp))
+		return -EFAULT;
+	return 0;
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	struct timespec rtn_tp = {
+		.tv_sec = 0,
+		.tv_nsec = hrtimer_resolution,
+	};
+
+	switch (which_clock) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+	case CLOCK_BOOTTIME:
+		if (compat_put_timespec(&rtn_tp, tp))
+			return -EFAULT;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
 COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 		       struct compat_timespec __user *, rqtp,
 		       struct compat_timespec __user *, rmtp)
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index e82bb1f..61a5fb9 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1082,8 +1082,66 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
 	return err;
 }
 
+SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
+		struct timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 rtn_tp64;
+	struct timespec rtn_tp;
+	int error;
+
+	if (!kc)
+		return -EINVAL;
+
+	error = kc->clock_getres(which_clock, &rtn_tp64);
+	rtn_tp = timespec64_to_timespec(rtn_tp64);
+
+	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+		error = -EFAULT;
+
+	return error;
+}
+
 #ifdef CONFIG_COMPAT
 
+COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 new_tp64;
+	struct timespec new_tp;
+
+	if (!kc || !kc->clock_set)
+		return -EINVAL;
+
+	if (compat_get_timespec(&new_tp, tp))
+		return -EFAULT;
+
+	new_tp64 = timespec_to_timespec64(new_tp);
+
+	return kc->clock_set(which_clock, &new_tp64);
+}
+
+COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
+{
+	const struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timespec64 kernel_tp64;
+	struct timespec kernel_tp;
+	int error;
+
+	if (!kc)
+		return -EINVAL;
+
+	error = kc->clock_get(which_clock, &kernel_tp64);
+	kernel_tp = timespec64_to_timespec(kernel_tp64);
+
+	if (!error && compat_put_timespec(&kernel_tp, tp))
+		error = -EFAULT;
+
+	return error;
+}
+
 COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
 		       struct compat_timex __user *, utp)
 {
@@ -1107,10 +1165,9 @@ COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
 
 	return err;
 }
-#endif
 
-SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
-		struct timespec __user *, tp)
+COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
+		       struct compat_timespec __user *, tp)
 {
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec64 rtn_tp64;
@@ -1123,11 +1180,12 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 	error = kc->clock_getres(which_clock, &rtn_tp64);
 	rtn_tp = timespec64_to_timespec(rtn_tp64);
 
-	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
+	if (!error && tp && compat_put_timespec(&rtn_tp, tp))
 		error = -EFAULT;
 
 	return error;
 }
+#endif
 
 /*
  * nanosleep for monotonic and realtime clocks

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] posix-timers: Move compat_timer_create() to native, get rid of set_fs()
  2017-06-07  8:42   ` [PATCH 14/16] timer_create(): move compat to native, get rid of set_fs() Al Viro
@ 2017-06-13 22:11     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:11 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, mingo, hpa, linux-kernel, john.stultz, viro, tglx

Commit-ID:  2482097c6c0f01ad74c9b2cff120a519ac59846e
Gitweb:     http://git.kernel.org/tip/2482097c6c0f01ad74c9b2cff120a519ac59846e
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:39 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:45 +0200

posix-timers: Move compat_timer_create() to native, get rid of set_fs()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-14-viro@ZenIV.linux.org.uk

---
 kernel/compat.c            | 18 --------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 59 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 42 insertions(+), 36 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 582c38b..4544eb6 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -580,24 +580,6 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
 	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
-		       struct compat_sigevent __user *, timer_event_spec,
-		       timer_t __user *, created_timer_id)
-{
-	struct sigevent __user *event = NULL;
-
-	if (timer_event_spec) {
-		struct sigevent kevent;
-
-		event = compat_alloc_user_space(sizeof(*event));
-		if (get_compat_sigevent(&kevent, timer_event_spec) ||
-		    copy_to_user(event, &kevent, sizeof(*event)))
-			return -EFAULT;
-	}
-
-	return sys_timer_create(which_clock, event, created_timer_id);
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index a375c31..38f3b20 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -41,6 +41,7 @@ SYS_NI(setitimer);
 #ifdef __ARCH_WANT_SYS_ALARM
 SYS_NI(alarm);
 #endif
+COMPAT_SYS_NI(timer_create);
 COMPAT_SYS_NI(clock_adjtime);
 COMPAT_SYS_NI(timer_settime);
 COMPAT_SYS_NI(timer_gettime);
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 61a5fb9..c9f45a8 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -490,15 +490,12 @@ static int common_timer_create(struct k_itimer *new_timer)
 }
 
 /* Create a POSIX.1b interval timer. */
-
-SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
-		struct sigevent __user *, timer_event_spec,
-		timer_t __user *, created_timer_id)
+static int do_timer_create(clockid_t which_clock, struct sigevent *event,
+			   timer_t __user *created_timer_id)
 {
 	const struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct k_itimer *new_timer;
 	int error, new_timer_id;
-	sigevent_t event;
 	int it_id_set = IT_ID_NOT_SET;
 
 	if (!kc)
@@ -523,29 +520,25 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 	new_timer->kclock = kc;
 	new_timer->it_overrun = -1;
 
-	if (timer_event_spec) {
-		if (copy_from_user(&event, timer_event_spec, sizeof (event))) {
-			error = -EFAULT;
-			goto out;
-		}
+	if (event) {
 		rcu_read_lock();
-		new_timer->it_pid = get_pid(good_sigevent(&event));
+		new_timer->it_pid = get_pid(good_sigevent(event));
 		rcu_read_unlock();
 		if (!new_timer->it_pid) {
 			error = -EINVAL;
 			goto out;
 		}
+		new_timer->it_sigev_notify     = event->sigev_notify;
+		new_timer->sigq->info.si_signo = event->sigev_signo;
+		new_timer->sigq->info.si_value = event->sigev_value;
 	} else {
-		memset(&event.sigev_value, 0, sizeof(event.sigev_value));
-		event.sigev_notify = SIGEV_SIGNAL;
-		event.sigev_signo = SIGALRM;
-		event.sigev_value.sival_int = new_timer->it_id;
+		new_timer->it_sigev_notify     = SIGEV_SIGNAL;
+		new_timer->sigq->info.si_signo = SIGALRM;
+		memset(&new_timer->sigq->info.si_value, 0, sizeof(sigval_t));
+		new_timer->sigq->info.si_value.sival_int = new_timer->it_id;
 		new_timer->it_pid = get_pid(task_tgid(current));
 	}
 
-	new_timer->it_sigev_notify     = event.sigev_notify;
-	new_timer->sigq->info.si_signo = event.sigev_signo;
-	new_timer->sigq->info.si_value = event.sigev_value;
 	new_timer->sigq->info.si_tid   = new_timer->it_id;
 	new_timer->sigq->info.si_code  = SI_TIMER;
 
@@ -576,6 +569,36 @@ out:
 	return error;
 }
 
+SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
+		struct sigevent __user *, timer_event_spec,
+		timer_t __user *, created_timer_id)
+{
+	if (timer_event_spec) {
+		sigevent_t event;
+
+		if (copy_from_user(&event, timer_event_spec, sizeof (event)))
+			return -EFAULT;
+		return do_timer_create(which_clock, &event, created_timer_id);
+	}
+	return do_timer_create(which_clock, NULL, created_timer_id);
+}
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
+		       struct compat_sigevent __user *, timer_event_spec,
+		       timer_t __user *, created_timer_id)
+{
+	if (timer_event_spec) {
+		sigevent_t event;
+
+		if (get_compat_sigevent(&event, timer_event_spec))
+			return -EFAULT;
+		return do_timer_create(which_clock, &event, created_timer_id);
+	}
+	return do_timer_create(which_clock, NULL, created_timer_id);
+}
+#endif
+
 /*
  * Locking issues: We need to protect the result of the id look up until
  * we get the timer locked down so it is not deleted under us.  The

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] time: Move compat_time()/stime() to native
  2017-06-07  8:42   ` [PATCH 15/16] time()/stime(): move compat to native Al Viro
@ 2017-06-13 22:11     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:11 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, john.stultz, peterz, tglx, mingo, linux-kernel, viro

Commit-ID:  b180db2c8ca6692a10b79631cadc18d03303d494
Gitweb:     http://git.kernel.org/tip/b180db2c8ca6692a10b79631cadc18d03303d494
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:40 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:45 +0200

time: Move compat_time()/stime() to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-15-viro@ZenIV.linux.org.uk

---
 kernel/compat.c    | 40 ----------------------------------------
 kernel/time/time.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index 4544eb6..aa7b9a2 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -739,46 +739,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 	return ret;
 }
 
-#ifdef __ARCH_WANT_COMPAT_SYS_TIME
-
-/* compat_time_t is a 32 bit "long" and needs to get converted. */
-
-COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
-{
-	compat_time_t i;
-	struct timeval tv;
-
-	do_gettimeofday(&tv);
-	i = tv.tv_sec;
-
-	if (tloc) {
-		if (put_user(i,tloc))
-			return -EFAULT;
-	}
-	force_successful_syscall_return();
-	return i;
-}
-
-COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
-{
-	struct timespec tv;
-	int err;
-
-	if (get_user(tv.tv_sec, tptr))
-		return -EFAULT;
-
-	tv.tv_nsec = 0;
-
-	err = security_settime(&tv, NULL);
-	if (err)
-		return err;
-
-	do_settimeofday(&tv);
-	return 0;
-}
-
-#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
-
 #ifdef CONFIG_NUMA
 COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
 		       compat_uptr_t __user *, pages32,
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 400662f..e5d4499 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -100,6 +100,47 @@ SYSCALL_DEFINE1(stime, time_t __user *, tptr)
 
 #endif /* __ARCH_WANT_SYS_TIME */
 
+#ifdef CONFIG_COMPAT
+#ifdef __ARCH_WANT_COMPAT_SYS_TIME
+
+/* compat_time_t is a 32 bit "long" and needs to get converted. */
+COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
+{
+	struct timeval tv;
+	compat_time_t i;
+
+	do_gettimeofday(&tv);
+	i = tv.tv_sec;
+
+	if (tloc) {
+		if (put_user(i,tloc))
+			return -EFAULT;
+	}
+	force_successful_syscall_return();
+	return i;
+}
+
+COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
+{
+	struct timespec tv;
+	int err;
+
+	if (get_user(tv.tv_sec, tptr))
+		return -EFAULT;
+
+	tv.tv_nsec = 0;
+
+	err = security_settime(&tv, NULL);
+	if (err)
+		return err;
+
+	do_settimeofday(&tv);
+	return 0;
+}
+
+#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
+#endif
+
 SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
 		struct timezone __user *, tz)
 {

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [tip:timers/core] time: Move compat_gettimeofday()/settimeofday() to native
  2017-06-07  8:42   ` [PATCH 16/16] gettimeofday()/settimeofday(): move compat " Al Viro
@ 2017-06-13 22:12     ` tip-bot for Al Viro
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Al Viro @ 2017-06-13 22:12 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, mingo, john.stultz, hpa, linux-kernel, viro, tglx

Commit-ID:  2b2d02856b3176701c91d723356f766d6ee27853
Gitweb:     http://git.kernel.org/tip/2b2d02856b3176701c91d723356f766d6ee27853
Author:     Al Viro <viro@zeniv.linux.org.uk>
AuthorDate: Wed, 7 Jun 2017 09:42:41 +0100
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 14 Jun 2017 00:00:46 +0200

time: Move compat_gettimeofday()/settimeofday() to native

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170607084241.28657-16-viro@ZenIV.linux.org.uk

---
 kernel/compat.c    | 38 --------------------------------------
 kernel/time/time.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/kernel/compat.c b/kernel/compat.c
index aa7b9a2..ebd8bdc 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -92,44 +92,6 @@ int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc)
 	return 0;
 }
 
-COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
-		       struct timezone __user *, tz)
-{
-	if (tv) {
-		struct timeval ktv;
-		do_gettimeofday(&ktv);
-		if (compat_put_timeval(&ktv, tv))
-			return -EFAULT;
-	}
-	if (tz) {
-		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
-		       struct timezone __user *, tz)
-{
-	struct timespec64 new_ts;
-	struct timeval user_tv;
-	struct timezone new_tz;
-
-	if (tv) {
-		if (compat_get_timeval(&user_tv, tv))
-			return -EFAULT;
-		new_ts.tv_sec = user_tv.tv_sec;
-		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
-	}
-	if (tz) {
-		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
-			return -EFAULT;
-	}
-
-	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
-}
-
 static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
 {
 	return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
diff --git a/kernel/time/time.c b/kernel/time/time.c
index e5d4499..7c89e43 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -257,6 +257,47 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
 	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
+		       struct timezone __user *, tz)
+{
+	if (tv) {
+		struct timeval ktv;
+
+		do_gettimeofday(&ktv);
+		if (compat_put_timeval(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
+		       struct timezone __user *, tz)
+{
+	struct timespec64 new_ts;
+	struct timeval user_tv;
+	struct timezone new_tz;
+
+	if (tv) {
+		if (compat_get_timeval(&user_tv, tv))
+			return -EFAULT;
+		new_ts.tv_sec = user_tv.tv_sec;
+		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
+	}
+	if (tz) {
+		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
+}
+#endif
+
 SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
 {
 	struct timex txc;		/* Local copy of parameter */

^ permalink raw reply related	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2017-06-13 22:16 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-07  8:41 [PATCHSET] sanitizing compat nanosleep and other timer-related syscalls Al Viro
2017-06-07  8:42 ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Al Viro
2017-06-07  8:42   ` [PATCH 02/16] move copyout and freeze handling into alarmtimer_do_nsleep() Al Viro
2017-06-13 22:04     ` [tip:timers/core] alarmtimer: Move " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 03/16] hrtimer_nanosleep(): pass rmtp in restart_block Al Viro
2017-06-13 22:05     ` [tip:timers/core] hrtimer_nanosleep(): Pass " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 04/16] move copyout to do_nanosleel() Al Viro
2017-06-13 22:05     ` [tip:timers/core] hrtimer: Move copyout of remaining time to do_nanosleep() tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 05/16] clock_nanosleep(): stash rmtp into restart_block Al Viro
2017-06-13 22:06     ` [tip:timers/core] posix-timers: Store rmtp into restart_block in sys_clock_nanosleep() tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts Al Viro
2017-06-07 10:07     ` Peter Zijlstra
2017-06-13 22:06     ` [tip:timers/core] time/posix-timers: Move the compat copyouts to the nanosleep implementations tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 07/16] {clock_,}nanosleep(2): merge timespec copyout logics into a new helper Al Viro
2017-06-13 22:07     ` [tip:timers/core] hrtimers/posix-timers: Merge nanosleep " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 08/16] kill ->nsleep_restart() Al Viro
2017-06-13 22:08     ` [tip:timers/core] posix-timers: Kill ->nsleep_restart() tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 09/16] move adjtimex-related compat syscalls to native counterparts Al Viro
2017-06-13 22:08     ` [tip:timers/core] ntp: Move adjtimex related " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 10/16] take compat timer_settime(2) to native one Al Viro
2017-06-13 22:09     ` [tip:timers/core] posix-timers: Take " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 11/16] take compat timer_gettime(2) " Al Viro
2017-06-13 22:09     ` [tip:timers/core] posix-timers: Take " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 12/16] move compat itimer syscalls to native ones Al Viro
2017-06-13 22:10     ` [tip:timers/core] itimers: Move " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 13/16] clock_gettime/clock_settime/clock_getres: move to native syscalls Al Viro
2017-06-13 22:10     ` [tip:timers/core] posix-timers: Move compat versions of clock_gettime/settime/getres tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 14/16] timer_create(): move compat to native, get rid of set_fs() Al Viro
2017-06-13 22:11     ` [tip:timers/core] posix-timers: Move compat_timer_create() " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 15/16] time()/stime(): move compat to native Al Viro
2017-06-13 22:11     ` [tip:timers/core] time: Move compat_time()/stime() " tip-bot for Al Viro
2017-06-07  8:42   ` [PATCH 16/16] gettimeofday()/settimeofday(): move compat " Al Viro
2017-06-13 22:12     ` [tip:timers/core] time: Move compat_gettimeofday()/settimeofday() " tip-bot for Al Viro
2017-06-12 23:08   ` [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep() Thomas Gleixner
2017-06-13  7:46     ` Thomas Gleixner
2017-06-13 22:04   ` [tip:timers/core] posix-cpu-timers: Move " tip-bot for Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).