time: introduce {get,put}_itimerspec64
authorDeepa Dinamani <deepa.kernel@gmail.com>
Sat, 24 Jun 2017 18:45:03 +0000 (11:45 -0700)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 26 Jun 2017 01:58:46 +0000 (21:58 -0400)
As we change the user space type for the timerfd and posix timer
functions to newer data types, we need some form of conversion
helpers to avoid duplicating that logic.

Suggested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
include/linux/compat.h
include/linux/posix-timers.h
include/linux/time.h
kernel/compat.c
kernel/time/time.c

index 3eb04016ffa9378f5c86d75296a58305abe5cfa1..2ed54020ace0c994c5fce8dd3e513f8818303d93 100644 (file)
@@ -166,6 +166,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 *, const void __user *);
 extern int compat_put_timespec64(const struct timespec64 *, void __user *);
+extern int get_compat_itimerspec64(struct itimerspec64 *its,
+                       const struct compat_itimerspec __user *uits);
+extern int put_compat_itimerspec64(const struct itimerspec64 *its,
+                       struct compat_itimerspec __user *uits);
 
 /*
  * This function convert a timespec if necessary and returns a *user
index 29f1b7f09ced6bf51385a02a9601fe25f671ea86..62839fd04dce25dc63fa8ceb175eb94ae915171a 100644 (file)
@@ -113,5 +113,4 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
 
 void posixtimer_rearm(struct siginfo *info);
-
 #endif
index 36afb579495fa18c75a08ae230d31f6d8fe2a507..f9858d7e63611d4b0a36a119197ebda22e249bd4 100644 (file)
@@ -12,6 +12,10 @@ int get_timespec64(struct timespec64 *ts,
                const struct timespec __user *uts);
 int put_timespec64(const struct timespec64 *ts,
                struct timespec __user *uts);
+int get_itimerspec64(struct itimerspec64 *it,
+                       const struct itimerspec __user *uit);
+int put_itimerspec64(const struct itimerspec64 *it,
+                       struct itimerspec __user *uit);
 
 #define TIME_T_MAX     (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
 
@@ -275,4 +279,13 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
        a->tv_nsec = ns;
 }
 
+static inline bool itimerspec64_valid(const struct itimerspec64 *its)
+{
+       if (!timespec64_valid(&(its->it_interval)) ||
+               !timespec64_valid(&(its->it_value)))
+               return false;
+
+       return true;
+}
+
 #endif
index 73f26ba44a8ab8c14a6f06c7e2ca36d63e516ab7..a350deda503abc6e8a6a4b4ac9dc4c3e40e73046 100644 (file)
@@ -586,6 +586,27 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
        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
index adb9853ca6b0c1c978326dd866fb7ba3b3df895b..44a8c1402133be79d00fd6e66eb5825404277185 100644 (file)
@@ -918,3 +918,33 @@ int put_timespec64(const struct timespec64 *ts,
        return copy_to_user(uts, &kts, sizeof(kts)) ? -EFAULT : 0;
 }
 EXPORT_SYMBOL_GPL(put_timespec64);
+
+int get_itimerspec64(struct itimerspec64 *it,
+                       const struct itimerspec __user *uit)
+{
+       int ret;
+
+       ret = get_timespec64(&it->it_interval, &uit->it_interval);
+       if (ret)
+               return ret;
+
+       ret = get_timespec64(&it->it_value, &uit->it_value);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(get_itimerspec64);
+
+int put_itimerspec64(const struct itimerspec64 *it,
+                       struct itimerspec __user *uit)
+{
+       int ret;
+
+       ret = put_timespec64(&it->it_interval, &uit->it_interval);
+       if (ret)
+               return ret;
+
+       ret = put_timespec64(&it->it_value, &uit->it_value);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(put_itimerspec64);