These are new helper functions that convert between a user compat_timespec and a kernel timespec64 structure.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- include/linux/compat_time.h | 2 ++ kernel/compat.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h index 84a999be3856..dada7bd49f58 100644 --- a/include/linux/compat_time.h +++ b/include/linux/compat_time.h @@ -118,6 +118,8 @@ extern int compat_get_timespec(struct timespec *, const void __user *); extern int compat_put_timespec(const struct timespec *, void __user *); 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);
/* * This function convert a timespec if necessary and returns a *user diff --git a/kernel/compat.c b/kernel/compat.c index c3596ce64ac4..ad428b433d02 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -157,6 +157,20 @@ static int __compat_put_timespec(const struct timespec *ts, struct compat_timesp __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; }
+static int __compat_get_timespec64(struct timespec64 *ts, const struct compat_timespec __user *cts) +{ + return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || + __get_user(ts->tv_sec, &cts->tv_sec) || + __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; +} + +static int __compat_put_timespec64(const struct timespec64 *ts, struct compat_timespec __user *cts) +{ + return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || + __put_user(ts->tv_sec, &cts->tv_sec) || + __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; +} + int compat_get_timeval(struct timeval *tv, const void __user *utv) { if (COMPAT_USE_64BIT_TIME) @@ -193,6 +207,24 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts) } EXPORT_SYMBOL_GPL(compat_put_timespec);
+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); + #ifdef CONFIG_COMPAT int compat_convert_timespec(struct timespec __user **kts, const void __user *cts)