As part of the work to make these system calls handle 64-bit
time_t, we move the compat handling closer to the actual system
calls. The next step is to combine the actual implementation.

Signed-off-by: Arnd Bergmann <[email protected]>
---
 include/linux/compat_time.h  |   4 +
 include/linux/posix-timers.h |   2 -
 kernel/compat.c              | 177 +------------------------------------------
 kernel/time/posix-timers.c   | 174 +++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 179 insertions(+), 178 deletions(-)

diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
index 37c3860d97fa..afaa1ca7986d 100644
--- a/include/linux/compat_time.h
+++ b/include/linux/compat_time.h
@@ -120,6 +120,10 @@ extern int compat_get_timeval(struct timeval *, const void 
__user *);
 extern int compat_put_timeval(const struct timeval *, void __user *);
 extern int compat_get_timespec64(struct timespec64 *ts, const void __user 
*uts);
 extern int compat_put_timespec64(const struct timespec64 *ts, void __user 
*uts);
+struct compat_timex;
+struct timex;
+extern int compat_get_timex(struct timex *txc, struct compat_timex __user 
*utp);
+extern int compat_put_timex(struct compat_timex __user *utp, struct timex 
*txc);
 
 /*
  * This function convert a timespec if necessary and returns a *user
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index bc44076f7e0b..2d676be022e4 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -134,8 +134,6 @@ bool posix_cpu_timers_can_stop_tick(struct task_struct 
*tsk);
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
                           cputime_t *newval, cputime_t *oldval);
 
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
 int get_itimerspec(struct itimerspec *it,
                   const struct __kernel_itimerspec __user *uit);
diff --git a/kernel/compat.c b/kernel/compat.c
index 13653247ba6c..22a20bd37a73 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -33,7 +33,7 @@
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_COMPAT_TIME
-static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
+int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
 {
        memset(txc, 0, sizeof(struct timex));
 
@@ -63,7 +63,7 @@ static int compat_get_timex(struct timex *txc, struct 
compat_timex __user *utp)
        return 0;
 }
 
-static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
+int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
 {
        if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
                        __put_user(txc->modes, &utp->modes) ||
@@ -743,180 +743,7 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, 
which_clock,
 
        return sys_timer_create(which_clock, event, created_timer_id);
 }
-#endif
-
-#ifdef CONFIG_COMPAT_TIME
-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)
-{
-       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)
-{
-       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_adjtime, clockid_t, which_clock,
-                      struct compat_timex __user *, utp)
-{
-       struct timex txc;
-       mm_segment_t oldfs;
-       int err, ret;
-
-       err = compat_get_timex(&txc, utp);
-       if (err)
-               return err;
-
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
-       set_fs(oldfs);
-
-       err = compat_put_timex(utp, &txc);
-       if (err)
-               return err;
-
-       return ret;
-}
-
-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;
-}
-
-static long compat_clock_nanosleep_restart(struct restart_block *restart)
-{
-       long err;
-       mm_segment_t oldfs;
-       struct timespec tu;
-       struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
-
-       restart->nanosleep.rmtp = (struct timespec __user *) &tu;
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       err = clock_nanosleep_restart(restart);
-       set_fs(oldfs);
-
-       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-           compat_put_timespec(&tu, rmtp))
-               return -EFAULT;
-
-       if (err == -ERESTART_RESTARTBLOCK) {
-               restart->fn = compat_clock_nanosleep_restart;
-               restart->nanosleep.compat_rmtp = rmtp;
-       }
-       return err;
-}
-
-COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
-                      struct compat_timespec __user *, rqtp,
-                      struct compat_timespec __user *, rmtp)
-{
-       long err;
-       mm_segment_t oldfs;
-       struct timespec in, out;
-       struct restart_block *restart;
-
-       if (compat_get_timespec(&in, rqtp))
-               return -EFAULT;
-
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       err = sys_clock_nanosleep(which_clock, flags,
-                                 (struct timespec __user *) &in,
-                                 (struct timespec __user *) &out);
-       set_fs(oldfs);
-
-       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-           compat_put_timespec(&out, rmtp))
-               return -EFAULT;
-
-       if (err == -ERESTART_RESTARTBLOCK) {
-               restart = &current->restart_block;
-               restart->fn = compat_clock_nanosleep_restart;
-               restart->nanosleep.compat_rmtp = rmtp;
-       }
-       return err;
-}
-#endif
-
-#ifdef CONFIG_COMPAT
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index c99b10725025..4c0d43c7c015 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>
 #include <linux/list.h>
 #include <linux/init.h>
+#include <linux/compat.h>
 #include <linux/compiler.h>
 #include <linux/hash.h>
 #include <linux/posix-clock.h>
@@ -1146,7 +1147,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, 
which_clock, int, flags,
  * 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)
+static long clock_nanosleep_restart(struct restart_block *restart_block)
 {
        clockid_t which_clock = restart_block->nanosleep.clockid;
        struct k_clock *kc = clockid_to_kclock(which_clock);
@@ -1156,3 +1157,174 @@ long clock_nanosleep_restart(struct restart_block 
*restart_block)
 
        return kc->nsleep_restart(restart_block);
 }
+
+#ifdef CONFIG_COMPAT_TIME
+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)
+{
+       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)
+{
+       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_adjtime, clockid_t, which_clock,
+                      struct compat_timex __user *, utp)
+{
+       struct timex txc;
+       mm_segment_t oldfs;
+       int err, ret;
+
+       err = compat_get_timex(&txc, utp);
+       if (err)
+               return err;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
+       set_fs(oldfs);
+
+       err = compat_put_timex(utp, &txc);
+       if (err)
+               return err;
+
+       return ret;
+}
+
+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;
+}
+
+static long compat_clock_nanosleep_restart(struct restart_block *restart)
+{
+       long err;
+       mm_segment_t oldfs;
+       struct timespec tu;
+       struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
+
+       restart->nanosleep.rmtp = (struct timespec __user *) &tu;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       err = clock_nanosleep_restart(restart);
+       set_fs(oldfs);
+
+       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+           compat_put_timespec(&tu, rmtp))
+               return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->nanosleep.compat_rmtp = rmtp;
+       }
+       return err;
+}
+
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+                      struct compat_timespec __user *, rqtp,
+                      struct compat_timespec __user *, rmtp)
+{
+       long err;
+       mm_segment_t oldfs;
+       struct timespec in, out;
+       struct restart_block *restart;
+
+       if (compat_get_timespec(&in, rqtp))
+               return -EFAULT;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       err = sys_clock_nanosleep(which_clock, flags,
+                                 (struct timespec __user *) &in,
+                                 (struct timespec __user *) &out);
+       set_fs(oldfs);
+
+       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+           compat_put_timespec(&out, rmtp))
+               return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart = &current->restart_block;
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->nanosleep.compat_rmtp = rmtp;
+       }
+       return err;
+}
+#endif
-- 
2.1.0.rc2

_______________________________________________
Y2038 mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/y2038

Reply via email to