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