Skip to contentSkip to conversation

sanitizing compat nanosleep and other timer-related syscalls

PATCH New Al Viro 4 participants 36 messages Jun 7, 2017 – Jun 13, 2017

Subsystems (3)
lore
Share & tools
lore

Al Viro

author
#0 lore raw

PATCH 1/1 sanitizing compat nanosleep and other timer-related syscalls

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

author
#1 lore raw

PATCH 1/16 move copyout of timespec into do_cpu_nanosleep()

From: Al Viro <[email protected]>

---
 kernel/time/posix-cpu-timers.c | 62 ++++++++++++++++++------------------------
 1 file changed, 27 insertions(+), 35 deletions(-)
kernel/time/posix-cpu-timers.c +27 -35
index cb4a4eb44279..ef1f2bdc896e 100644
@@ -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)
Signature · 1 line
2.11.0
author
#2 lore raw

PATCH 2/16 move copyout and freeze handling into alarmtimer_do_nsleep()

From: Al Viro <[email protected]>

---
 kernel/time/alarmtimer.c | 102 +++++++++++++++--------------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)
kernel/time/alarmtimer.c +32 -70
index d8a7a7e214de..ac6e9bc6cc59 100644
@@ -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;
 }
 
Signature · 1 line
2.11.0
#3 lore raw

[tip:timers/core] alarmtimer: Move copyout and freeze handling into alarmtimer_do_nsleep()

alarmtimer: Move copyout and freeze handling into alarmtimer_do_nsleep()
Commit-ID:  15f27ce24cb613e6e01ce27c4094c55e55dde5d4
Gitweb:     http://git.kernel.org/tip/15f27ce24cb613e6e01ce27c4094c55e55dde5d4
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:27 +0100
Committer:  Thomas Gleixner <[email protected]>
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 ]

---
 kernel/time/alarmtimer.c | 102 +++++++++++++++--------------------------------
 1 file changed, 32 insertions(+), 70 deletions(-)
kernel/time/alarmtimer.c +32 -70
index d8a7a7e..ac6e9bc 100644
@@ -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;
 }
 
author
#4 lore raw

PATCH 3/16 hrtimer_nanosleep(): pass rmtp in restart_block

In reply to Al Viro

From: Al Viro <[email protected]>

---
 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(-)
