utimes: Make utimes y2038 safe

struct timespec is not y2038 safe on 32 bit machines.
Replace timespec with y2038 safe struct timespec64.

Note that the patch only changes the internals without
modifying the syscall interfaces. This will be part
of a separate series.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Deepa Dinamani and committed by
Al Viro
aaed2dd8 7ff2819e

+14 -13
+12 -11
fs/utimes.c
··· 22 */ 23 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 24 { 25 - struct timespec tv[2]; 26 27 if (times) { 28 if (get_user(tv[0].tv_sec, &times->actime) || ··· 44 return nsec >= 0 && nsec <= 999999999; 45 } 46 47 - static int utimes_common(const struct path *path, struct timespec *times) 48 { 49 int error; 50 struct iattr newattrs; ··· 115 * must be owner or have write permission. 116 * Else, update from *times, must be owner or super user. 117 */ 118 - long do_utimes(int dfd, const char __user *filename, struct timespec *times, 119 int flags) 120 { 121 int error = -EINVAL; ··· 167 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 168 struct timespec __user *, utimes, int, flags) 169 { 170 - struct timespec tstimes[2]; 171 172 if (utimes) { 173 - if (copy_from_user(&tstimes, utimes, sizeof(tstimes))) 174 return -EFAULT; 175 176 /* Nothing to do, we must not even check the path. */ ··· 187 struct timeval __user *, utimes) 188 { 189 struct timeval times[2]; 190 - struct timespec tstimes[2]; 191 192 if (utimes) { 193 if (copy_from_user(&times, utimes, sizeof(times))) ··· 225 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, 226 struct compat_utimbuf __user *, t) 227 { 228 - struct timespec tv[2]; 229 230 if (t) { 231 if (get_user(tv[0].tv_sec, &t->actime) || ··· 239 240 COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) 241 { 242 - struct timespec tv[2]; 243 244 if (t) { 245 - if (compat_get_timespec(&tv[0], &t[0]) || 246 - compat_get_timespec(&tv[1], &t[1])) 247 return -EFAULT; 248 249 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) ··· 254 255 COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) 256 { 257 - struct timespec tv[2]; 258 259 if (t) { 260 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
··· 22 */ 23 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 24 { 25 + struct timespec64 tv[2]; 26 27 if (times) { 28 if (get_user(tv[0].tv_sec, &times->actime) || ··· 44 return nsec >= 0 && nsec <= 999999999; 45 } 46 47 + static int utimes_common(const struct path *path, struct timespec64 *times) 48 { 49 int error; 50 struct iattr newattrs; ··· 115 * must be owner or have write permission. 116 * Else, update from *times, must be owner or super user. 117 */ 118 + long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, 119 int flags) 120 { 121 int error = -EINVAL; ··· 167 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 168 struct timespec __user *, utimes, int, flags) 169 { 170 + struct timespec64 tstimes[2]; 171 172 if (utimes) { 173 + if ((get_timespec64(&tstimes[0], &utimes[0]) || 174 + get_timespec64(&tstimes[1], &utimes[1]))) 175 return -EFAULT; 176 177 /* Nothing to do, we must not even check the path. */ ··· 186 struct timeval __user *, utimes) 187 { 188 struct timeval times[2]; 189 + struct timespec64 tstimes[2]; 190 191 if (utimes) { 192 if (copy_from_user(&times, utimes, sizeof(times))) ··· 224 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, 225 struct compat_utimbuf __user *, t) 226 { 227 + struct timespec64 tv[2]; 228 229 if (t) { 230 if (get_user(tv[0].tv_sec, &t->actime) || ··· 238 239 COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) 240 { 241 + struct timespec64 tv[2]; 242 243 if (t) { 244 + if (compat_get_timespec64(&tv[0], &t[0]) || 245 + compat_get_timespec64(&tv[1], &t[1])) 246 return -EFAULT; 247 248 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) ··· 253 254 COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) 255 { 256 + struct timespec64 tv[2]; 257 258 if (t) { 259 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
+1 -1
include/linux/time.h
··· 178 struct itimerval *ovalue); 179 extern int do_getitimer(int which, struct itimerval *value); 180 181 - extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); 182 183 /* 184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
··· 178 struct itimerval *ovalue); 179 extern int do_getitimer(int which, struct itimerval *value); 180 181 + extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags); 182 183 /* 184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
+1 -1
init/initramfs.c
··· 110 111 static long __init do_utime(char *filename, time_t mtime) 112 { 113 - struct timespec t[2]; 114 115 t[0].tv_sec = mtime; 116 t[0].tv_nsec = 0;
··· 110 111 static long __init do_utime(char *filename, time_t mtime) 112 { 113 + struct timespec64 t[2]; 114 115 t[0].tv_sec = mtime; 116 t[0].tv_nsec = 0;