Merge branch 'timers-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Jul 2017 22:34:35 +0000 (15:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Jul 2017 22:34:35 +0000 (15:34 -0700)
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

1  2 
kernel/compat.c
kernel/time/posix-cpu-timers.c

diff --combined kernel/compat.c
@@@ -120,6 -120,50 +120,50 @@@ static int __compat_put_timespec(const 
                        __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
  }
  
+ static int __compat_get_timespec64(struct timespec64 *ts64,
+                                  const struct compat_timespec __user *cts)
+ {
+       struct compat_timespec ts;
+       int ret;
+       ret = copy_from_user(&ts, cts, sizeof(ts));
+       if (ret)
+               return -EFAULT;
+       ts64->tv_sec = ts.tv_sec;
+       ts64->tv_nsec = ts.tv_nsec;
+       return 0;
+ }
+ static int __compat_put_timespec64(const struct timespec64 *ts64,
+                                  struct compat_timespec __user *cts)
+ {
+       struct compat_timespec ts = {
+               .tv_sec = ts64->tv_sec,
+               .tv_nsec = ts64->tv_nsec
+       };
+       return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0;
+ }
+ int compat_get_timespec64(struct timespec64 *ts, const void __user *uts)
+ {
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
+       else
+               return __compat_get_timespec64(ts, uts);
+ }
+ EXPORT_SYMBOL_GPL(compat_get_timespec64);
+ int compat_put_timespec64(const struct timespec64 *ts, void __user *uts)
+ {
+       if (COMPAT_USE_64BIT_TIME)
+               return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
+       else
+               return __compat_put_timespec64(ts, uts);
+ }
+ EXPORT_SYMBOL_GPL(compat_put_timespec64);
  int compat_get_timeval(struct timeval *tv, const void __user *utv)
  {
        if (COMPAT_USE_64BIT_TIME)
@@@ -396,6 -440,72 +440,6 @@@ int put_compat_rusage(const struct rusa
        return 0;
  }
  
 -COMPAT_SYSCALL_DEFINE4(wait4,
 -      compat_pid_t, pid,
 -      compat_uint_t __user *, stat_addr,
 -      int, options,
 -      struct compat_rusage __user *, ru)
 -{
 -      if (!ru) {
 -              return sys_wait4(pid, stat_addr, options, NULL);
 -      } else {
 -              struct rusage r;
 -              int ret;
 -              unsigned int status;
 -              mm_segment_t old_fs = get_fs();
 -
 -              set_fs (KERNEL_DS);
 -              ret = sys_wait4(pid,
 -                              (stat_addr ?
 -                               (unsigned int __user *) &status : NULL),
 -                              options, (struct rusage __user *) &r);
 -              set_fs (old_fs);
 -
 -              if (ret > 0) {
 -                      if (put_compat_rusage(&r, ru))
 -                              return -EFAULT;
 -                      if (stat_addr && put_user(status, stat_addr))
 -                              return -EFAULT;
 -              }
 -              return ret;
 -      }
 -}
 -
 -COMPAT_SYSCALL_DEFINE5(waitid,
 -              int, which, compat_pid_t, pid,
 -              struct compat_siginfo __user *, uinfo, int, options,
 -              struct compat_rusage __user *, uru)
 -{
 -      siginfo_t info;
 -      struct rusage ru;
 -      long ret;
 -      mm_segment_t old_fs = get_fs();
 -
 -      memset(&info, 0, sizeof(info));
 -
 -      set_fs(KERNEL_DS);
 -      ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
 -                       uru ? (struct rusage __user *)&ru : NULL);
 -      set_fs(old_fs);
 -
 -      if ((ret < 0) || (info.si_signo == 0))
 -              return ret;
 -
 -      if (uru) {
 -              /* sys_waitid() overwrites everything in ru */
 -              if (COMPAT_USE_64BIT_TIME)
 -                      ret = copy_to_user(uru, &ru, sizeof(ru));
 -              else
 -                      ret = put_compat_rusage(&ru, uru);
 -              if (ret)
 -                      return -EFAULT;
 -      }
 -
 -      BUG_ON(info.si_code & __SI_MASK);
 -      info.si_code |= __SI_CHLD;
 -      return copy_siginfo_to_user32(uinfo, &info);
 -}
 -
  static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
                                    unsigned len, struct cpumask *new_mask)
  {
@@@ -476,6 -586,27 +520,27 @@@ int put_compat_itimerspec(struct compat
        return 0;
  }
  
+ int get_compat_itimerspec64(struct itimerspec64 *its,
+                       const struct compat_itimerspec __user *uits)
+ {
+       if (__compat_get_timespec64(&its->it_interval, &uits->it_interval) ||
+           __compat_get_timespec64(&its->it_value, &uits->it_value))
+               return -EFAULT;
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(get_compat_itimerspec64);
+ int put_compat_itimerspec64(const struct itimerspec64 *its,
+                       struct compat_itimerspec __user *uits)
+ {
+       if (__compat_put_timespec64(&its->it_interval, &uits->it_interval) ||
+           __compat_put_timespec64(&its->it_value, &uits->it_value))
+               return -EFAULT;
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(put_compat_itimerspec64);
  /*
   * We currently only need the following fields from the sigevent
   * structure: sigev_value, sigev_signo, sig_notify and (sometimes
@@@ -580,11 -580,7 +580,11 @@@ static int posix_cpu_timer_set(struct k
  
        WARN_ON_ONCE(p == NULL);
  
 -      new_expires = timespec64_to_ns(&new->it_value);
 +      /*
 +       * Use the to_ktime conversion because that clamps the maximum
 +       * value to KTIME_MAX and avoid multiplication overflows.
 +       */
 +      new_expires = ktime_to_ns(timespec64_to_ktime(new->it_value));
  
        /*
         * Protect against sighand release/switch in exit/exec and p->cpu_timers
@@@ -1318,12 -1314,8 +1318,8 @@@ static int do_cpu_nanosleep(const clock
                 */
                restart = &current->restart_block;
                restart->nanosleep.expires = expires;
-               if (restart->nanosleep.type != TT_NONE) {
-                       struct timespec ts;
-                       ts = timespec64_to_timespec(it.it_value);
-                       error = nanosleep_copyout(restart, &ts);
-               }
+               if (restart->nanosleep.type != TT_NONE)
+                       error = nanosleep_copyout(restart, &it.it_value);
        }
  
        return error;