1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/file.h> 3 #include <linux/mount.h> 4 #include <linux/namei.h> 5 #include <linux/utime.h> 6 #include <linux/syscalls.h> 7 #include <linux/uaccess.h> 8 #include <linux/compat.h> 9 #include <asm/unistd.h> 10 #include <linux/filelock.h> 11 #include "internal.h" 12 13 static bool nsec_valid(long nsec) 14 { 15 if (nsec == UTIME_OMIT || nsec == UTIME_NOW) 16 return true; 17 18 return nsec >= 0 && nsec <= 999999999; 19 } 20 21 int vfs_utimes(const struct path *path, struct timespec64 *times) 22 { 23 int error; 24 struct iattr newattrs; 25 struct inode *inode = path->dentry->d_inode; 26 struct delegated_inode delegated_inode = { }; 27 28 if (times) { 29 if (!nsec_valid(times[0].tv_nsec) || 30 !nsec_valid(times[1].tv_nsec)) 31 return -EINVAL; 32 if (times[0].tv_nsec == UTIME_NOW && 33 times[1].tv_nsec == UTIME_NOW) 34 times = NULL; 35 } 36 37 error = mnt_want_write(path->mnt); 38 if (error) 39 goto out; 40 41 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 42 if (times) { 43 if (times[0].tv_nsec == UTIME_OMIT) 44 newattrs.ia_valid &= ~ATTR_ATIME; 45 else if (times[0].tv_nsec != UTIME_NOW) { 46 newattrs.ia_atime = times[0]; 47 newattrs.ia_valid |= ATTR_ATIME_SET; 48 } 49 50 if (times[1].tv_nsec == UTIME_OMIT) 51 newattrs.ia_valid &= ~ATTR_MTIME; 52 else if (times[1].tv_nsec != UTIME_NOW) { 53 newattrs.ia_mtime = times[1]; 54 newattrs.ia_valid |= ATTR_MTIME_SET; 55 } 56 /* 57 * Tell setattr_prepare(), that this is an explicit time 58 * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET 59 * were used. 60 */ 61 newattrs.ia_valid |= ATTR_TIMES_SET; 62 } else { 63 newattrs.ia_valid |= ATTR_TOUCH; 64 } 65 retry_deleg: 66 inode_lock(inode); 67 error = notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs, 68 &delegated_inode); 69 inode_unlock(inode); 70 if (is_delegated(&delegated_inode)) { 71 error = break_deleg_wait(&delegated_inode); 72 if (!error) 73 goto retry_deleg; 74 } 75 76 mnt_drop_write(path->mnt); 77 out: 78 return error; 79 } 80 EXPORT_SYMBOL_GPL(vfs_utimes); 81 82 static int do_utimes_path(int dfd, const char __user *filename, 83 struct timespec64 *times, int flags) 84 { 85 struct path path; 86 int lookup_flags = 0, error; 87 88 if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) 89 return -EINVAL; 90 91 if (!(flags & AT_SYMLINK_NOFOLLOW)) 92 lookup_flags |= LOOKUP_FOLLOW; 93 94 CLASS(filename_uflags, name)(filename, flags); 95 retry: 96 error = filename_lookup(dfd, name, lookup_flags, &path, NULL); 97 if (error) 98 return error; 99 error = vfs_utimes(&path, times); 100 path_put(&path); 101 if (retry_estale(error, lookup_flags)) { 102 lookup_flags |= LOOKUP_REVAL; 103 goto retry; 104 } 105 return error; 106 } 107 108 static int do_utimes_fd(int fd, struct timespec64 *times, int flags) 109 { 110 if (flags) 111 return -EINVAL; 112 113 CLASS(fd, f)(fd); 114 if (fd_empty(f)) 115 return -EBADF; 116 return vfs_utimes(&fd_file(f)->f_path, times); 117 } 118 119 /* 120 * do_utimes - change times on filename or file descriptor 121 * @dfd: open file descriptor, -1 or AT_FDCWD 122 * @filename: path name or NULL 123 * @times: new times or NULL 124 * @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment) 125 * 126 * If filename is NULL and dfd refers to an open file, then operate on 127 * the file. Otherwise look up filename, possibly using dfd as a 128 * starting point. 129 * 130 * If times==NULL, set access and modification to current time, 131 * must be owner or have write permission. 132 * Else, update from *times, must be owner or super user. 133 */ 134 long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, 135 int flags) 136 { 137 if (filename == NULL && dfd != AT_FDCWD) 138 return do_utimes_fd(dfd, times, flags); 139 return do_utimes_path(dfd, filename, times, flags); 140 } 141 142 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 143 struct __kernel_timespec __user *, utimes, int, flags) 144 { 145 struct timespec64 tstimes[2]; 146 147 if (utimes) { 148 if ((get_timespec64(&tstimes[0], &utimes[0]) || 149 get_timespec64(&tstimes[1], &utimes[1]))) 150 return -EFAULT; 151 152 /* Nothing to do, we must not even check the path. */ 153 if (tstimes[0].tv_nsec == UTIME_OMIT && 154 tstimes[1].tv_nsec == UTIME_OMIT) 155 return 0; 156 } 157 158 return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags); 159 } 160 161 #ifdef __ARCH_WANT_SYS_UTIME 162 /* 163 * futimesat(), utimes() and utime() are older versions of utimensat() 164 * that are provided for compatibility with traditional C libraries. 165 * On modern architectures, we always use libc wrappers around 166 * utimensat() instead. 167 */ 168 static long do_futimesat(int dfd, const char __user *filename, 169 struct __kernel_old_timeval __user *utimes) 170 { 171 struct __kernel_old_timeval times[2]; 172 struct timespec64 tstimes[2]; 173 174 if (utimes) { 175 if (copy_from_user(×, utimes, sizeof(times))) 176 return -EFAULT; 177 178 /* This test is needed to catch all invalid values. If we 179 would test only in do_utimes we would miss those invalid 180 values truncated by the multiplication with 1000. Note 181 that we also catch UTIME_{NOW,OMIT} here which are only 182 valid for utimensat. */ 183 if (times[0].tv_usec >= 1000000 || times[0].tv_usec < 0 || 184 times[1].tv_usec >= 1000000 || times[1].tv_usec < 0) 185 return -EINVAL; 186 187 tstimes[0].tv_sec = times[0].tv_sec; 188 tstimes[0].tv_nsec = 1000 * times[0].tv_usec; 189 tstimes[1].tv_sec = times[1].tv_sec; 190 tstimes[1].tv_nsec = 1000 * times[1].tv_usec; 191 } 192 193 return do_utimes(dfd, filename, utimes ? tstimes : NULL, 0); 194 } 195 196 197 SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename, 198 struct __kernel_old_timeval __user *, utimes) 199 { 200 return do_futimesat(dfd, filename, utimes); 201 } 202 203 SYSCALL_DEFINE2(utimes, char __user *, filename, 204 struct __kernel_old_timeval __user *, utimes) 205 { 206 return do_futimesat(AT_FDCWD, filename, utimes); 207 } 208 209 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 210 { 211 struct timespec64 tv[2]; 212 213 if (times) { 214 if (get_user(tv[0].tv_sec, ×->actime) || 215 get_user(tv[1].tv_sec, ×->modtime)) 216 return -EFAULT; 217 tv[0].tv_nsec = 0; 218 tv[1].tv_nsec = 0; 219 } 220 return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0); 221 } 222 #endif 223 224 #ifdef CONFIG_COMPAT_32BIT_TIME 225 /* 226 * Not all architectures have sys_utime, so implement this in terms 227 * of sys_utimes. 228 */ 229 #ifdef __ARCH_WANT_SYS_UTIME32 230 SYSCALL_DEFINE2(utime32, const char __user *, filename, 231 struct old_utimbuf32 __user *, t) 232 { 233 struct timespec64 tv[2]; 234 235 if (t) { 236 if (get_user(tv[0].tv_sec, &t->actime) || 237 get_user(tv[1].tv_sec, &t->modtime)) 238 return -EFAULT; 239 tv[0].tv_nsec = 0; 240 tv[1].tv_nsec = 0; 241 } 242 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0); 243 } 244 #endif 245 246 SYSCALL_DEFINE4(utimensat_time32, unsigned int, dfd, const char __user *, filename, struct old_timespec32 __user *, t, int, flags) 247 { 248 struct timespec64 tv[2]; 249 250 if (t) { 251 if (get_old_timespec32(&tv[0], &t[0]) || 252 get_old_timespec32(&tv[1], &t[1])) 253 return -EFAULT; 254 255 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) 256 return 0; 257 } 258 return do_utimes(dfd, filename, t ? tv : NULL, flags); 259 } 260 261 #ifdef __ARCH_WANT_SYS_UTIME32 262 static long do_compat_futimesat(unsigned int dfd, const char __user *filename, 263 struct old_timeval32 __user *t) 264 { 265 struct timespec64 tv[2]; 266 267 if (t) { 268 if (get_user(tv[0].tv_sec, &t[0].tv_sec) || 269 get_user(tv[0].tv_nsec, &t[0].tv_usec) || 270 get_user(tv[1].tv_sec, &t[1].tv_sec) || 271 get_user(tv[1].tv_nsec, &t[1].tv_usec)) 272 return -EFAULT; 273 if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 || 274 tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0) 275 return -EINVAL; 276 tv[0].tv_nsec *= 1000; 277 tv[1].tv_nsec *= 1000; 278 } 279 return do_utimes(dfd, filename, t ? tv : NULL, 0); 280 } 281 282 SYSCALL_DEFINE3(futimesat_time32, unsigned int, dfd, 283 const char __user *, filename, 284 struct old_timeval32 __user *, t) 285 { 286 return do_compat_futimesat(dfd, filename, t); 287 } 288 289 SYSCALL_DEFINE2(utimes_time32, const char __user *, filename, struct old_timeval32 __user *, t) 290 { 291 return do_compat_futimesat(AT_FDCWD, filename, t); 292 } 293 #endif 294 #endif 295