summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepa Dinamani <deepa.kernel@gmail.com>2017-08-02 22:51:15 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-09-03 20:24:30 -0400
commitaaed2dd8a31359e5767ee099ecbb078d55be4d29 (patch)
treef04a2e3db658c12cabae3dfd4449d8199dc0fc19
parent7ff2819e8dd5b528887dfbe4ff395f5d2142edff (diff)
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>
-rw-r--r--fs/utimes.c23
-rw-r--r--include/linux/time.h2
-rw-r--r--init/initramfs.c2
3 files changed, 14 insertions, 13 deletions
diff --git a/fs/utimes.c b/fs/utimes.c
index 6571d8c848a0..51edb9f9507c 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -22,7 +22,7 @@
22 */ 22 */
23SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 23SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
24{ 24{
25 struct timespec tv[2]; 25 struct timespec64 tv[2];
26 26
27 if (times) { 27 if (times) {
28 if (get_user(tv[0].tv_sec, &times->actime) || 28 if (get_user(tv[0].tv_sec, &times->actime) ||
@@ -44,7 +44,7 @@ static bool nsec_valid(long nsec)
44 return nsec >= 0 && nsec <= 999999999; 44 return nsec >= 0 && nsec <= 999999999;
45} 45}
46 46
47static int utimes_common(const struct path *path, struct timespec *times) 47static int utimes_common(const struct path *path, struct timespec64 *times)
48{ 48{
49 int error; 49 int error;
50 struct iattr newattrs; 50 struct iattr newattrs;
@@ -115,7 +115,7 @@ out:
115 * must be owner or have write permission. 115 * must be owner or have write permission.
116 * Else, update from *times, must be owner or super user. 116 * Else, update from *times, must be owner or super user.
117 */ 117 */
118long do_utimes(int dfd, const char __user *filename, struct timespec *times, 118long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
119 int flags) 119 int flags)
120{ 120{
121 int error = -EINVAL; 121 int error = -EINVAL;
@@ -167,10 +167,11 @@ out:
167SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 167SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
168 struct timespec __user *, utimes, int, flags) 168 struct timespec __user *, utimes, int, flags)
169{ 169{
170 struct timespec tstimes[2]; 170 struct timespec64 tstimes[2];
171 171
172 if (utimes) { 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 return -EFAULT; 175 return -EFAULT;
175 176
176 /* Nothing to do, we must not even check the path. */ 177 /* Nothing to do, we must not even check the path. */
@@ -186,7 +187,7 @@ SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
186 struct timeval __user *, utimes) 187 struct timeval __user *, utimes)
187{ 188{
188 struct timeval times[2]; 189 struct timeval times[2];
189 struct timespec tstimes[2]; 190 struct timespec64 tstimes[2];
190 191
191 if (utimes) { 192 if (utimes) {
192 if (copy_from_user(&times, utimes, sizeof(times))) 193 if (copy_from_user(&times, utimes, sizeof(times)))
@@ -224,7 +225,7 @@ SYSCALL_DEFINE2(utimes, char __user *, filename,
224COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, 225COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
225 struct compat_utimbuf __user *, t) 226 struct compat_utimbuf __user *, t)
226{ 227{
227 struct timespec tv[2]; 228 struct timespec64 tv[2];
228 229
229 if (t) { 230 if (t) {
230 if (get_user(tv[0].tv_sec, &t->actime) || 231 if (get_user(tv[0].tv_sec, &t->actime) ||
@@ -238,11 +239,11 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
238 239
239COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) 240COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
240{ 241{
241 struct timespec tv[2]; 242 struct timespec64 tv[2];
242 243
243 if (t) { 244 if (t) {
244 if (compat_get_timespec(&tv[0], &t[0]) || 245 if (compat_get_timespec64(&tv[0], &t[0]) ||
245 compat_get_timespec(&tv[1], &t[1])) 246 compat_get_timespec64(&tv[1], &t[1]))
246 return -EFAULT; 247 return -EFAULT;
247 248
248 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) 249 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
@@ -253,7 +254,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena
253 254
254COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) 255COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
255{ 256{
256 struct timespec tv[2]; 257 struct timespec64 tv[2];
257 258
258 if (t) { 259 if (t) {
259 if (get_user(tv[0].tv_sec, &t[0].tv_sec) || 260 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
diff --git a/include/linux/time.h b/include/linux/time.h
index 4abb32d4c6b8..3d0cd017f0d7 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -178,7 +178,7 @@ extern int do_setitimer(int which, struct itimerval *value,
178 struct itimerval *ovalue); 178 struct itimerval *ovalue);
179extern int do_getitimer(int which, struct itimerval *value); 179extern int do_getitimer(int which, struct itimerval *value);
180 180
181extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); 181extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags);
182 182
183/* 183/*
184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so 184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
diff --git a/init/initramfs.c b/init/initramfs.c
index 8a532050043f..e64bf7b4c1ca 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -110,7 +110,7 @@ static void __init free_hash(void)
110 110
111static long __init do_utime(char *filename, time_t mtime) 111static long __init do_utime(char *filename, time_t mtime)
112{ 112{
113 struct timespec t[2]; 113 struct timespec64 t[2];
114 114
115 t[0].tv_sec = mtime; 115 t[0].tv_sec = mtime;
116 t[0].tv_nsec = 0; 116 t[0].tv_nsec = 0;