1
0
Fork 0

posix-timers: Use get_timespec64() and put_timespec64()

Usage of these apis and their compat versions makes
the syscalls: clock_gettime, clock_settime, clock_getres
and their compat implementations simpler.

This is a preparatory patch to isolate data conversions to
struct timespec64 at userspace boundaries. This helps contain
the changes needed to transition to new y2038 safe types.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
zero-colors
Deepa Dinamani 2017-06-24 11:45:05 -07:00 committed by Al Viro
parent 63a766a178
commit 5c4994102f
2 changed files with 70 additions and 76 deletions

View File

@ -51,40 +51,52 @@ SYS_NI(alarm);
SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
const struct timespec __user *, tp) const struct timespec __user *, tp)
{ {
struct timespec64 new_tp64; struct timespec64 new_tp;
struct timespec new_tp;
if (which_clock != CLOCK_REALTIME) if (which_clock != CLOCK_REALTIME)
return -EINVAL; return -EINVAL;
if (copy_from_user(&new_tp, tp, sizeof (*tp))) if (get_timespec64(&new_tp, tp))
return -EFAULT; return -EFAULT;
new_tp64 = timespec_to_timespec64(new_tp); return do_sys_settimeofday64(&new_tp, NULL);
return do_sys_settimeofday64(&new_tp64, NULL);
} }
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp)
struct timespec __user *,tp)
{ {
struct timespec64 kernel_tp64;
struct timespec kernel_tp;
switch (which_clock) { switch (which_clock) {
case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; case CLOCK_REALTIME:
case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; ktime_get_real_ts64(tp);
case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; break;
default: return -EINVAL; case CLOCK_MONOTONIC:
ktime_get_ts64(tp);
break;
case CLOCK_BOOTTIME:
get_monotonic_boottime64(tp);
break;
default:
return -EINVAL;
} }
kernel_tp = timespec64_to_timespec(kernel_tp64); return 0;
if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) }
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
struct timespec __user *, tp)
{
int ret;
struct timespec64 kernel_tp;
ret = do_clock_gettime(which_clock, &kernel_tp);
if (ret)
return ret;
if (put_timespec64(&kernel_tp, tp))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
{ {
struct timespec rtn_tp = { struct timespec64 rtn_tp = {
.tv_sec = 0, .tv_sec = 0,
.tv_nsec = hrtimer_resolution, .tv_nsec = hrtimer_resolution,
}; };
@ -93,7 +105,7 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __us
case CLOCK_REALTIME: case CLOCK_REALTIME:
case CLOCK_MONOTONIC: case CLOCK_MONOTONIC:
case CLOCK_BOOTTIME: case CLOCK_BOOTTIME:
if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) if (put_timespec64(&rtn_tp, tp))
return -EFAULT; return -EFAULT;
return 0; return 0;
default: default:
@ -142,41 +154,35 @@ COMPAT_SYS_NI(setitimer);
COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
struct compat_timespec __user *, tp) struct compat_timespec __user *, tp)
{ {
struct timespec64 new_tp64; struct timespec64 new_tp;
struct timespec new_tp;
if (which_clock != CLOCK_REALTIME) if (which_clock != CLOCK_REALTIME)
return -EINVAL; return -EINVAL;
if (compat_get_timespec(&new_tp, tp)) if (compat_get_timespec64(&new_tp, tp))
return -EFAULT; return -EFAULT;
new_tp64 = timespec_to_timespec64(new_tp); return do_sys_settimeofday64(&new_tp, NULL);
return do_sys_settimeofday64(&new_tp64, NULL);
} }
COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
struct compat_timespec __user *,tp) struct compat_timespec __user *, tp)
{ {
struct timespec64 kernel_tp64; int ret;
struct timespec kernel_tp; struct timespec64 kernel_tp;
switch (which_clock) { ret = do_clock_gettime(which_clock, &kernel_tp);
case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; if (ret)
case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; return ret;
case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break;
default: return -EINVAL;
}
kernel_tp = timespec64_to_timespec(kernel_tp64); if (compat_put_timespec64(&kernel_tp, tp))
if (compat_put_timespec(&kernel_tp, tp))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
struct compat_timespec __user *, tp) struct compat_timespec __user *, tp)
{ {
struct timespec rtn_tp = { struct timespec64 rtn_tp = {
.tv_sec = 0, .tv_sec = 0,
.tv_nsec = hrtimer_resolution, .tv_nsec = hrtimer_resolution,
}; };
@ -185,13 +191,14 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
case CLOCK_REALTIME: case CLOCK_REALTIME:
case CLOCK_MONOTONIC: case CLOCK_MONOTONIC:
case CLOCK_BOOTTIME: case CLOCK_BOOTTIME:
if (compat_put_timespec(&rtn_tp, tp)) if (compat_put_timespec64(&rtn_tp, tp))
return -EFAULT; return -EFAULT;
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
} }
COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
struct compat_timespec __user *, rqtp, struct compat_timespec __user *, rqtp,
struct compat_timespec __user *, rmtp) struct compat_timespec __user *, rmtp)

