diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 18:34:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 18:34:35 -0400 |
commit | ea3b25e1320df4e575c323b6ab22a5fc79976fbe (patch) | |
tree | ee824920b52a6458e383bc2b057cc5508e60fafe | |
parent | 89fbf5384ddf666a595eb6562dc63fcbfeb8f6a5 (diff) | |
parent | 725816e8aabb1c183baa2bc9572ab9a0d26b9ea1 (diff) |
Merge branch 'timers-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull timer-related user access updates from Al Viro:
"Continuation of timers-related stuff (there had been more, but my
parts of that series are already merged via timers/core). This is more
of y2038 work by Deepa Dinamani, partially disrupted by the
unification of native and compat timers-related syscalls"
* 'timers-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
posix_clocks: Use get_itimerspec64() and put_itimerspec64()
timerfd: Use get_itimerspec64() and put_itimerspec64()
nanosleep: Use get_timespec64() and put_timespec64()
posix-timers: Use get_timespec64() and put_timespec64()
posix-stubs: Conditionally include COMPAT_SYS_NI defines
time: introduce {get,put}_itimerspec64
time: add get_timespec64 and put_timespec64
-rw-r--r-- | fs/timerfd.c | 43 | ||||
-rw-r--r-- | include/linux/compat.h | 6 | ||||
-rw-r--r-- | include/linux/hrtimer.h | 2 | ||||
-rw-r--r-- | include/linux/posix-timers.h | 1 | ||||
-rw-r--r-- | include/linux/time.h | 18 | ||||
-rw-r--r-- | kernel/compat.c | 65 | ||||
-rw-r--r-- | kernel/time/alarmtimer.c | 4 | ||||
-rw-r--r-- | kernel/time/hrtimer.c | 30 | ||||
-rw-r--r-- | kernel/time/posix-cpu-timers.c | 8 | ||||
-rw-r--r-- | kernel/time/posix-stubs.c | 96 | ||||
-rw-r--r-- | kernel/time/posix-timers.c | 127 | ||||
-rw-r--r-- | kernel/time/time.c | 58 |
12 files changed, 287 insertions, 171 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c index c543cdb5f8ed..ece0c02d7e63 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -169,7 +169,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | static int timerfd_setup(struct timerfd_ctx *ctx, int flags, | 171 | static int timerfd_setup(struct timerfd_ctx *ctx, int flags, |
172 | const struct itimerspec *ktmr) | 172 | const struct itimerspec64 *ktmr) |
173 | { | 173 | { |
174 | enum hrtimer_mode htmode; | 174 | enum hrtimer_mode htmode; |
175 | ktime_t texp; | 175 | ktime_t texp; |
@@ -178,10 +178,10 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags, | |||
178 | htmode = (flags & TFD_TIMER_ABSTIME) ? | 178 | htmode = (flags & TFD_TIMER_ABSTIME) ? |
179 | HRTIMER_MODE_ABS: HRTIMER_MODE_REL; | 179 | HRTIMER_MODE_ABS: HRTIMER_MODE_REL; |
180 | 180 | ||
181 | texp = timespec_to_ktime(ktmr->it_value); | 181 | texp = timespec64_to_ktime(ktmr->it_value); |
182 | ctx->expired = 0; | 182 | ctx->expired = 0; |
183 | ctx->ticks = 0; | 183 | ctx->ticks = 0; |
184 | ctx->tintv = timespec_to_ktime(ktmr->it_interval); | 184 | ctx->tintv = timespec64_to_ktime(ktmr->it_interval); |
185 | 185 | ||
186 | if (isalarm(ctx)) { | 186 | if (isalarm(ctx)) { |
187 | alarm_init(&ctx->t.alarm, | 187 | alarm_init(&ctx->t.alarm, |
@@ -432,16 +432,15 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | static int do_timerfd_settime(int ufd, int flags, | 434 | static int do_timerfd_settime(int ufd, int flags, |
435 | const struct itimerspec *new, | 435 | const struct itimerspec64 *new, |
436 | struct itimerspec *old) | 436 | struct itimerspec64 *old) |
437 | { | 437 | { |
438 | struct fd f; | 438 | struct fd f; |
439 | struct timerfd_ctx *ctx; | 439 | struct timerfd_ctx *ctx; |
440 | int ret; | 440 | int ret; |
441 | 441 | ||
442 | if ((flags & ~TFD_SETTIME_FLAGS) || | 442 | if ((flags & ~TFD_SETTIME_FLAGS) || |
443 | !timespec_valid(&new->it_value) || | 443 | !itimerspec64_valid(new)) |
444 | !timespec_valid(&new->it_interval)) | ||
445 | return -EINVAL; | 444 | return -EINVAL; |
446 | 445 | ||
447 | ret = timerfd_fget(ufd, &f); | 446 | ret = timerfd_fget(ufd, &f); |
@@ -487,8 +486,8 @@ static int do_timerfd_settime(int ufd, int flags, | |||
487 | hrtimer_forward_now(&ctx->t.tmr, ctx->tintv); | 486 | hrtimer_forward_now(&ctx->t.tmr, ctx->tintv); |
488 | } | 487 | } |
489 | 488 | ||
490 | old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 489 | old->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx)); |
491 | old->it_interval = ktime_to_timespec(ctx->tintv); | 490 | old->it_interval = ktime_to_timespec64(ctx->tintv); |
492 | 491 | ||
493 | /* | 492 | /* |
494 | * Re-program the timer to the new value ... | 493 | * Re-program the timer to the new value ... |
@@ -500,7 +499,7 @@ static int do_timerfd_settime(int ufd, int flags, | |||
500 | return ret; | 499 | return ret; |
501 | } | 500 | } |
502 | 501 | ||
503 | static int do_timerfd_gettime(int ufd, struct itimerspec *t) | 502 | static int do_timerfd_gettime(int ufd, struct itimerspec64 *t) |
504 | { | 503 | { |
505 | struct fd f; | 504 | struct fd f; |
506 | struct timerfd_ctx *ctx; | 505 | struct timerfd_ctx *ctx; |
@@ -525,8 +524,8 @@ static int do_timerfd_gettime(int ufd, struct itimerspec *t) | |||
525 | hrtimer_restart(&ctx->t.tmr); | 524 | hrtimer_restart(&ctx->t.tmr); |
526 | } | 525 | } |
527 | } | 526 | } |
528 | t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 527 | t->it_value = ktime_to_timespec64(timerfd_get_remaining(ctx)); |
529 | t->it_interval = ktime_to_timespec(ctx->tintv); | 528 | t->it_interval = ktime_to_timespec64(ctx->tintv); |
530 | spin_unlock_irq(&ctx->wqh.lock); | 529 | spin_unlock_irq(&ctx->wqh.lock); |
531 | fdput(f); | 530 | fdput(f); |
532 | return 0; | 531 | return 0; |
@@ -536,15 +535,15 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
536 | const struct itimerspec __user *, utmr, | 535 | const struct itimerspec __user *, utmr, |
537 | struct itimerspec __user *, otmr) | 536 | struct itimerspec __user *, otmr) |
538 | { | 537 | { |
539 | struct itimerspec new, old; | 538 | struct itimerspec64 new, old; |
540 | int ret; | 539 | int ret; |
541 | 540 | ||
542 | if (copy_from_user(&new, utmr, sizeof(new))) | 541 | if (get_itimerspec64(&new, utmr)) |
543 | return -EFAULT; | 542 | return -EFAULT; |
544 | ret = do_timerfd_settime(ufd, flags, &new, &old); | 543 | ret = do_timerfd_settime(ufd, flags, &new, &old); |
545 | if (ret) | 544 | if (ret) |
546 | return ret; | 545 | return ret; |
547 | if (otmr && copy_to_user(otmr, &old, sizeof(old))) | 546 | if (otmr && put_itimerspec64(&old, otmr)) |
548 | return -EFAULT; | 547 | return -EFAULT; |
549 | 548 | ||
550 | return ret; | 549 | return ret; |
@@ -552,11 +551,11 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
552 | 551 | ||
553 | SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) | 552 | SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) |
554 | { | 553 | { |
555 | struct itimerspec kotmr; | 554 | struct itimerspec64 kotmr; |
556 | int ret = do_timerfd_gettime(ufd, &kotmr); | 555 | int ret = do_timerfd_gettime(ufd, &kotmr); |
557 | if (ret) | 556 | if (ret) |
558 | return ret; | 557 | return ret; |
559 | return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; | 558 | return put_itimerspec64(&kotmr, otmr) ? -EFAULT : 0; |
560 | } | 559 | } |
561 | 560 | ||
562 | #ifdef CONFIG_COMPAT | 561 | #ifdef CONFIG_COMPAT |
@@ -564,15 +563,15 @@ COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
564 | const struct compat_itimerspec __user *, utmr, | 563 | const struct compat_itimerspec __user *, utmr, |
565 | struct compat_itimerspec __user *, otmr) | 564 | struct compat_itimerspec __user *, otmr) |
566 | { | 565 | { |
567 | struct itimerspec new, old; | 566 | struct itimerspec64 new, old; |
568 | int ret; | 567 | int ret; |
569 | 568 | ||
570 | if (get_compat_itimerspec(&new, utmr)) | 569 | if (get_compat_itimerspec64(&new, utmr)) |
571 | return -EFAULT; | 570 | return -EFAULT; |
572 | ret = do_timerfd_settime(ufd, flags, &new, &old); | 571 | ret = do_timerfd_settime(ufd, flags, &new, &old); |
573 | if (ret) | 572 | if (ret) |
574 | return ret; | 573 | return ret; |
575 | if (otmr && put_compat_itimerspec(otmr, &old)) | 574 | if (otmr && put_compat_itimerspec64(&old, otmr)) |
576 | return -EFAULT; | 575 | return -EFAULT; |
577 | return ret; | 576 | return ret; |
578 | } | 577 | } |
@@ -580,10 +579,10 @@ COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
580 | COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, | 579 | COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, |
581 | struct compat_itimerspec __user *, otmr) | 580 | struct compat_itimerspec __user *, otmr) |
582 | { | 581 | { |
583 | struct itimerspec kotmr; | 582 | struct itimerspec64 kotmr; |
584 | int ret = do_timerfd_gettime(ufd, &kotmr); | 583 | int ret = do_timerfd_gettime(ufd, &kotmr); |
585 | if (ret) | 584 | if (ret) |
586 | return ret; | 585 | return ret; |
587 | return put_compat_itimerspec(otmr, &kotmr) ? -EFAULT: 0; | 586 | return put_compat_itimerspec64(&kotmr, otmr) ? -EFAULT : 0; |
588 | } | 587 | } |
589 | #endif | 588 | #endif |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 425563c7647b..2ed54020ace0 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -164,6 +164,12 @@ extern int compat_get_timespec(struct timespec *, const void __user *); | |||
164 | extern int compat_put_timespec(const struct timespec *, void __user *); | 164 | extern int compat_put_timespec(const struct timespec *, void __user *); |
165 | extern int compat_get_timeval(struct timeval *, const void __user *); | 165 | extern int compat_get_timeval(struct timeval *, const void __user *); |
166 | extern int compat_put_timeval(const struct timeval *, void __user *); | 166 | extern int compat_put_timeval(const struct timeval *, void __user *); |
167 | extern int compat_get_timespec64(struct timespec64 *, const void __user *); | ||
168 | extern int compat_put_timespec64(const struct timespec64 *, void __user *); | ||
169 | extern int get_compat_itimerspec64(struct itimerspec64 *its, | ||
170 | const struct compat_itimerspec __user *uits); | ||
171 | extern int put_compat_itimerspec64(const struct itimerspec64 *its, | ||
172 | struct compat_itimerspec __user *uits); | ||
167 | 173 | ||
168 | /* | 174 | /* |
169 | * This function convert a timespec if necessary and returns a *user | 175 | * This function convert a timespec if necessary and returns a *user |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 255edd5e7a74..012c37fdb688 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -453,7 +453,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer, | |||
453 | 453 | ||
454 | /* Precise sleep: */ | 454 | /* Precise sleep: */ |
455 | 455 | ||
456 | extern int nanosleep_copyout(struct restart_block *, struct timespec *); | 456 | extern int nanosleep_copyout(struct restart_block *, struct timespec64 *); |
457 | extern long hrtimer_nanosleep(const struct timespec64 *rqtp, | 457 | extern long hrtimer_nanosleep(const struct timespec64 *rqtp, |
458 | const enum hrtimer_mode mode, | 458 | const enum hrtimer_mode mode, |
459 | const clockid_t clockid); | 459 | const clockid_t clockid); |
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 29f1b7f09ced..62839fd04dce 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h | |||
@@ -113,5 +113,4 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, | |||
113 | void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); | 113 | void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); |
114 | 114 | ||
115 | void posixtimer_rearm(struct siginfo *info); | 115 | void posixtimer_rearm(struct siginfo *info); |
116 | |||
117 | #endif | 116 | #endif |
diff --git a/include/linux/time.h b/include/linux/time.h index c0543f5f25de..f9858d7e6361 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -8,6 +8,15 @@ | |||
8 | 8 | ||
9 | extern struct timezone sys_tz; | 9 | extern struct timezone sys_tz; |
10 | 10 | ||
11 | int get_timespec64(struct timespec64 *ts, | ||
12 | const struct timespec __user *uts); | ||
13 | int put_timespec64(const struct timespec64 *ts, | ||
14 | struct timespec __user *uts); | ||
15 | int get_itimerspec64(struct itimerspec64 *it, | ||
16 | const struct itimerspec __user *uit); | ||
17 | int put_itimerspec64(const struct itimerspec64 *it, | ||
18 | struct itimerspec __user *uit); | ||
19 | |||
11 | #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) | 20 | #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) |
12 | 21 | ||
13 | static inline int timespec_equal(const struct timespec *a, | 22 | static inline int timespec_equal(const struct timespec *a, |
@@ -270,4 +279,13 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) | |||
270 | a->tv_nsec = ns; | 279 | a->tv_nsec = ns; |
271 | } | 280 | } |
272 | 281 | ||
282 | static inline bool itimerspec64_valid(const struct itimerspec64 *its) | ||
283 | { | ||
284 | if (!timespec64_valid(&(its->it_interval)) || | ||
285 | !timespec64_valid(&(its->it_value))) | ||
286 | return false; | ||
287 | |||
288 | return true; | ||
289 | } | ||
290 | |||
273 | #endif | 291 | #endif |
diff --git a/kernel/compat.c b/kernel/compat.c index 9ce1d4876e60..0621c8e1ab72 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -120,6 +120,50 @@ static int __compat_put_timespec(const struct timespec *ts, struct compat_timesp | |||
120 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; | 120 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static int __compat_get_timespec64(struct timespec64 *ts64, | ||
124 | const struct compat_timespec __user *cts) | ||
125 | { | ||
126 | struct compat_timespec ts; | ||
127 | int ret; | ||
128 | |||
129 | ret = copy_from_user(&ts, cts, sizeof(ts)); | ||
130 | if (ret) | ||
131 | return -EFAULT; | ||
132 | |||
133 | ts64->tv_sec = ts.tv_sec; | ||
134 | ts64->tv_nsec = ts.tv_nsec; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int __compat_put_timespec64(const struct timespec64 *ts64, | ||
140 | struct compat_timespec __user *cts) | ||
141 | { | ||
142 | struct compat_timespec ts = { | ||
143 | .tv_sec = ts64->tv_sec, | ||
144 | .tv_nsec = ts64->tv_nsec | ||
145 | }; | ||
146 | return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0; | ||
147 | } | ||
148 | |||
149 | int compat_get_timespec64(struct timespec64 *ts, const void __user *uts) | ||
150 | { | ||
151 | if (COMPAT_USE_64BIT_TIME) | ||
152 | return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0; | ||
153 | else | ||
154 | return __compat_get_timespec64(ts, uts); | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(compat_get_timespec64); | ||
157 | |||
158 | int compat_put_timespec64(const struct timespec64 *ts, void __user *uts) | ||
159 | { | ||
160 | if (COMPAT_USE_64BIT_TIME) | ||
161 | return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0; | ||
162 | else | ||
163 | return __compat_put_timespec64(ts, uts); | ||
164 | } | ||
165 | EXPORT_SYMBOL_GPL(compat_put_timespec64); | ||
166 | |||
123 | int compat_get_timeval(struct timeval *tv, const void __user *utv) | 167 | int compat_get_timeval(struct timeval *tv, const void __user *utv) |
124 | { | 168 | { |
125 | if (COMPAT_USE_64BIT_TIME) | 169 | if (COMPAT_USE_64BIT_TIME) |
@@ -476,6 +520,27 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst, | |||
476 | return 0; | 520 | return 0; |
477 | } | 521 | } |
478 | 522 | ||
523 | int get_compat_itimerspec64(struct itimerspec64 *its, | ||
524 | const struct compat_itimerspec __user *uits) | ||
525 | { | ||
526 | |||
527 | if (__compat_get_timespec64(&its->it_interval, &uits->it_interval) || | ||
528 | __compat_get_timespec64(&its->it_value, &uits->it_value)) | ||
529 | return -EFAULT; | ||
530 | return 0; | ||
531 | } | ||
532 | EXPORT_SYMBOL_GPL(get_compat_itimerspec64); | ||
533 | |||
534 | int put_compat_itimerspec64(const struct itimerspec64 *its, | ||
535 | struct compat_itimerspec __user *uits) | ||
536 | { | ||
537 | if (__compat_put_timespec64(&its->it_interval, &uits->it_interval) || | ||
538 | __compat_put_timespec64(&its->it_value, &uits->it_value)) | ||
539 | return -EFAULT; | ||
540 | return 0; | ||
541 | } | ||
542 | EXPORT_SYMBOL_GPL(put_compat_itimerspec64); | ||
543 | |||
479 | /* | 544 | /* |
480 | * We currently only need the following fields from the sigevent | 545 | * We currently only need the following fields from the sigevent |
481 | * structure: sigev_value, sigev_signo, sig_notify and (sometimes | 546 | * structure: sigev_value, sigev_signo, sig_notify and (sometimes |
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index c991cf212c6d..0b8ff7d257ea 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -712,14 +712,14 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp, | |||
712 | alarmtimer_freezerset(absexp, type); | 712 | alarmtimer_freezerset(absexp, type); |
713 | restart = ¤t->restart_block; | 713 | restart = ¤t->restart_block; |
714 | if (restart->nanosleep.type != TT_NONE) { | 714 | if (restart->nanosleep.type != TT_NONE) { |
715 | struct timespec rmt; | 715 | struct timespec64 rmt; |
716 | ktime_t rem; | 716 | ktime_t rem; |
717 | 717 | ||
718 | rem = ktime_sub(absexp, alarm_bases[type].gettime()); | 718 | rem = ktime_sub(absexp, alarm_bases[type].gettime()); |
719 | 719 | ||
720 | if (rem <= 0) | 720 | if (rem <= 0) |
721 | return 0; | 721 | return 0; |
722 | rmt = ktime_to_timespec(rem); | 722 | rmt = ktime_to_timespec64(rem); |
723 | 723 | ||
724 | return nanosleep_copyout(restart, &rmt); | 724 | return nanosleep_copyout(restart, &rmt); |
725 | } | 725 | } |
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 81da124f1115..88f75f92ef36 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c | |||
@@ -1440,17 +1440,17 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task) | |||
1440 | } | 1440 | } |
1441 | EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); | 1441 | EXPORT_SYMBOL_GPL(hrtimer_init_sleeper); |
1442 | 1442 | ||
1443 | int nanosleep_copyout(struct restart_block *restart, struct timespec *ts) | 1443 | int nanosleep_copyout(struct restart_block *restart, struct timespec64 *ts) |
1444 | { | 1444 | { |
1445 | switch(restart->nanosleep.type) { | 1445 | switch(restart->nanosleep.type) { |
1446 | #ifdef CONFIG_COMPAT | 1446 | #ifdef CONFIG_COMPAT |
1447 | case TT_COMPAT: | 1447 | case TT_COMPAT: |
1448 | if (compat_put_timespec(ts, restart->nanosleep.compat_rmtp)) | 1448 | if (compat_put_timespec64(ts, restart->nanosleep.compat_rmtp)) |
1449 | return -EFAULT; | 1449 | return -EFAULT; |
1450 | break; | 1450 | break; |
1451 | #endif | 1451 | #endif |
1452 | case TT_NATIVE: | 1452 | case TT_NATIVE: |
1453 | if (copy_to_user(restart->nanosleep.rmtp, ts, sizeof(struct timespec))) | 1453 | if (put_timespec64(ts, restart->nanosleep.rmtp)) |
1454 | return -EFAULT; | 1454 | return -EFAULT; |
1455 | break; | 1455 | break; |
1456 | default: | 1456 | default: |
@@ -1485,11 +1485,11 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod | |||
1485 | restart = ¤t->restart_block; | 1485 | restart = ¤t->restart_block; |
1486 | if (restart->nanosleep.type != TT_NONE) { | 1486 | if (restart->nanosleep.type != TT_NONE) { |
1487 | ktime_t rem = hrtimer_expires_remaining(&t->timer); | 1487 | ktime_t rem = hrtimer_expires_remaining(&t->timer); |
1488 | struct timespec rmt; | 1488 | struct timespec64 rmt; |
1489 | 1489 | ||
1490 | if (rem <= 0) | 1490 | if (rem <= 0) |
1491 | return 0; | 1491 | return 0; |
1492 | rmt = ktime_to_timespec(rem); | 1492 | rmt = ktime_to_timespec64(rem); |
1493 | 1493 | ||
1494 | return nanosleep_copyout(restart, &rmt); | 1494 | return nanosleep_copyout(restart, &rmt); |
1495 | } | 1495 | } |
@@ -1546,19 +1546,17 @@ out: | |||
1546 | SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, | 1546 | SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, |
1547 | struct timespec __user *, rmtp) | 1547 | struct timespec __user *, rmtp) |
1548 | { | 1548 | { |
1549 | struct timespec64 tu64; | 1549 | struct timespec64 tu; |
1550 | struct timespec tu; | ||
1551 | 1550 | ||
1552 | if (copy_from_user(&tu, rqtp, sizeof(tu))) | 1551 | if (get_timespec64(&tu, rqtp)) |
1553 | return -EFAULT; | 1552 | return -EFAULT; |
1554 | 1553 | ||
1555 | tu64 = timespec_to_timespec64(tu); | 1554 | if (!timespec64_valid(&tu)) |
1556 | if (!timespec64_valid(&tu64)) | ||
1557 | return -EINVAL; | 1555 | return -EINVAL; |
1558 | 1556 | ||
1559 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; | 1557 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; |
1560 | current->restart_block.nanosleep.rmtp = rmtp; | 1558 | current->restart_block.nanosleep.rmtp = rmtp; |
1561 | return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC); | 1559 | return hrtimer_nanosleep(&tu, HRTIMER_MODE_REL, CLOCK_MONOTONIC); |
1562 | } | 1560 | } |
1563 | 1561 | ||
1564 | #ifdef CONFIG_COMPAT | 1562 | #ifdef CONFIG_COMPAT |
@@ -1566,19 +1564,17 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, | |||
1566 | COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, | 1564 | COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, |
1567 | struct compat_timespec __user *, rmtp) | 1565 | struct compat_timespec __user *, rmtp) |
1568 | { | 1566 | { |
1569 | struct timespec64 tu64; | 1567 | struct timespec64 tu; |
1570 | struct timespec tu; | ||
1571 | 1568 | ||
1572 | if (compat_get_timespec(&tu, rqtp)) | 1569 | if (compat_get_timespec64(&tu, rqtp)) |
1573 | return -EFAULT; | 1570 | return -EFAULT; |
1574 | 1571 | ||
1575 | tu64 = timespec_to_timespec64(tu); | 1572 | if (!timespec64_valid(&tu)) |
1576 | if (!timespec64_valid(&tu64)) | ||
1577 | return -EINVAL; | 1573 | return -EINVAL; |
1578 | 1574 | ||
1579 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; | 1575 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; |
1580 | current->restart_block.nanosleep.compat_rmtp = rmtp; | 1576 | current->restart_block.nanosleep.compat_rmtp = rmtp; |
1581 | return hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC); | 1577 | return hrtimer_nanosleep(&tu, HRTIMER_MODE_REL, CLOCK_MONOTONIC); |
1582 | } | 1578 | } |
1583 | #endif | 1579 | #endif |
1584 | 1580 | ||
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 60cb24ac9ebc..a3bd5dbe0dc4 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c | |||
@@ -1318,12 +1318,8 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, | |||
1318 | */ | 1318 | */ |
1319 | restart = ¤t->restart_block; | 1319 | restart = ¤t->restart_block; |
1320 | restart->nanosleep.expires = expires; | 1320 | restart->nanosleep.expires = expires; |
1321 | if (restart->nanosleep.type != TT_NONE) { | 1321 | if (restart->nanosleep.type != TT_NONE) |
1322 | struct timespec ts; | 1322 | error = nanosleep_copyout(restart, &it.it_value); |
1323 | |||
1324 | ts = timespec64_to_timespec(it.it_value); | ||
1325 | error = nanosleep_copyout(restart, &ts); | ||
1326 | } | ||
1327 | } | 1323 | } |
1328 | 1324 | ||
1329 | return error; | 1325 | return error; |
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c index 38f3b20efa29..06f34feb635e 100644 --- a/kernel/time/posix-stubs.c +++ b/kernel/time/posix-stubs.c | |||
@@ -41,12 +41,6 @@ SYS_NI(setitimer); | |||
41 | #ifdef __ARCH_WANT_SYS_ALARM | 41 | #ifdef __ARCH_WANT_SYS_ALARM |
42 | SYS_NI(alarm); | 42 | SYS_NI(alarm); |
43 | #endif | 43 | #endif |
44 | COMPAT_SYS_NI(timer_create); | ||
45 | COMPAT_SYS_NI(clock_adjtime); | ||
46 | COMPAT_SYS_NI(timer_settime); | ||
47 | COMPAT_SYS_NI(timer_gettime); | ||
48 | COMPAT_SYS_NI(getitimer); | ||
49 | COMPAT_SYS_NI(setitimer); | ||
50 | 44 | ||
51 | /* | 45 | /* |
52 | * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC | 46 | * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC |
@@ -57,40 +51,52 @@ COMPAT_SYS_NI(setitimer); | |||
57 | SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, | 51 | SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, |
58 | const struct timespec __user *, tp) | 52 | const struct timespec __user *, tp) |
59 | { | 53 | { |
60 | struct timespec64 new_tp64; | 54 | struct timespec64 new_tp; |
61 | struct timespec new_tp; | ||
62 | 55 | ||
63 | if (which_clock != CLOCK_REALTIME) | 56 | if (which_clock != CLOCK_REALTIME) |
64 | return -EINVAL; | 57 | return -EINVAL; |
65 | if (copy_from_user(&new_tp, tp, sizeof (*tp))) | 58 | if (get_timespec64(&new_tp, tp)) |
66 | return -EFAULT; | 59 | return -EFAULT; |
67 | 60 | ||
68 | new_tp64 = timespec_to_timespec64(new_tp); | 61 | return do_sys_settimeofday64(&new_tp, NULL); |
69 | return do_sys_settimeofday64(&new_tp64, NULL); | ||
70 | } | 62 | } |
71 | 63 | ||
72 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | 64 | int do_clock_gettime(clockid_t which_clock, struct timespec64 *tp) |
73 | struct timespec __user *,tp) | ||
74 | { | 65 | { |
75 | struct timespec64 kernel_tp64; | ||
76 | struct timespec kernel_tp; | ||
77 | |||
78 | switch (which_clock) { | 66 | switch (which_clock) { |
79 | case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; | 67 | case CLOCK_REALTIME: |
80 | case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; | 68 | ktime_get_real_ts64(tp); |
81 | case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; | 69 | break; |
82 | default: return -EINVAL; | 70 | case CLOCK_MONOTONIC: |
71 | ktime_get_ts64(tp); | ||
72 | break; | ||
73 | case CLOCK_BOOTTIME: | ||
74 | get_monotonic_boottime64(tp); | ||
75 | break; | ||
76 | default: | ||
77 | return -EINVAL; | ||
83 | } | 78 | } |
84 | 79 | ||
85 | kernel_tp = timespec64_to_timespec(kernel_tp64); | 80 | return 0; |
86 | if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) | 81 | } |
82 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | ||
83 | struct timespec __user *, tp) | ||
84 | { | ||
85 | int ret; | ||
86 | struct timespec64 kernel_tp; | ||
87 | |||
88 | ret = do_clock_gettime(which_clock, &kernel_tp); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | |||
92 | if (put_timespec64(&kernel_tp, tp)) | ||
87 | return -EFAULT; | 93 | return -EFAULT; |
88 | return 0; | 94 | return 0; |
89 | } | 95 | } |
90 | 96 | ||
91 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) | 97 | SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp) |
92 | { | 98 | { |
93 | struct timespec rtn_tp = { | 99 | struct timespec64 rtn_tp = { |
94 | .tv_sec = 0, | 100 | .tv_sec = 0, |
95 | .tv_nsec = hrtimer_resolution, | 101 | .tv_nsec = hrtimer_resolution, |
96 | }; | 102 | }; |
@@ -99,7 +105,7 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __us | |||
99 | case CLOCK_REALTIME: | 105 | case CLOCK_REALTIME: |
100 | case CLOCK_MONOTONIC: | 106 | case CLOCK_MONOTONIC: |
101 | case CLOCK_BOOTTIME: | 107 | case CLOCK_BOOTTIME: |
102 | if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp))) | 108 | if (put_timespec64(&rtn_tp, tp)) |
103 | return -EFAULT; | 109 | return -EFAULT; |
104 | return 0; | 110 | return 0; |
105 | default: | 111 | default: |
@@ -138,44 +144,45 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, | |||
138 | } | 144 | } |
139 | 145 | ||
140 | #ifdef CONFIG_COMPAT | 146 | #ifdef CONFIG_COMPAT |
147 | COMPAT_SYS_NI(timer_create); | ||
148 | COMPAT_SYS_NI(clock_adjtime); | ||
149 | COMPAT_SYS_NI(timer_settime); | ||
150 | COMPAT_SYS_NI(timer_gettime); | ||
151 | COMPAT_SYS_NI(getitimer); | ||
152 | COMPAT_SYS_NI(setitimer); | ||
153 | |||
141 | COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, | 154 | COMPAT_SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, |
142 | struct compat_timespec __user *, tp) | 155 | struct compat_timespec __user *, tp) |
143 | { | 156 | { |
144 | struct timespec64 new_tp64; | 157 | struct timespec64 new_tp; |
145 | struct timespec new_tp; | ||
146 | 158 | ||
147 | if (which_clock != CLOCK_REALTIME) | 159 | if (which_clock != CLOCK_REALTIME) |
148 | return -EINVAL; | 160 | return -EINVAL; |
149 | if (compat_get_timespec(&new_tp, tp)) | 161 | if (compat_get_timespec64(&new_tp, tp)) |
150 | return -EFAULT; | 162 | return -EFAULT; |
151 | 163 | ||
152 | new_tp64 = timespec_to_timespec64(new_tp); | 164 | return do_sys_settimeofday64(&new_tp, NULL); |
153 | return do_sys_settimeofday64(&new_tp64, NULL); | ||
154 | } | 165 | } |
155 | 166 | ||
156 | COMPAT_SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | 167 | COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, |
157 | struct compat_timespec __user *,tp) | 168 | struct compat_timespec __user *, tp) |
158 | { | 169 | { |
159 | struct timespec64 kernel_tp64; | 170 | int ret; |
160 | struct timespec kernel_tp; | 171 | struct timespec64 kernel_tp; |
161 | 172 | ||
162 | switch (which_clock) { | 173 | ret = do_clock_gettime(which_clock, &kernel_tp); |
163 | case CLOCK_REALTIME: ktime_get_real_ts64(&kernel_tp64); break; | 174 | if (ret) |
164 | case CLOCK_MONOTONIC: ktime_get_ts64(&kernel_tp64); break; | 175 | return ret; |
165 | case CLOCK_BOOTTIME: get_monotonic_boottime64(&kernel_tp64); break; | ||
166 | default: return -EINVAL; | ||
167 | } | ||
168 | 176 | ||
169 | kernel_tp = timespec64_to_timespec(kernel_tp64); | 177 | if (compat_put_timespec64(&kernel_tp, tp)) |
170 | if (compat_put_timespec(&kernel_tp, tp)) | ||
171 | return -EFAULT; | 178 | return -EFAULT; |
172 | return 0; | 179 | return 0; |
173 | } | 180 | } |
174 | 181 | ||
175 | COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, | 182 | COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, |
176 | struct compat_timespec __user *, tp) | 183 | struct compat_timespec __user *, tp) |
177 | { | 184 | { |
178 | struct timespec rtn_tp = { | 185 | struct timespec64 rtn_tp = { |
179 | .tv_sec = 0, | 186 | .tv_sec = 0, |
180 | .tv_nsec = hrtimer_resolution, | 187 | .tv_nsec = hrtimer_resolution, |
181 | }; | 188 | }; |
@@ -184,13 +191,14 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, | |||
184 | case CLOCK_REALTIME: | 191 | case CLOCK_REALTIME: |
185 | case CLOCK_MONOTONIC: | 192 | case CLOCK_MONOTONIC: |
186 | case CLOCK_BOOTTIME: | 193 | case CLOCK_BOOTTIME: |
187 | if (compat_put_timespec(&rtn_tp, tp)) | 194 | if (compat_put_timespec64(&rtn_tp, tp)) |
188 | return -EFAULT; | 195 | return -EFAULT; |
189 | return 0; | 196 | return 0; |
190 | default: | 197 | default: |
191 | return -EINVAL; | 198 | return -EINVAL; |
192 | } | 199 | } |
193 | } | 200 | } |
201 | |||
194 | COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, | 202 | COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, |
195 | struct compat_timespec __user *, rqtp, | 203 | struct compat_timespec __user *, rqtp, |
196 | struct compat_timespec __user *, rmtp) | 204 | struct compat_timespec __user *, rmtp) |
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 82d67be7d9d1..13d6881f908b 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
@@ -739,13 +739,11 @@ static int do_timer_gettime(timer_t timer_id, struct itimerspec64 *setting) | |||
739 | SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, | 739 | SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, |
740 | struct itimerspec __user *, setting) | 740 | struct itimerspec __user *, setting) |
741 | { | 741 | { |
742 | struct itimerspec64 cur_setting64; | 742 | struct itimerspec64 cur_setting; |
743 | 743 | ||
744 | int ret = do_timer_gettime(timer_id, &cur_setting64); | 744 | int ret = do_timer_gettime(timer_id, &cur_setting); |
745 | if (!ret) { | 745 | if (!ret) { |
746 | struct itimerspec cur_setting; | 746 | if (put_itimerspec64(&cur_setting, setting)) |
747 | cur_setting = itimerspec64_to_itimerspec(&cur_setting64); | ||
748 | if (copy_to_user(setting, &cur_setting, sizeof (cur_setting))) | ||
749 | ret = -EFAULT; | 747 | ret = -EFAULT; |
750 | } | 748 | } |
751 | return ret; | 749 | return ret; |
@@ -755,13 +753,11 @@ SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, | |||
755 | COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, | 753 | COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id, |
756 | struct compat_itimerspec __user *, setting) | 754 | struct compat_itimerspec __user *, setting) |
757 | { | 755 | { |
758 | struct itimerspec64 cur_setting64; | 756 | struct itimerspec64 cur_setting; |
759 | 757 | ||
760 | int ret = do_timer_gettime(timer_id, &cur_setting64); | 758 | int ret = do_timer_gettime(timer_id, &cur_setting); |
761 | if (!ret) { | 759 | if (!ret) { |
762 | struct itimerspec cur_setting; | 760 | if (put_compat_itimerspec64(&cur_setting, setting)) |
763 | cur_setting = itimerspec64_to_itimerspec(&cur_setting64); | ||
764 | if (put_compat_itimerspec(setting, &cur_setting)) | ||
765 | ret = -EFAULT; | 761 | ret = -EFAULT; |
766 | } | 762 | } |
767 | return ret; | 763 | return ret; |
@@ -907,23 +903,19 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, | |||
907 | const struct itimerspec __user *, new_setting, | 903 | const struct itimerspec __user *, new_setting, |
908 | struct itimerspec __user *, old_setting) | 904 | struct itimerspec __user *, old_setting) |
909 | { | 905 | { |
910 | struct itimerspec64 new_spec64, old_spec64; | 906 | struct itimerspec64 new_spec, old_spec; |
911 | struct itimerspec64 *rtn = old_setting ? &old_spec64 : NULL; | 907 | struct itimerspec64 *rtn = old_setting ? &old_spec : NULL; |
912 | struct itimerspec new_spec; | ||
913 | int error = 0; | 908 | int error = 0; |
914 | 909 | ||
915 | if (!new_setting) | 910 | if (!new_setting) |
916 | return -EINVAL; | 911 | return -EINVAL; |
917 | 912 | ||
918 | if (copy_from_user(&new_spec, new_setting, sizeof (new_spec))) | 913 | if (get_itimerspec64(&new_spec, new_setting)) |
919 | return -EFAULT; | 914 | return -EFAULT; |
920 | new_spec64 = itimerspec_to_itimerspec64(&new_spec); | ||
921 | 915 | ||
922 | error = do_timer_settime(timer_id, flags, &new_spec64, rtn); | 916 | error = do_timer_settime(timer_id, flags, &new_spec, rtn); |
923 | if (!error && old_setting) { | 917 | if (!error && old_setting) { |
924 | struct itimerspec old_spec; | 918 | if (put_itimerspec64(&old_spec, old_setting)) |
925 | old_spec = itimerspec64_to_itimerspec(&old_spec64); | ||
926 | if (copy_to_user(old_setting, &old_spec, sizeof (old_spec))) | ||
927 | error = -EFAULT; | 919 | error = -EFAULT; |
928 | } | 920 | } |
929 | return error; | 921 | return error; |
@@ -934,22 +926,18 @@ COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, | |||
934 | struct compat_itimerspec __user *, new, | 926 | struct compat_itimerspec __user *, new, |
935 | struct compat_itimerspec __user *, old) | 927 | struct compat_itimerspec __user *, old) |
936 | { | 928 | { |
937 | struct itimerspec64 new_spec64, old_spec64; | 929 | struct itimerspec64 new_spec, old_spec; |
938 | struct itimerspec64 *rtn = old ? &old_spec64 : NULL; | 930 | struct itimerspec64 *rtn = old ? &old_spec : NULL; |
939 | struct itimerspec new_spec; | ||
940 | int error = 0; | 931 | int error = 0; |
941 | 932 | ||
942 | if (!new) | 933 | if (!new) |
943 | return -EINVAL; | 934 | return -EINVAL; |
944 | if (get_compat_itimerspec(&new_spec, new)) | 935 | if (get_compat_itimerspec64(&new_spec, new)) |
945 | return -EFAULT; | 936 | return -EFAULT; |
946 | 937 | ||
947 | new_spec64 = itimerspec_to_itimerspec64(&new_spec); | 938 | error = do_timer_settime(timer_id, flags, &new_spec, rtn); |
948 | error = do_timer_settime(timer_id, flags, &new_spec64, rtn); | ||
949 | if (!error && old) { | 939 | if (!error && old) { |
950 | struct itimerspec old_spec; | 940 | if (put_compat_itimerspec64(&old_spec, old)) |
951 | old_spec = itimerspec64_to_itimerspec(&old_spec64); | ||
952 | if (put_compat_itimerspec(old, &old_spec)) | ||
953 | error = -EFAULT; | 941 | error = -EFAULT; |
954 | } | 942 | } |
955 | return error; | 943 | return error; |
@@ -1049,34 +1037,30 @@ SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock, | |||
1049 | const struct timespec __user *, tp) | 1037 | const struct timespec __user *, tp) |
1050 | { | 1038 | { |
1051 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1039 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1052 | struct timespec64 new_tp64; | 1040 | struct timespec64 new_tp; |
1053 | struct timespec new_tp; | ||
1054 | 1041 | ||
1055 | if (!kc || !kc->clock_set) | 1042 | if (!kc || !kc->clock_set) |
1056 | return -EINVAL; | 1043 | return -EINVAL; |
1057 | 1044 | ||
1058 | if (copy_from_user(&new_tp, tp, sizeof (*tp))) | 1045 | if (get_timespec64(&new_tp, tp)) |
1059 | return -EFAULT; | 1046 | return -EFAULT; |
1060 | new_tp64 = timespec_to_timespec64(new_tp); | ||
1061 | 1047 | ||
1062 | return kc->clock_set(which_clock, &new_tp64); | 1048 | return kc->clock_set(which_clock, &new_tp); |
1063 | } | 1049 | } |
1064 | 1050 | ||
1065 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, | 1051 | SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock, |
1066 | struct timespec __user *,tp) | 1052 | struct timespec __user *,tp) |
1067 | { | 1053 | { |
1068 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1054 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1069 | struct timespec64 kernel_tp64; | 1055 | struct timespec64 kernel_tp; |
1070 | struct timespec kernel_tp; | ||
1071 | int error; | 1056 | int error; |
1072 | 1057 | ||
1073 | if (!kc) | 1058 | if (!kc) |
1074 | return -EINVAL; | 1059 | return -EINVAL; |
1075 | 1060 | ||
1076 | error = kc->clock_get(which_clock, &kernel_tp64); | 1061 | error = kc->clock_get(which_clock, &kernel_tp); |
1077 | kernel_tp = timespec64_to_timespec(kernel_tp64); | ||
1078 | 1062 | ||
1079 | if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp))) | 1063 | if (!error && put_timespec64(&kernel_tp, tp)) |
1080 | error = -EFAULT; | 1064 | error = -EFAULT; |
1081 | 1065 | ||
1082 | return error; | 1066 | return error; |
@@ -1109,17 +1093,15 @@ SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, | |||
1109 | struct timespec __user *, tp) | 1093 | struct timespec __user *, tp) |
1110 | { | 1094 | { |
1111 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1095 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1112 | struct timespec64 rtn_tp64; | 1096 | struct timespec64 rtn_tp; |
1113 | struct timespec rtn_tp; | ||
1114 | int error; | 1097 | int error; |
1115 | 1098 | ||
1116 | if (!kc) | 1099 | if (!kc) |
1117 | return -EINVAL; | 1100 | return -EINVAL; |
1118 | 1101 | ||
1119 | error = kc->clock_getres(which_clock, &rtn_tp64); | 1102 | error = kc->clock_getres(which_clock, &rtn_tp); |
1120 | rtn_tp = timespec64_to_timespec(rtn_tp64); | ||
1121 | 1103 | ||
1122 | if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) | 1104 | if (!error && tp && put_timespec64(&rtn_tp, tp)) |
1123 | error = -EFAULT; | 1105 | error = -EFAULT; |
1124 | 1106 | ||
1125 | return error; | 1107 | return error; |
@@ -1131,38 +1113,33 @@ COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock, | |||
1131 | struct compat_timespec __user *, tp) | 1113 | struct compat_timespec __user *, tp) |
1132 | { | 1114 | { |
1133 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1115 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1134 | struct timespec64 new_tp64; | 1116 | struct timespec64 ts; |
1135 | struct timespec new_tp; | ||
1136 | 1117 | ||
1137 | if (!kc || !kc->clock_set) | 1118 | if (!kc || !kc->clock_set) |
1138 | return -EINVAL; | 1119 | return -EINVAL; |
1139 | 1120 | ||
1140 | if (compat_get_timespec(&new_tp, tp)) | 1121 | if (compat_get_timespec64(&ts, tp)) |
1141 | return -EFAULT; | 1122 | return -EFAULT; |
1142 | 1123 | ||
1143 | new_tp64 = timespec_to_timespec64(new_tp); | 1124 | return kc->clock_set(which_clock, &ts); |
1144 | |||
1145 | return kc->clock_set(which_clock, &new_tp64); | ||
1146 | } | 1125 | } |
1147 | 1126 | ||
1148 | COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, | 1127 | COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock, |
1149 | struct compat_timespec __user *, tp) | 1128 | struct compat_timespec __user *, tp) |
1150 | { | 1129 | { |
1151 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1130 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1152 | struct timespec64 kernel_tp64; | 1131 | struct timespec64 ts; |
1153 | struct timespec kernel_tp; | 1132 | int err; |
1154 | int error; | ||
1155 | 1133 | ||
1156 | if (!kc) | 1134 | if (!kc) |
1157 | return -EINVAL; | 1135 | return -EINVAL; |
1158 | 1136 | ||
1159 | error = kc->clock_get(which_clock, &kernel_tp64); | 1137 | err = kc->clock_get(which_clock, &ts); |
1160 | kernel_tp = timespec64_to_timespec(kernel_tp64); | ||
1161 | 1138 | ||
1162 | if (!error && compat_put_timespec(&kernel_tp, tp)) | 1139 | if (!err && compat_put_timespec64(&ts, tp)) |
1163 | error = -EFAULT; | 1140 | err = -EFAULT; |
1164 | 1141 | ||
1165 | return error; | 1142 | return err; |
1166 | } | 1143 | } |
1167 | 1144 | ||
1168 | COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, | 1145 | COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock, |
@@ -1193,21 +1170,19 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock, | |||
1193 | struct compat_timespec __user *, tp) | 1170 | struct compat_timespec __user *, tp) |
1194 | { | 1171 | { |
1195 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1172 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1196 | struct timespec64 rtn_tp64; | 1173 | struct timespec64 ts; |
1197 | struct timespec rtn_tp; | 1174 | int err; |
1198 | int error; | ||
1199 | 1175 | ||
1200 | if (!kc) | 1176 | if (!kc) |
1201 | return -EINVAL; | 1177 | return -EINVAL; |
1202 | 1178 | ||
1203 | error = kc->clock_getres(which_clock, &rtn_tp64); | 1179 | err = kc->clock_getres(which_clock, &ts); |
1204 | rtn_tp = timespec64_to_timespec(rtn_tp64); | 1180 | if (!err && tp && compat_put_timespec64(&ts, tp)) |
1205 | 1181 | return -EFAULT; | |
1206 | if (!error && tp && compat_put_timespec(&rtn_tp, tp)) | ||
1207 | error = -EFAULT; | ||
1208 | 1182 | ||
1209 | return error; | 1183 | return err; |
1210 | } | 1184 | } |
1185 | |||
1211 | #endif | 1186 | #endif |
1212 | 1187 | ||
1213 | /* | 1188 | /* |
@@ -1226,26 +1201,24 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, | |||
1226 | struct timespec __user *, rmtp) | 1201 | struct timespec __user *, rmtp) |
1227 | { | 1202 | { |
1228 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1203 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1229 | struct timespec64 t64; | 1204 | struct timespec64 t; |
1230 | struct timespec t; | ||
1231 | 1205 | ||
1232 | if (!kc) | 1206 | if (!kc) |
1233 | return -EINVAL; | 1207 | return -EINVAL; |
1234 | if (!kc->nsleep) | 1208 | if (!kc->nsleep) |
1235 | return -ENANOSLEEP_NOTSUP; | 1209 | return -ENANOSLEEP_NOTSUP; |
1236 | 1210 | ||
1237 | if (copy_from_user(&t, rqtp, sizeof (struct timespec))) | 1211 | if (get_timespec64(&t, rqtp)) |
1238 | return -EFAULT; | 1212 | return -EFAULT; |
1239 | 1213 | ||
1240 | t64 = timespec_to_timespec64(t); | 1214 | if (!timespec64_valid(&t)) |
1241 | if (!timespec64_valid(&t64)) | ||
1242 | return -EINVAL; | 1215 | return -EINVAL; |
1243 | if (flags & TIMER_ABSTIME) | 1216 | if (flags & TIMER_ABSTIME) |
1244 | rmtp = NULL; | 1217 | rmtp = NULL; |
1245 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; | 1218 | current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE; |
1246 | current->restart_block.nanosleep.rmtp = rmtp; | 1219 | current->restart_block.nanosleep.rmtp = rmtp; |
1247 | 1220 | ||
1248 | return kc->nsleep(which_clock, flags, &t64); | 1221 | return kc->nsleep(which_clock, flags, &t); |
1249 | } | 1222 | } |
1250 | 1223 | ||
1251 | #ifdef CONFIG_COMPAT | 1224 | #ifdef CONFIG_COMPAT |
@@ -1254,26 +1227,24 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags, | |||
1254 | struct compat_timespec __user *, rmtp) | 1227 | struct compat_timespec __user *, rmtp) |
1255 | { | 1228 | { |
1256 | const struct k_clock *kc = clockid_to_kclock(which_clock); | 1229 | const struct k_clock *kc = clockid_to_kclock(which_clock); |
1257 | struct timespec64 t64; | 1230 | struct timespec64 t; |
1258 | struct timespec t; | ||
1259 | 1231 | ||
1260 | if (!kc) | 1232 | if (!kc) |
1261 | return -EINVAL; | 1233 | return -EINVAL; |
1262 | if (!kc->nsleep) | 1234 | if (!kc->nsleep) |
1263 | return -ENANOSLEEP_NOTSUP; | 1235 | return -ENANOSLEEP_NOTSUP; |
1264 | 1236 | ||
1265 | if (compat_get_timespec(&t, rqtp)) | 1237 | if (compat_get_timespec64(&t, rqtp)) |
1266 | return -EFAULT; | 1238 | return -EFAULT; |
1267 | 1239 | ||
1268 | t64 = timespec_to_timespec64(t); | 1240 | if (!timespec64_valid(&t)) |
1269 | if (!timespec64_valid(&t64)) | ||
1270 | return -EINVAL; | 1241 | return -EINVAL; |
1271 | if (flags & TIMER_ABSTIME) | 1242 | if (flags & TIMER_ABSTIME) |
1272 | rmtp = NULL; | 1243 | rmtp = NULL; |
1273 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; | 1244 | current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE; |
1274 | current->restart_block.nanosleep.compat_rmtp = rmtp; | 1245 | current->restart_block.nanosleep.compat_rmtp = rmtp; |
1275 | 1246 | ||
1276 | return kc->nsleep(which_clock, flags, &t64); | 1247 | return kc->nsleep(which_clock, flags, &t); |
1277 | } | 1248 | } |
1278 | #endif | 1249 | #endif |
1279 | 1250 | ||
diff --git a/kernel/time/time.c b/kernel/time/time.c index 7c89e437c4d7..44a8c1402133 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c | |||
@@ -890,3 +890,61 @@ struct timespec64 timespec64_add_safe(const struct timespec64 lhs, | |||
890 | 890 | ||
891 | return res; | 891 | return res; |
892 | } | 892 | } |
893 | |||
894 | int get_timespec64(struct timespec64 *ts, | ||
895 | const struct timespec __user *uts) | ||
896 | { | ||
897 | struct timespec kts; | ||
898 | int ret; | ||
899 | |||
900 | ret = copy_from_user(&kts, uts, sizeof(kts)); | ||
901 | if (ret) | ||
902 | return -EFAULT; | ||
903 | |||
904 | ts->tv_sec = kts.tv_sec; | ||
905 | ts->tv_nsec = kts.tv_nsec; | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | EXPORT_SYMBOL_GPL(get_timespec64); | ||
910 | |||
911 | int put_timespec64(const struct timespec64 *ts, | ||
912 | struct timespec __user *uts) | ||
913 | { | ||
914 | struct timespec kts = { | ||
915 | .tv_sec = ts->tv_sec, | ||
916 | .tv_nsec = ts->tv_nsec | ||
917 | }; | ||
918 | return copy_to_user(uts, &kts, sizeof(kts)) ? -EFAULT : 0; | ||
919 | } | ||
920 | EXPORT_SYMBOL_GPL(put_timespec64); | ||
921 | |||
922 | int get_itimerspec64(struct itimerspec64 *it, | ||
923 | const struct itimerspec __user *uit) | ||
924 | { | ||
925 | int ret; | ||
926 | |||
927 | ret = get_timespec64(&it->it_interval, &uit->it_interval); | ||
928 | if (ret) | ||
929 | return ret; | ||
930 | |||
931 | ret = get_timespec64(&it->it_value, &uit->it_value); | ||
932 | |||
933 | return ret; | ||
934 | } | ||
935 | EXPORT_SYMBOL_GPL(get_itimerspec64); | ||
936 | |||
937 | int put_itimerspec64(const struct itimerspec64 *it, | ||
938 | struct itimerspec __user *uit) | ||
939 | { | ||
940 | int ret; | ||
941 | |||
942 | ret = put_timespec64(&it->it_interval, &uit->it_interval); | ||
943 | if (ret) | ||
944 | return ret; | ||
945 | |||
946 | ret = put_timespec64(&it->it_value, &uit->it_value); | ||
947 | |||
948 | return ret; | ||
949 | } | ||
950 | EXPORT_SYMBOL_GPL(put_itimerspec64); | ||