include/linux/hrtimer.h +0 -1
index 8c5b10eb7265..b80c34f6fd4b 100644
@@ -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);
kernel/compat.c +3 -3
index 933bcb31ae10..cc9ba9d29b47 100644
@@ -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);
 
 	/*
kernel/time/hrtimer.c +6 -5
index ac053bb5296e..4ae777f159de 100644
@@ -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);
 }
 
 /*
kernel/time/posix-stubs.c +4 -1
index c0cd53eb018a..156a5e6f3bd2 100644
@@ -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:
kernel/time/posix-timers.c +4 -1
index 6e7a70b1bf37..5108023a5f3b 100644
@@ -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);
 }
Signature · 1 line
2.11.0
#5 lore raw

[tip:timers/core] hrtimer_nanosleep(): Pass rmtp in restart_block

hrtimer_nanosleep(): Pass rmtp in restart_block
Commit-ID:  192a82f9003fe8fabd6088aa646e829225a94c55
Gitweb:     http://git.kernel.org/tip/192a82f9003fe8fabd6088aa646e829225a94c55
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:28 +0100
Committer:  Thomas Gleixner <[email protected]>
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 ]

---
 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(-)
include/linux/hrtimer.h +0 -1
index 8c5b10e..b80c34f 100644
@@ -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);
kernel/compat.c +3 -3
index 933bcb3..cc9ba9d 100644
@@ -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);
 
 	/*
kernel/time/hrtimer.c +6 -5
index ac053bb..4ae777f 100644
@@ -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);
 }
 
 /*
kernel/time/posix-stubs.c +4 -1
index c0cd53e..156a5e6 100644
@@ -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:
kernel/time/posix-timers.c +4 -1
index 58c0f60..1a9f59f 100644
@@ -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);
 }
author
#6 lore raw

PATCH 4/16 move copyout to do_nanosleel()

In reply to Al Viro

From: Al Viro <[email protected]>

---
 kernel/time/hrtimer.c | 62 +++++++++++++++++----------------------------------
 1 file changed, 20 insertions(+), 42 deletions(-)
kernel/time/hrtimer.c +20 -42
index 4ae777f159de..baa7b846b6e3 100644
@@ -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;
Signature · 1 line
2.11.0
#7 lore raw

[tip:timers/core] hrtimer: Move copyout of remaining time to do_nanosleep()

hrtimer: Move copyout of remaining time to do_nanosleep()
Commit-ID:  a7602681fc63f1a3ddd3da336296c9634c2ff974
Gitweb:     http://git.kernel.org/tip/a7602681fc63f1a3ddd3da336296c9634c2ff974
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:29 +0100
Committer:  Thomas Gleixner <[email protected]>
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 ]

---
 kernel/time/hrtimer.c | 62 +++++++++++++++++----------------------------------
 1 file changed, 20 insertions(+), 42 deletions(-)
kernel/time/hrtimer.c +20 -42
index 4ae777f..baa7b84 100644
@@ -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;
author
#8 lore raw

PATCH 5/16 clock_nanosleep(): stash rmtp into restart_block

In reply to Al Viro

From: Al Viro <[email protected]>

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

---
 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(-)
kernel/time/alarmtimer.c +1 -7
index ac6e9bc6cc59..d859a3601ddd 100644
@@ -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;
 
kernel/time/posix-cpu-timers.c +3 -9
index ef1f2bdc896e..f999b3ebba7e 100644
@@ -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)
 {
kernel/time/posix-timers.c +5 -5
index 5108023a5f3b..f39ed4bdcc5a 100644
@@ -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);
 }
 
 /*
kernel/time/posix-timers.h +1 -1
index b086f5ba2f5b..bfd9e15c6ce0 100644
@@ -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,
Signature · 1 line
2.11.0
#9 lore raw

[tip:timers/core] posix-timers: Store rmtp into restart_block in sys_clock_nanosleep()

posix-timers: Store rmtp into restart_block in sys_clock_nanosleep()
Commit-ID:  99e6c0e6ec349575886ca7daffc9cb7ec583176f
Gitweb:     http://git.kernel.org/tip/99e6c0e6ec349575886ca7daffc9cb7ec583176f
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:30 +0100
Committer:  Thomas Gleixner <[email protected]>
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

---
 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(-)
kernel/time/alarmtimer.c +1 -7
index ac6e9bc..d859a36 100644
@@ -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;
 
kernel/time/posix-cpu-timers.c +3 -9
index 239fff9..ec6258c 100644
@@ -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)
 {
kernel/time/posix-timers.c +5 -5
index 1a9f59f..a3e5c01 100644
@@ -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);
 }
 
 /*
kernel/time/posix-timers.h +1 -1
index b086f5b..bfd9e15 100644
@@ -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,
author
#10 lore raw

PATCH 6/16 nanosleep/clock_nanosleep: teach to do compat copyouts

In reply to Al Viro

From: Al Viro <[email protected]>

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.

---
 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(-)
include/linux/posix-timers.h +0 -2
index 667095dbcd37..29f1b7f09ced 100644
@@ -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);
include/linux/restart_block.h +5 -2
index 0d905d8ec553..4509944bd953 100644
@@ -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 */
kernel/compat.c +0 -131

143 lines not on this page · raw message

kernel/time/alarmtimer.c +12 -4
index d859a3601ddd..868083ae7434 100644
@@ -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;
kernel/time/hrtimer.c +34 -4
index baa7b846b6e3..5534606e3985 100644
@@ -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:
  */
kernel/time/posix-cpu-timers.c +13 -5
index f999b3ebba7e..b88bc3fc56c5 100644
@@ -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);
kernel/time/posix-stubs.c +27 -2
index 156a5e6f3bd2..2fe2322d1243 100644
@@ -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
kernel/time/posix-timers.c +24 -8
index f39ed4bdcc5a..b729e1c0b57d 100644
@@ -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,
Signature · 1 line
2.11.0
#11 lore raw