View File

@ -1049,34 +1049,30 @@ SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
const struct timespec __user *, tp) const struct timespec __user *, tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 new_tp64; struct timespec64 new_tp;
struct timespec new_tp;
if (!kc || !kc->clock_set) if (!kc || !kc->clock_set)
return -EINVAL; return -EINVAL;
if (copy_from_user(&new_tp, tp, sizeof (*tp))) if (get_timespec64(&new_tp, tp))
return -EFAULT; return -EFAULT;
new_tp64 = timespec_to_timespec64(new_tp);
return kc->clock_set(which_clock, &new_tp64); return kc->clock_set(which_clock, &new_tp);
} }
SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
struct timespec __user *,tp) struct timespec __user *,tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 kernel_tp64; struct timespec64 kernel_tp;
struct timespec kernel_tp;
int error; int error;
if (!kc) if (!kc)
return -EINVAL; return -EINVAL;
error = kc->clock_get(which_clock, &kernel_tp64); error = kc->clock_get(which_clock, &kernel_tp);
kernel_tp = timespec64_to_timespec(kernel_tp64);
if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) if (!error && put_timespec64(&kernel_tp, tp))
error = -EFAULT; error = -EFAULT;
return error; return error;
@ -1109,17 +1105,15 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
struct timespec __user *, tp) struct timespec __user *, tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 rtn_tp64; struct timespec64 rtn_tp;
struct timespec rtn_tp;
int error; int error;
if (!kc) if (!kc)
return -EINVAL; return -EINVAL;
error = kc->clock_getres(which_clock, &rtn_tp64); error = kc->clock_getres(which_clock, &rtn_tp);
rtn_tp = timespec64_to_timespec(rtn_tp64);
if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) if (!error && tp && put_timespec64(&rtn_tp, tp))
error = -EFAULT; error = -EFAULT;
return error; return error;
@ -1131,38 +1125,33 @@ COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
struct compat_timespec __user *, tp) struct compat_timespec __user *, tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 new_tp64; struct timespec64 ts;
struct timespec new_tp;
if (!kc || !kc->clock_set) if (!kc || !kc->clock_set)
return -EINVAL; return -EINVAL;
if (compat_get_timespec(&new_tp, tp)) if (compat_get_timespec64(&ts, tp))
return -EFAULT; return -EFAULT;
new_tp64 = timespec_to_timespec64(new_tp); return kc->clock_set(which_clock, &ts);
return kc->clock_set(which_clock, &new_tp64);
} }
COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
struct compat_timespec __user *, tp) struct compat_timespec __user *, tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 kernel_tp64; struct timespec64 ts;
struct timespec kernel_tp; int err;
int error;
if (!kc) if (!kc)
return -EINVAL; return -EINVAL;
error = kc->clock_get(which_clock, &kernel_tp64); err = kc->clock_get(which_clock, &ts);
kernel_tp = timespec64_to_timespec(kernel_tp64);
if (!error && compat_put_timespec(&kernel_tp, tp)) if (!err && compat_put_timespec64(&ts, tp))
error = -EFAULT; err = -EFAULT;
return error; return err;
} }
COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
@ -1193,21 +1182,19 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
struct compat_timespec __user *, tp) struct compat_timespec __user *, tp)
{ {
const struct k_clock *kc = clockid_to_kclock(which_clock); const struct k_clock *kc = clockid_to_kclock(which_clock);
struct timespec64 rtn_tp64; struct timespec64 ts;
struct timespec rtn_tp; int err;
int error;
if (!kc) if (!kc)
return -EINVAL; return -EINVAL;
error = kc->clock_getres(which_clock, &rtn_tp64); err = kc->clock_getres(which_clock, &ts);
rtn_tp = timespec64_to_timespec(rtn_tp64); if (!err && tp && compat_put_timespec64(&ts, tp))
return -EFAULT;
if (!error && tp && compat_put_timespec(&rtn_tp, tp)) return err;
error = -EFAULT;
return error;
} }
#endif #endif
/* /*