0001
0002 #include <linux/file.h>
0003 #include <linux/mount.h>
0004 #include <linux/namei.h>
0005 #include <linux/utime.h>
0006 #include <linux/syscalls.h>
0007 #include <linux/uaccess.h>
0008 #include <linux/compat.h>
0009 #include <asm/unistd.h>
0010
0011 static bool nsec_valid(long nsec)
0012 {
0013 if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
0014 return true;
0015
0016 return nsec >= 0 && nsec <= 999999999;
0017 }
0018
0019 int vfs_utimes(const struct path *path, struct timespec64 *times)
0020 {
0021 int error;
0022 struct iattr newattrs;
0023 struct inode *inode = path->dentry->d_inode;
0024 struct inode *delegated_inode = NULL;
0025
0026 if (times) {
0027 if (!nsec_valid(times[0].tv_nsec) ||
0028 !nsec_valid(times[1].tv_nsec))
0029 return -EINVAL;
0030 if (times[0].tv_nsec == UTIME_NOW &&
0031 times[1].tv_nsec == UTIME_NOW)
0032 times = NULL;
0033 }
0034
0035 error = mnt_want_write(path->mnt);
0036 if (error)
0037 goto out;
0038
0039 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
0040 if (times) {
0041 if (times[0].tv_nsec == UTIME_OMIT)
0042 newattrs.ia_valid &= ~ATTR_ATIME;
0043 else if (times[0].tv_nsec != UTIME_NOW) {
0044 newattrs.ia_atime = times[0];
0045 newattrs.ia_valid |= ATTR_ATIME_SET;
0046 }
0047
0048 if (times[1].tv_nsec == UTIME_OMIT)
0049 newattrs.ia_valid &= ~ATTR_MTIME;
0050 else if (times[1].tv_nsec != UTIME_NOW) {
0051 newattrs.ia_mtime = times[1];
0052 newattrs.ia_valid |= ATTR_MTIME_SET;
0053 }
0054
0055
0056
0057
0058
0059 newattrs.ia_valid |= ATTR_TIMES_SET;
0060 } else {
0061 newattrs.ia_valid |= ATTR_TOUCH;
0062 }
0063 retry_deleg:
0064 inode_lock(inode);
0065 error = notify_change(mnt_user_ns(path->mnt), path->dentry, &newattrs,
0066 &delegated_inode);
0067 inode_unlock(inode);
0068 if (delegated_inode) {
0069 error = break_deleg_wait(&delegated_inode);
0070 if (!error)
0071 goto retry_deleg;
0072 }
0073
0074 mnt_drop_write(path->mnt);
0075 out:
0076 return error;
0077 }
0078
0079 static int do_utimes_path(int dfd, const char __user *filename,
0080 struct timespec64 *times, int flags)
0081 {
0082 struct path path;
0083 int lookup_flags = 0, error;
0084
0085 if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH))
0086 return -EINVAL;
0087
0088 if (!(flags & AT_SYMLINK_NOFOLLOW))
0089 lookup_flags |= LOOKUP_FOLLOW;
0090 if (flags & AT_EMPTY_PATH)
0091 lookup_flags |= LOOKUP_EMPTY;
0092
0093 retry:
0094 error = user_path_at(dfd, filename, lookup_flags, &path);
0095 if (error)
0096 return error;
0097
0098 error = vfs_utimes(&path, times);
0099 path_put(&path);
0100 if (retry_estale(error, lookup_flags)) {
0101 lookup_flags |= LOOKUP_REVAL;
0102 goto retry;
0103 }
0104
0105 return error;
0106 }
0107
0108 static int do_utimes_fd(int fd, struct timespec64 *times, int flags)
0109 {
0110 struct fd f;
0111 int error;
0112
0113 if (flags)
0114 return -EINVAL;
0115
0116 f = fdget(fd);
0117 if (!f.file)
0118 return -EBADF;
0119 error = vfs_utimes(&f.file->f_path, times);
0120 fdput(f);
0121 return error;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
0140 int flags)
0141 {
0142 if (filename == NULL && dfd != AT_FDCWD)
0143 return do_utimes_fd(dfd, times, flags);
0144 return do_utimes_path(dfd, filename, times, flags);
0145 }
0146
0147 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
0148 struct __kernel_timespec __user *, utimes, int, flags)
0149 {
0150 struct timespec64 tstimes[2];
0151
0152 if (utimes) {
0153 if ((get_timespec64(&tstimes[0], &utimes[0]) ||
0154 get_timespec64(&tstimes[1], &utimes[1])))
0155 return -EFAULT;
0156
0157
0158 if (tstimes[0].tv_nsec == UTIME_OMIT &&
0159 tstimes[1].tv_nsec == UTIME_OMIT)
0160 return 0;
0161 }
0162
0163 return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags);
0164 }
0165
0166 #ifdef __ARCH_WANT_SYS_UTIME
0167
0168
0169
0170
0171
0172
0173 static long do_futimesat(int dfd, const char __user *filename,
0174 struct __kernel_old_timeval __user *utimes)
0175 {
0176 struct __kernel_old_timeval times[2];
0177 struct timespec64 tstimes[2];
0178
0179 if (utimes) {
0180 if (copy_from_user(×, utimes, sizeof(times)))
0181 return -EFAULT;
0182
0183
0184
0185
0186
0187
0188 if (times[0].tv_usec >= 1000000 || times[0].tv_usec < 0 ||
0189 times[1].tv_usec >= 1000000 || times[1].tv_usec < 0)
0190 return -EINVAL;
0191
0192 tstimes[0].tv_sec = times[0].tv_sec;
0193 tstimes[0].tv_nsec = 1000 * times[0].tv_usec;
0194 tstimes[1].tv_sec = times[1].tv_sec;
0195 tstimes[1].tv_nsec = 1000 * times[1].tv_usec;
0196 }
0197
0198 return do_utimes(dfd, filename, utimes ? tstimes : NULL, 0);
0199 }
0200
0201
0202 SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
0203 struct __kernel_old_timeval __user *, utimes)
0204 {
0205 return do_futimesat(dfd, filename, utimes);
0206 }
0207
0208 SYSCALL_DEFINE2(utimes, char __user *, filename,
0209 struct __kernel_old_timeval __user *, utimes)
0210 {
0211 return do_futimesat(AT_FDCWD, filename, utimes);
0212 }
0213
0214 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
0215 {
0216 struct timespec64 tv[2];
0217
0218 if (times) {
0219 if (get_user(tv[0].tv_sec, ×->actime) ||
0220 get_user(tv[1].tv_sec, ×->modtime))
0221 return -EFAULT;
0222 tv[0].tv_nsec = 0;
0223 tv[1].tv_nsec = 0;
0224 }
0225 return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0);
0226 }
0227 #endif
0228
0229 #ifdef CONFIG_COMPAT_32BIT_TIME
0230
0231
0232
0233
0234 #ifdef __ARCH_WANT_SYS_UTIME32
0235 SYSCALL_DEFINE2(utime32, const char __user *, filename,
0236 struct old_utimbuf32 __user *, t)
0237 {
0238 struct timespec64 tv[2];
0239
0240 if (t) {
0241 if (get_user(tv[0].tv_sec, &t->actime) ||
0242 get_user(tv[1].tv_sec, &t->modtime))
0243 return -EFAULT;
0244 tv[0].tv_nsec = 0;
0245 tv[1].tv_nsec = 0;
0246 }
0247 return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
0248 }
0249 #endif
0250
0251 SYSCALL_DEFINE4(utimensat_time32, unsigned int, dfd, const char __user *, filename, struct old_timespec32 __user *, t, int, flags)
0252 {
0253 struct timespec64 tv[2];
0254
0255 if (t) {
0256 if (get_old_timespec32(&tv[0], &t[0]) ||
0257 get_old_timespec32(&tv[1], &t[1]))
0258 return -EFAULT;
0259
0260 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
0261 return 0;
0262 }
0263 return do_utimes(dfd, filename, t ? tv : NULL, flags);
0264 }
0265
0266 #ifdef __ARCH_WANT_SYS_UTIME32
0267 static long do_compat_futimesat(unsigned int dfd, const char __user *filename,
0268 struct old_timeval32 __user *t)
0269 {
0270 struct timespec64 tv[2];
0271
0272 if (t) {
0273 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
0274 get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
0275 get_user(tv[1].tv_sec, &t[1].tv_sec) ||
0276 get_user(tv[1].tv_nsec, &t[1].tv_usec))
0277 return -EFAULT;
0278 if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
0279 tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
0280 return -EINVAL;
0281 tv[0].tv_nsec *= 1000;
0282 tv[1].tv_nsec *= 1000;
0283 }
0284 return do_utimes(dfd, filename, t ? tv : NULL, 0);
0285 }
0286
0287 SYSCALL_DEFINE3(futimesat_time32, unsigned int, dfd,
0288 const char __user *, filename,
0289 struct old_timeval32 __user *, t)
0290 {
0291 return do_compat_futimesat(dfd, filename, t);
0292 }
0293
0294 SYSCALL_DEFINE2(utimes_time32, const char __user *, filename, struct old_timeval32 __user *, t)
0295 {
0296 return do_compat_futimesat(AT_FDCWD, filename, t);
0297 }
0298 #endif
0299 #endif