Re: [PATCH 06/16] nanosleep/clock_nanosleep: teach to do compat copyouts

Quoted 7 lines · Al Viro

From: Al Viro <[email protected]>

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(-)
include/linux/restart_block.h +9 -1
index 4509944bd953..0834e4a8ce69 100644
@@ -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
kernel/time/alarmtimer.c +1 -1
index 80154e795535..734920be9d4b 100644
@@ -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;
 
kernel/time/hrtimer.c +15 -8
index 5dd4b3a34495..e1e06a8b6c43 100644
@@ -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);
 }
kernel/time/posix-cpu-timers.c +1 -1
index f6c5f77b944d..929499e6b4ac 100644
@@ -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);
kernel/time/posix-stubs.c +2 -2
index c0c18701a4da..4b54dcf8d517 100644
@@ -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,
kernel/time/posix-timers.c +2 -2
index 014e6ff8982e..3c85d6762690 100644
@@ -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);
#12 lore raw

[tip:timers/core] time/posix-timers: Move the compat copyouts to the nanosleep implementations

In reply to Al Viro
time/posix-timers: Move the compat copyouts to the nanosleep implementations
Commit-ID:  edbeda46322fbcb15af2d2d0f2daffb0cd349a5a
Gitweb:     http://git.kernel.org/tip/edbeda46322fbcb15af2d2d0f2daffb0cd349a5a
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:31 +0100
Committer:  Thomas Gleixner <[email protected]>
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 ]

---
 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(-)
include/linux/posix-timers.h +0 -2
index 667095d..29f1b7f 100644
@@ -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);
include/linux/restart_block.h +13 -2
index 0d905d8..19df8422 100644
@@ -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 */
kernel/compat.c +0 -131

143 lines not on this page · raw message

kernel/time/alarmtimer.c +12 -4
index d859a36..57bcf94 100644
@@ -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;
kernel/time/hrtimer.c +37 -5

75 lines not on this page · raw message

kernel/time/posix-cpu-timers.c +14 -6
index ec6258c..1563ca2 100644
@@ -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);
kernel/time/posix-stubs.c +42 -13

73 lines not on this page · raw message

kernel/time/posix-timers.c +24 -8
index a3e5c01..bec86b6 100644
@@ -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,
author
#13 lore raw

PATCH 7/16 {clock_,}nanosleep(2): merge timespec copyout logics into a new helper

In reply to Al Viro

From: Al Viro <[email protected]>

---
 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(-)
include/linux/hrtimer.h +2 -0
index b80c34f6fd4b..38b968f3df4e 100644
@@ -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);
kernel/time/alarmtimer.c +1 -9
index 868083ae7434..80154e795535 100644
@@ -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;
 }
kernel/time/hrtimer.c +15 -9
index 5534606e3985..6c19995e977e 100644
@@ -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;
 }
kernel/time/posix-cpu-timers.c +2 -11
index b88bc3fc56c5..ba0d7e34616b 100644
@@ -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;
Signature · 1 line
2.11.0
#14 lore raw

[tip:timers/core] hrtimers/posix-timers: Merge nanosleep timespec copyout logics into a new helper

hrtimers/posix-timers: Merge nanosleep timespec copyout logics into a new helper
Commit-ID:  ce41aaf47af3d28c4c958e07675a3e0a51f09bd3
Gitweb:     http://git.kernel.org/tip/ce41aaf47af3d28c4c958e07675a3e0a51f09bd3
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:32 +0100
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 14 Jun 2017 00:00:42 +0200

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

---
 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(-)
include/linux/hrtimer.h +2 -0
index b80c34f..38b968f 100644
@@ -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);
kernel/time/alarmtimer.c +1 -9
index 57bcf94..7bed4e4 100644
@@ -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;
 }
kernel/time/hrtimer.c +20 -9
index 5370da8..db2f5f7 100644
@@ -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;
 }
