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