summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/hrtimer.h2
-rw-r--r--kernel/hrtimer.c51
-rw-r--r--kernel/posix-timers.c17
3 files changed, 31 insertions, 39 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 600fc3bcf63..1ad56a7b2f7 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -316,7 +316,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
/* Precise sleep: */
extern long hrtimer_nanosleep(struct timespec *rqtp,
- struct timespec *rmtp,
+ struct timespec __user *rmtp,
const enum hrtimer_mode mode,
const clockid_t clockid);
extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 668f3967eb3..355085f0896 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1319,11 +1319,26 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
return t->task == NULL;
}
+static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
+{
+ struct timespec rmt;
+ ktime_t rem;
+
+ rem = ktime_sub(timer->expires, timer->base->get_time());
+ if (rem.tv64 <= 0)
+ return 0;
+ rmt = ktime_to_timespec(rem);
+
+ if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+ return -EFAULT;
+
+ return 1;
+}
+
long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
{
struct hrtimer_sleeper t;
- struct timespec *rmtp;
- ktime_t time;
+ struct timespec __user *rmtp;
restart->fn = do_no_restart_syscall;
@@ -1333,12 +1348,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
if (do_nanosleep(&t, HRTIMER_MODE_ABS))
return 0;
- rmtp = (struct timespec *)restart->arg1;
+ rmtp = (struct timespec __user *)restart->arg1;
if (rmtp) {
- time = ktime_sub(t.timer.expires, t.timer.base->get_time());
- if (time.tv64 <= 0)
- return 0;
- *rmtp = ktime_to_timespec(time);
+ int ret = update_rmtp(&t.timer, rmtp);
+ if (ret <= 0)
+ return ret;
}
restart->fn = hrtimer_nanosleep_restart;
@@ -1347,12 +1361,11 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
return -ERESTART_RESTARTBLOCK;
}
-long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
const enum hrtimer_mode mode, const clockid_t clockid)
{
struct restart_block *restart;
struct hrtimer_sleeper t;
- ktime_t rem;
hrtimer_init(&t.timer, clockid, mode);
t.timer.expires = timespec_to_ktime(*rqtp);
@@ -1364,10 +1377,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
return -ERESTARTNOHAND;
if (rmtp) {
- rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
- if (rem.tv64 <= 0)
- return 0;
- *rmtp = ktime_to_timespec(rem);
+ int ret = update_rmtp(&t.timer, rmtp);
+ if (ret <= 0)
+ return ret;
}
restart = &current_thread_info()->restart_block;
@@ -1383,8 +1395,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
asmlinkage long
sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
{
- struct timespec tu, rmt;
- int ret;
+ struct timespec tu;
if (copy_from_user(&tu, rqtp, sizeof(tu)))
return -EFAULT;
@@ -1392,15 +1403,7 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
if (!timespec_valid(&tu))
return -EINVAL;
- ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
- CLOCK_MONOTONIC);
-
- if (ret && rmtp) {
- if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
- return -EFAULT;
- }
-
- return ret;
+ return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
}
/*
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index ce268966007..022c9c3cee6 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -982,20 +982,9 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
static int common_nsleep(const clockid_t which_clock, int flags,
struct timespec *tsave, struct timespec __user *rmtp)
{
- struct timespec rmt;
- int ret;
-
- ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL,
- flags & TIMER_ABSTIME ?
- HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
- which_clock);
-
- if (ret && rmtp) {
- if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
- return -EFAULT;
- }
-
- return ret;
+ return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+ HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+ which_clock);
}
asmlinkage long