kernel/time/posix-cpu-timers.c +2 -11
index 1563ca2..993a924 100644
@@ -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;
author
#15 lore raw

PATCH 8/16 kill ->nsleep_restart()

In reply to Al Viro

From: Al Viro <[email protected]>

---
 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(-)
include/linux/hrtimer.h +0 -1
index 38b968f3df4e..d83b7ed1cb0e 100644
@@ -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);
kernel/time/hrtimer.c +1 -1
index 6c19995e977e..5dd4b3a34495 100644
@@ -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;
kernel/time/posix-cpu-timers.c +0 -6
index ba0d7e34616b..f6c5f77b944d 100644
@@ -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 = {
kernel/time/posix-timers.c +0 -4
index b729e1c0b57d..922acf713cc0 100644
@@ -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,
kernel/time/posix-timers.h +0 -1
index bfd9e15c6ce0..5e69bb85629f 100644
@@ -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);
Signature · 1 line
2.11.0
#16 lore raw

[tip:timers/core] posix-timers: Kill ->nsleep_restart()

posix-timers: Kill ->nsleep_restart()
Commit-ID:  fb923c4a3c2ee735755d4a93522150fc35d0ecbd
Gitweb:     http://git.kernel.org/tip/fb923c4a3c2ee735755d4a93522150fc35d0ecbd
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:33 +0100
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 14 Jun 2017 00:00:42 +0200

posix-timers: Kill ->nsleep_restart()

No more users.

---
 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(-)
include/linux/hrtimer.h +0 -1
index 38b968f..d83b7ed 100644
@@ -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);
kernel/time/hrtimer.c +1 -1
index db2f5f7..45f83cc 100644
@@ -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;
kernel/time/posix-cpu-timers.c +0 -6
index 993a924..515148d 100644
@@ -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 = {
kernel/time/posix-timers.c +0 -4
index bec86b6..ea4a463 100644
@@ -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,
kernel/time/posix-timers.h +0 -1
index bfd9e15..5e69bb8 100644
@@ -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);
author
#17 lore raw

PATCH 9/16 move adjtimex-related compat syscalls to native counterparts

In reply to Al Viro

From: Al Viro <[email protected]>

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

---
 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(-)
