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