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