include/linux/compat.h +4 -0
index 1c5f3152cbb5..ecb8dd261d36 100644
@@ -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 {
kernel/compat.c +52 -89

165 lines not on this page · raw message

kernel/time/posix-stubs.c +2 -0
index 2fe2322d1243..9b1c8f71d164 100644
@@ -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
kernel/time/posix-timers.c +27 -0
index 922acf713cc0..d08a2fdeabf9 100644
@@ -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)
 {
kernel/time/time.c +23 -1
index 49c73c6ed648..400662f16c5a 100644
@@ -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.
  *
Signature · 1 line
2.11.0
#18 lore raw

[tip:timers/core] ntp: Move adjtimex related compat syscalls to native counterparts

ntp: Move adjtimex related compat syscalls to native counterparts
Commit-ID:  3a4d44b6162555070194e486ff6b3799a8d323a2
Gitweb:     http://git.kernel.org/tip/3a4d44b6162555070194e486ff6b3799a8d323a2
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:34 +0100
Committer:  Thomas Gleixner <[email protected]>
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.

---
 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(-)
include/linux/compat.h +4 -0
index 1c5f315..ecb8dd2 100644
@@ -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 {
kernel/compat.c +52 -89

165 lines not on this page · raw message

kernel/time/posix-stubs.c +2 -0
index 749b76f..954d1d8 100644
@@ -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
kernel/time/posix-timers.c +27 -0
index ea4a463..b1b6d52 100644
@@ -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)
 {
kernel/time/time.c +23 -1
index 49c73c6..400662f 100644
@@ -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.
  *
author
#19 lore raw

PATCH 10/16 take compat timer_settime(2) to native one

In reply to Al Viro

From: Al Viro <[email protected]>

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

---
 kernel/compat.c            | 23 -------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 83 ++++++++++++++++++++++++++++++++++------------
 3 files changed, 62 insertions(+), 45 deletions(-)
kernel/compat.c +0 -23
index 97087b333543..df39e2e00c47 100644
@@ -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)
 {
kernel/time/posix-stubs.c +1 -0
index 9b1c8f71d164..e65c468c20b5 100644
@@ -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
kernel/time/posix-timers.c +61 -22

111 lines not on this page · raw message

Signature · 1 line
2.11.0
#20 lore raw

[tip:timers/core] posix-timers: Take compat timer_settime(2) to native one

posix-timers: Take compat timer_settime(2) to native one
Commit-ID:  1acbe7708b0313b33287bb4ffcbf26462ea3c588
Gitweb:     http://git.kernel.org/tip/1acbe7708b0313b33287bb4ffcbf26462ea3c588
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:35 +0100
Committer:  Thomas Gleixner <[email protected]>
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

---
 kernel/compat.c            | 23 ------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 87 +++++++++++++++++++++++++++++++++-------------
 3 files changed, 64 insertions(+), 47 deletions(-)
kernel/compat.c +0 -23
index 97087b3..df39e2e 100644
@@ -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)
 {
kernel/time/posix-stubs.c +1 -0
index 954d1d8..ad263df 100644
@@ -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
kernel/time/posix-timers.c +63 -24

116 lines not on this page · raw message

author
#21 lore raw

PATCH 11/16 take compat timer_gettime(2) to native one

In reply to Al Viro

From: Al Viro <[email protected]>

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

---
 kernel/compat.c            | 17 -----------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 44 +++++++++++++++++++++++++++++++++++---------
 3 files changed, 36 insertions(+), 26 deletions(-)
kernel/compat.c +0 -17
index df39e2e00c47..1fb8cf7e691e 100644
@@ -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)
 {
kernel/time/posix-stubs.c +1 -0
index e65c468c20b5..c6d3cde2edc6 100644
@@ -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
kernel/time/posix-timers.c +35 -9

67 lines not on this page · raw message

Signature · 1 line
2.11.0
#22 lore raw

[tip:timers/core] posix-timers: Take compat timer_gettime(2) to native one

posix-timers: Take compat timer_gettime(2) to native one
Commit-ID:  b0dc12426ec404de99d7e75a12a22d9201d90914
Gitweb:     http://git.kernel.org/tip/b0dc12426ec404de99d7e75a12a22d9201d90914
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:36 +0100
Committer:  Thomas Gleixner <[email protected]>
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

---
 kernel/compat.c            | 17 -----------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 43 ++++++++++++++++++++++++++++++++++---------
 3 files changed, 35 insertions(+), 26 deletions(-)
kernel/compat.c +0 -17
index df39e2e..1fb8cf7 100644
@@ -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)
 {
kernel/time/posix-stubs.c +1 -0
index ad263df..f4a1962 100644
@@ -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
kernel/time/posix-timers.c +34 -9

66 lines not on this page · raw message

author
#23 lore raw

PATCH 12/16 move compat itimer syscalls to native ones

In reply to Al Viro

From: Al Viro <[email protected]>

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

---
 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(-)
include/linux/compat.h +4 -0
index ecb8dd261d36..425563c7647b 100644
@@ -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;
kernel/compat.c +16 -55

81 lines not on this page · raw message

kernel/time/itimer.c +36 -0
index 087d6a1279b8..b23c48dde3da 100644
@@ -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
kernel/time/posix-stubs.c +2 -0
index c6d3cde2edc6..369df2f9a9ff 100644
@@ -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
Signature · 1 line
2.11.0
#24 lore raw

[tip:timers/core] itimers: Move compat itimer syscalls to native ones

itimers: Move compat itimer syscalls to native ones
Commit-ID:  54ad9c46c262ce4a603dc7887e37956896a0211d
Gitweb:     http://git.kernel.org/tip/54ad9c46c262ce4a603dc7887e37956896a0211d
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:37 +0100
Committer:  Thomas Gleixner <[email protected]>
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.

---
 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(-)
include/linux/compat.h +4 -0
index ecb8dd2..425563c 100644
@@ -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;
kernel/compat.c +16 -53

81 lines not on this page · raw message

kernel/time/itimer.c +38 -0
index 087d6a1..9dd7ff5 100644
@@ -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
kernel/time/posix-stubs.c +2 -0
index f4a1962..7f88517 100644
@@ -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
author
#25 lore raw

PATCH 13/16 clock_gettime/clock_settime/clock_getres: move to native syscalls

In reply to Al Viro

From: Al Viro <[email protected]>

---
 kernel/compat.c            | 51 -----------------------------------
 kernel/time/posix-stubs.c  | 52 ++++++++++++++++++++++++++++++++++++
 kernel/time/posix-timers.c | 66 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 114 insertions(+), 55 deletions(-)
kernel/compat.c +0 -51
index 61e3be4cbd2a..e19ea2f06212 100644
@@ -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
kernel/time/posix-stubs.c +52 -0

58 lines not on this page · raw message

kernel/time/posix-timers.c +62 -4

91 lines not on this page · raw message

Signature · 1 line
2.11.0
#26 lore raw

[tip:timers/core] posix-timers: Move compat versions of clock_gettime/settime/getres

posix-timers: Move compat versions of clock_gettime/settime/getres
Commit-ID:  d822cdcce43f9d4dcddbf9c68f9537d542ccc3c3
Gitweb:     http://git.kernel.org/tip/d822cdcce43f9d4dcddbf9c68f9537d542ccc3c3
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:38 +0100
Committer:  Thomas Gleixner <[email protected]>
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.

---
 kernel/compat.c            | 51 -----------------------------------
 kernel/time/posix-stubs.c  | 53 +++++++++++++++++++++++++++++++++++++
 kernel/time/posix-timers.c | 66 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 115 insertions(+), 55 deletions(-)
kernel/compat.c +0 -51
index c349417..582c38b 100644
@@ -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
kernel/time/posix-stubs.c +53 -0

59 lines not on this page · raw message

kernel/time/posix-timers.c +62 -4

91 lines not on this page · raw message

author
#27 lore raw

PATCH 14/16 timer_create(): move compat to native, get rid of set_fs()

In reply to Al Viro

From: Al Viro <[email protected]>

---
 kernel/compat.c            | 18 ---------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 57 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 41 insertions(+), 35 deletions(-)
kernel/compat.c +0 -18
index e19ea2f06212..92ba0afafddc 100644
@@ -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
kernel/time/posix-stubs.c +1 -0
index ce45ab06fb3e..c0c18701a4da 100644
@@ -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);
kernel/time/posix-timers.c +40 -17

89 lines not on this page · raw message

Signature · 1 line
2.11.0
#28 lore raw

[tip:timers/core] posix-timers: Move compat_timer_create() to native, get rid of set_fs()

posix-timers: Move compat_timer_create() to native, get rid of set_fs()
Commit-ID:  2482097c6c0f01ad74c9b2cff120a519ac59846e
Gitweb:     http://git.kernel.org/tip/2482097c6c0f01ad74c9b2cff120a519ac59846e
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:39 +0100
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 14 Jun 2017 00:00:45 +0200

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

---
 kernel/compat.c            | 18 --------------
 kernel/time/posix-stubs.c  |  1 +
 kernel/time/posix-timers.c | 59 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 42 insertions(+), 36 deletions(-)
kernel/compat.c +0 -18
index 582c38b..4544eb6 100644
@@ -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
kernel/time/posix-stubs.c +1 -0
index a375c31..38f3b20 100644
@@ -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);
kernel/time/posix-timers.c +41 -18

