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>
11 static bool nsec_valid(long nsec
)
13 if (nsec
== UTIME_OMIT
|| nsec
== UTIME_NOW
)
16 return nsec
>= 0 && nsec
<= 999999999;
19 int vfs_utimes(const struct path
*path
, struct timespec64
*times
)
22 struct iattr newattrs
;
23 struct inode
*inode
= path
->dentry
->d_inode
;
24 struct inode
*delegated_inode
= NULL
;
27 if (!nsec_valid(times
[0].tv_nsec
) ||
28 !nsec_valid(times
[1].tv_nsec
))
30 if (times
[0].tv_nsec
== UTIME_NOW
&&
31 times
[1].tv_nsec
== UTIME_NOW
)
35 error
= mnt_want_write(path
->mnt
);
39 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
41 if (times
[0].tv_nsec
== UTIME_OMIT
)
42 newattrs
.ia_valid
&= ~ATTR_ATIME
;
43 else if (times
[0].tv_nsec
!= UTIME_NOW
) {
44 newattrs
.ia_atime
= times
[0];
45 newattrs
.ia_valid
|= ATTR_ATIME_SET
;
48 if (times
[1].tv_nsec
== UTIME_OMIT
)
49 newattrs
.ia_valid
&= ~ATTR_MTIME
;
50 else if (times
[1].tv_nsec
!= UTIME_NOW
) {
51 newattrs
.ia_mtime
= times
[1];
52 newattrs
.ia_valid
|= ATTR_MTIME_SET
;
55 * Tell setattr_prepare(), that this is an explicit time
56 * update, even if neither ATTR_ATIME_SET nor ATTR_MTIME_SET
59 newattrs
.ia_valid
|= ATTR_TIMES_SET
;
61 newattrs
.ia_valid
|= ATTR_TOUCH
;
65 error
= notify_change(path
->dentry
, &newattrs
, &delegated_inode
);
67 if (delegated_inode
) {
68 error
= break_deleg_wait(&delegated_inode
);
73 mnt_drop_write(path
->mnt
);
78 static int do_utimes_path(int dfd
, const char __user
*filename
,
79 struct timespec64
*times
, int flags
)
82 int lookup_flags
= 0, error
;
84 if (flags
& ~(AT_SYMLINK_NOFOLLOW
| AT_EMPTY_PATH
))
87 if (!(flags
& AT_SYMLINK_NOFOLLOW
))
88 lookup_flags
|= LOOKUP_FOLLOW
;
89 if (flags
& AT_EMPTY_PATH
)
90 lookup_flags
|= LOOKUP_EMPTY
;
93 error
= user_path_at(dfd
, filename
, lookup_flags
, &path
);
97 error
= vfs_utimes(&path
, times
);
99 if (retry_estale(error
, lookup_flags
)) {
100 lookup_flags
|= LOOKUP_REVAL
;
107 static int do_utimes_fd(int fd
, struct timespec64
*times
, int flags
)
118 error
= vfs_utimes(&f
.file
->f_path
, times
);
124 * do_utimes - change times on filename or file descriptor
125 * @dfd: open file descriptor, -1 or AT_FDCWD
126 * @filename: path name or NULL
127 * @times: new times or NULL
128 * @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
130 * If filename is NULL and dfd refers to an open file, then operate on
131 * the file. Otherwise look up filename, possibly using dfd as a
134 * If times==NULL, set access and modification to current time,
135 * must be owner or have write permission.
136 * Else, update from *times, must be owner or super user.
138 long do_utimes(int dfd
, const char __user
*filename
, struct timespec64
*times
,
141 if (filename
== NULL
&& dfd
!= AT_FDCWD
)
142 return do_utimes_fd(dfd
, times
, flags
);
143 return do_utimes_path(dfd
, filename
, times
, flags
);
146 SYSCALL_DEFINE4(utimensat
, int, dfd
, const char __user
*, filename
,
147 struct __kernel_timespec __user
*, utimes
, int, flags
)
149 struct timespec64 tstimes
[2];
152 if ((get_timespec64(&tstimes
[0], &utimes
[0]) ||
153 get_timespec64(&tstimes
[1], &utimes
[1])))
156 /* Nothing to do, we must not even check the path. */
157 if (tstimes
[0].tv_nsec
== UTIME_OMIT
&&
158 tstimes
[1].tv_nsec
== UTIME_OMIT
)
162 return do_utimes(dfd
, filename
, utimes
? tstimes
: NULL
, flags
);
165 #ifdef __ARCH_WANT_SYS_UTIME
167 * futimesat(), utimes() and utime() are older versions of utimensat()
168 * that are provided for compatibility with traditional C libraries.
169 * On modern architectures, we always use libc wrappers around
170 * utimensat() instead.
172 static long do_futimesat(int dfd
, const char __user
*filename
,
173 struct __kernel_old_timeval __user
*utimes
)
175 struct __kernel_old_timeval times
[2];
176 struct timespec64 tstimes
[2];
179 if (copy_from_user(×
, utimes
, sizeof(times
)))
182 /* This test is needed to catch all invalid values. If we
183 would test only in do_utimes we would miss those invalid
184 values truncated by the multiplication with 1000. Note
185 that we also catch UTIME_{NOW,OMIT} here which are only
186 valid for utimensat. */
187 if (times
[0].tv_usec
>= 1000000 || times
[0].tv_usec
< 0 ||
188 times
[1].tv_usec
>= 1000000 || times
[1].tv_usec
< 0)
191 tstimes
[0].tv_sec
= times
[0].tv_sec
;
192 tstimes
[0].tv_nsec
= 1000 * times
[0].tv_usec
;
193 tstimes
[1].tv_sec
= times
[1].tv_sec
;
194 tstimes
[1].tv_nsec
= 1000 * times
[1].tv_usec
;
197 return do_utimes(dfd
, filename
, utimes
? tstimes
: NULL
, 0);
201 SYSCALL_DEFINE3(futimesat
, int, dfd
, const char __user
*, filename
,
202 struct __kernel_old_timeval __user
*, utimes
)
204 return do_futimesat(dfd
, filename
, utimes
);
207 SYSCALL_DEFINE2(utimes
, char __user
*, filename
,
208 struct __kernel_old_timeval __user
*, utimes
)
210 return do_futimesat(AT_FDCWD
, filename
, utimes
);
213 SYSCALL_DEFINE2(utime
, char __user
*, filename
, struct utimbuf __user
*, times
)
215 struct timespec64 tv
[2];
218 if (get_user(tv
[0].tv_sec
, ×
->actime
) ||
219 get_user(tv
[1].tv_sec
, ×
->modtime
))
224 return do_utimes(AT_FDCWD
, filename
, times
? tv
: NULL
, 0);
228 #ifdef CONFIG_COMPAT_32BIT_TIME
230 * Not all architectures have sys_utime, so implement this in terms
233 #ifdef __ARCH_WANT_SYS_UTIME32
234 SYSCALL_DEFINE2(utime32
, const char __user
*, filename
,
235 struct old_utimbuf32 __user
*, t
)
237 struct timespec64 tv
[2];
240 if (get_user(tv
[0].tv_sec
, &t
->actime
) ||
241 get_user(tv
[1].tv_sec
, &t
->modtime
))
246 return do_utimes(AT_FDCWD
, filename
, t
? tv
: NULL
, 0);
250 SYSCALL_DEFINE4(utimensat_time32
, unsigned int, dfd
, const char __user
*, filename
, struct old_timespec32 __user
*, t
, int, flags
)
252 struct timespec64 tv
[2];
255 if (get_old_timespec32(&tv
[0], &t
[0]) ||
256 get_old_timespec32(&tv
[1], &t
[1]))
259 if (tv
[0].tv_nsec
== UTIME_OMIT
&& tv
[1].tv_nsec
== UTIME_OMIT
)
262 return do_utimes(dfd
, filename
, t
? tv
: NULL
, flags
);
265 #ifdef __ARCH_WANT_SYS_UTIME32
266 static long do_compat_futimesat(unsigned int dfd
, const char __user
*filename
,
267 struct old_timeval32 __user
*t
)
269 struct timespec64 tv
[2];
272 if (get_user(tv
[0].tv_sec
, &t
[0].tv_sec
) ||
273 get_user(tv
[0].tv_nsec
, &t
[0].tv_usec
) ||
274 get_user(tv
[1].tv_sec
, &t
[1].tv_sec
) ||
275 get_user(tv
[1].tv_nsec
, &t
[1].tv_usec
))
277 if (tv
[0].tv_nsec
>= 1000000 || tv
[0].tv_nsec
< 0 ||
278 tv
[1].tv_nsec
>= 1000000 || tv
[1].tv_nsec
< 0)
280 tv
[0].tv_nsec
*= 1000;
281 tv
[1].tv_nsec
*= 1000;
283 return do_utimes(dfd
, filename
, t
? tv
: NULL
, 0);
286 SYSCALL_DEFINE3(futimesat_time32
, unsigned int, dfd
,
287 const char __user
*, filename
,
288 struct old_timeval32 __user
*, t
)
290 return do_compat_futimesat(dfd
, filename
, t
);
293 SYSCALL_DEFINE2(utimes_time32
, const char __user
*, filename
, struct old_timeval32 __user
*, t
)
295 return do_compat_futimesat(AT_FDCWD
, filename
, t
);