91 lines not on this page · raw message

author
#29 lore raw

PATCH 15/16 time()/stime(): move compat to native

In reply to Al Viro

From: Al Viro <[email protected]>

---
 kernel/compat.c    | 40 ----------------------------------------
 kernel/time/time.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 40 deletions(-)
kernel/compat.c +0 -40
index 92ba0afafddc..a56aa5777987 100644
@@ -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,
kernel/time/time.c +42 -0

48 lines not on this page · raw message

Signature · 1 line
2.11.0
#30 lore raw

[tip:timers/core] time: Move compat_time()/stime() to native

time: Move compat_time()/stime() to native
Commit-ID:  b180db2c8ca6692a10b79631cadc18d03303d494
Gitweb:     http://git.kernel.org/tip/b180db2c8ca6692a10b79631cadc18d03303d494
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:40 +0100
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 14 Jun 2017 00:00:45 +0200

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

---
 kernel/compat.c    | 40 ----------------------------------------
 kernel/time/time.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 40 deletions(-)
kernel/compat.c +0 -40
index 4544eb6..aa7b9a2 100644
@@ -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,
kernel/time/time.c +41 -0

47 lines not on this page · raw message

author
#31 lore raw

PATCH 16/16 gettimeofday()/settimeofday(): move compat to native

In reply to Al Viro

From: Al Viro <[email protected]>

---
 kernel/compat.c    | 38 --------------------------------------
 kernel/time/time.c | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 38 deletions(-)
kernel/compat.c +0 -38
index a56aa5777987..40a388994576 100644
@@ -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)) ||
kernel/time/time.c +40 -0
index 1d5ebf6a8d9e..01dfb07563b6 100644
@@ -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 */
Signature · 1 line
2.11.0
#32 lore raw

[tip:timers/core] time: Move compat_gettimeofday()/settimeofday() to native

time: Move compat_gettimeofday()/settimeofday() to native
Commit-ID:  2b2d02856b3176701c91d723356f766d6ee27853
Gitweb:     http://git.kernel.org/tip/2b2d02856b3176701c91d723356f766d6ee27853
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:41 +0100
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Wed, 14 Jun 2017 00:00:46 +0200

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

---
 kernel/compat.c    | 38 --------------------------------------
 kernel/time/time.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 38 deletions(-)
kernel/compat.c +0 -38
index aa7b9a2..ebd8bdc 100644
@@ -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)) ||
kernel/time/time.c +41 -0

47 lines not on this page · raw message

#33 lore raw

Re: [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep()

In reply to Al Viro
Quoted 4 lines · Al Viro
kernel/time/posix-cpu-timers.c +1 -0
@@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 
 		error = -ERESTART_RESTARTBLOCK;
+		/*

kernel/time/posix-cpu-timers.c static int do_cpu_nanosleep(const clockid_t which_clock, int flags, · line 1255

Quoted 10 lines
kernel/time/posix-cpu-timers.c +10 -0
+		 * 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

#34 lore raw

Re: [PATCH 01/16] move copyout of timespec into do_cpu_nanosleep()

Quoted 18 lines · Thomas Gleixner
Quoted 4 lines · Al Viro
kernel/time/posix-cpu-timers.c +1 -0
@@ -1242,12 +1243,14 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 
 		error = -ERESTART_RESTARTBLOCK;
+		/*

kernel/time/posix-cpu-timers.c static int do_cpu_nanosleep(const clockid_t which_clock, int flags, · line 1255

Quoted 10 lines
kernel/time/posix-cpu-timers.c +10 -0
+		 * 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.

Quoted 5 lines

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

#35 lore raw

[tip:timers/core] posix-cpu-timers: Move copyout of timespec into do_cpu_nanosleep()

In reply to Al Viro
posix-cpu-timers: Move copyout of timespec into do_cpu_nanosleep()
Commit-ID:  86a9c446c13ecd8793ea8599761322aed125d542
Gitweb:     http://git.kernel.org/tip/86a9c446c13ecd8793ea8599761322aed125d542
Author:     Al Viro <[email protected]>
AuthorDate: Wed, 7 Jun 2017 09:42:26 +0100
Committer:  Thomas Gleixner <[email protected]>
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 ]

---
 kernel/time/posix-cpu-timers.c | 63 +++++++++++++++++++-----------------------
 1 file changed, 28 insertions(+), 35 deletions(-)
kernel/time/posix-cpu-timers.c +28 -35
index cb4a4eb..239fff9 100644
@@ -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)