summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-04-17 03:11:58 -0400
committerArnd Bergmann <arnd@arndb.de>2018-08-29 09:42:23 -0400
commit185cfaf7641e14af85635bb2750da302e32b04e3 (patch)
tree2c9be980c5bef6c442529df090e5f5170196b4ce
parenta4f7a3004630f1a0fb130ab1824942a49ce33140 (diff)
y2038: Compile utimes()/futimesat() conditionally
There are four generations of utimes() syscalls: utime(), utimes(), futimesat() and utimensat(), each one being a superset of the previous one. For y2038 support, we have to add another one, which is the same as the existing utimensat() but always passes 64-bit times_t based timespec values. There are currently 10 architectures that only use utimensat(), two that use utimes(), futimesat() and utimensat() but not utime(), and 11 architectures that have all four, and those define __ARCH_WANT_SYS_UTIME in order to get a sys_utime implementation. Since all the new architectures only want utimensat(), moving all the legacy entry points into a common __ARCH_WANT_SYS_UTIME guard simplifies the logic. Only alpha and ia64 grow a tiny bit as they now also get an unused sys_utime(), but it didn't seem worth the extra complexity of adding yet another ifdef for those. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/alpha/include/asm/unistd.h1
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/ia64/include/asm/unistd.h1
-rw-r--r--fs/utimes.c51
-rw-r--r--include/linux/syscalls.h10
5 files changed, 31 insertions, 34 deletions
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index edc090470023..9ff37aa1165f 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -14,6 +14,7 @@
14#define __ARCH_WANT_SYS_GETPGRP 14#define __ARCH_WANT_SYS_GETPGRP
15#define __ARCH_WANT_SYS_OLDUMOUNT 15#define __ARCH_WANT_SYS_OLDUMOUNT
16#define __ARCH_WANT_SYS_SIGPENDING 16#define __ARCH_WANT_SYS_SIGPENDING
17#define __ARCH_WANT_SYS_UTIME
17#define __ARCH_WANT_SYS_FORK 18#define __ARCH_WANT_SYS_FORK
18#define __ARCH_WANT_SYS_VFORK 19#define __ARCH_WANT_SYS_VFORK
19#define __ARCH_WANT_SYS_CLONE 20#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 8f1159c26f20..88ef2ce1f69a 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -26,13 +26,13 @@
26#define __ARCH_WANT_SYS_SIGPROCMASK 26#define __ARCH_WANT_SYS_SIGPROCMASK
27#define __ARCH_WANT_SYS_OLD_MMAP 27#define __ARCH_WANT_SYS_OLD_MMAP
28#define __ARCH_WANT_SYS_OLD_SELECT 28#define __ARCH_WANT_SYS_OLD_SELECT
29#define __ARCH_WANT_SYS_UTIME
29 30
30#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) 31#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
31#define __ARCH_WANT_SYS_TIME 32#define __ARCH_WANT_SYS_TIME
32#define __ARCH_WANT_SYS_IPC 33#define __ARCH_WANT_SYS_IPC
33#define __ARCH_WANT_SYS_OLDUMOUNT 34#define __ARCH_WANT_SYS_OLDUMOUNT
34#define __ARCH_WANT_SYS_ALARM 35#define __ARCH_WANT_SYS_ALARM
35#define __ARCH_WANT_SYS_UTIME
36#define __ARCH_WANT_SYS_OLD_GETRLIMIT 36#define __ARCH_WANT_SYS_OLD_GETRLIMIT
37#define __ARCH_WANT_OLD_READDIR 37#define __ARCH_WANT_OLD_READDIR
38#define __ARCH_WANT_SYS_SOCKETCALL 38#define __ARCH_WANT_SYS_SOCKETCALL
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index c5b2620c4a4c..49e34db2529c 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -29,6 +29,7 @@
29#define __IGNORE_umount2 /* umount() */ 29#define __IGNORE_umount2 /* umount() */
30 30
31#define __ARCH_WANT_NEW_STAT 31#define __ARCH_WANT_NEW_STAT
32#define __ARCH_WANT_SYS_UTIME
32 33
33#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) 34#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
34 35
diff --git a/fs/utimes.c b/fs/utimes.c
index d30f409ecc1a..2f6f08061a26 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -8,35 +8,6 @@
8#include <linux/compat.h> 8#include <linux/compat.h>
9#include <asm/unistd.h> 9#include <asm/unistd.h>
10 10
11#ifdef __ARCH_WANT_SYS_UTIME
12
13/*
14 * sys_utime() can be implemented in user-level using sys_utimes().
15 * Is this for backwards compatibility? If so, why not move it
16 * into the appropriate arch directory (for those architectures that
17 * need it).
18 */
19
20/* If times==NULL, set access and modification to current time,
21 * must be owner or have write permission.
22 * Else, update from *times, must be owner or super user.
23 */
24SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
25{
26 struct timespec64 tv[2];
27
28 if (times) {
29 if (get_user(tv[0].tv_sec, &times->actime) ||
30 get_user(tv[1].tv_sec, &times->modtime))
31 return -EFAULT;
32 tv[0].tv_nsec = 0;
33 tv[1].tv_nsec = 0;
34 }
35 return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0);
36}
37
38#endif
39
40static bool nsec_valid(long nsec) 11static bool nsec_valid(long nsec)
41{ 12{
42 if (nsec == UTIME_OMIT || nsec == UTIME_NOW) 13 if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
@@ -184,6 +155,13 @@ SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
184 return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags); 155 return do_utimes(dfd, filename, utimes ? tstimes : NULL, flags);
185} 156}
186 157
158#ifdef __ARCH_WANT_SYS_UTIME
159/*
160 * futimesat(), utimes() and utime() are older versions of utimensat()
161 * that are provided for compatibility with traditional C libraries.
162 * On modern architectures, we always use libc wrappers around
163 * utimensat() instead.
164 */
187static long do_futimesat(int dfd, const char __user *filename, 165static long do_futimesat(int dfd, const char __user *filename,
188 struct timeval __user *utimes) 166 struct timeval __user *utimes)
189{ 167{
@@ -225,6 +203,21 @@ SYSCALL_DEFINE2(utimes, char __user *, filename,
225 return do_futimesat(AT_FDCWD, filename, utimes); 203 return do_futimesat(AT_FDCWD, filename, utimes);
226} 204}
227 205
206SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
207{
208 struct timespec64 tv[2];
209
210 if (times) {
211 if (get_user(tv[0].tv_sec, &times->actime) ||
212 get_user(tv[1].tv_sec, &times->modtime))
213 return -EFAULT;
214 tv[0].tv_nsec = 0;
215 tv[1].tv_nsec = 0;
216 }
217 return do_utimes(AT_FDCWD, filename, times ? tv : NULL, 0);
218}
219#endif
220
228#ifdef CONFIG_COMPAT 221#ifdef CONFIG_COMPAT
229/* 222/*
230 * Not all architectures have sys_utime, so implement this in terms 223 * Not all architectures have sys_utime, so implement this in terms
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 420ac881a610..95e795fb0593 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -955,8 +955,6 @@ asmlinkage long sys_access(const char __user *filename, int mode);
955asmlinkage long sys_rename(const char __user *oldname, 955asmlinkage long sys_rename(const char __user *oldname,
956 const char __user *newname); 956 const char __user *newname);
957asmlinkage long sys_symlink(const char __user *old, const char __user *new); 957asmlinkage long sys_symlink(const char __user *old, const char __user *new);
958asmlinkage long sys_utimes(char __user *filename,
959 struct timeval __user *utimes);
960#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64) 958#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
961asmlinkage long sys_stat64(const char __user *filename, 959asmlinkage long sys_stat64(const char __user *filename,
962 struct stat64 __user *statbuf); 960 struct stat64 __user *statbuf);
@@ -986,14 +984,18 @@ asmlinkage long sys_alarm(unsigned int seconds);
986asmlinkage long sys_getpgrp(void); 984asmlinkage long sys_getpgrp(void);
987asmlinkage long sys_pause(void); 985asmlinkage long sys_pause(void);
988asmlinkage long sys_time(time_t __user *tloc); 986asmlinkage long sys_time(time_t __user *tloc);
987#ifdef __ARCH_WANT_SYS_UTIME
989asmlinkage long sys_utime(char __user *filename, 988asmlinkage long sys_utime(char __user *filename,
990 struct utimbuf __user *times); 989 struct utimbuf __user *times);
990asmlinkage long sys_utimes(char __user *filename,
991 struct timeval __user *utimes);
992asmlinkage long sys_futimesat(int dfd, const char __user *filename,
993 struct timeval __user *utimes);
994#endif
991asmlinkage long sys_creat(const char __user *pathname, umode_t mode); 995asmlinkage long sys_creat(const char __user *pathname, umode_t mode);
992asmlinkage long sys_getdents(unsigned int fd, 996asmlinkage long sys_getdents(unsigned int fd,
993 struct linux_dirent __user *dirent, 997 struct linux_dirent __user *dirent,
994 unsigned int count); 998 unsigned int count);
995asmlinkage long sys_futimesat(int dfd, const char __user *filename,
996 struct timeval __user *utimes);
997asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp, 999asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
998 fd_set __user *exp, struct timeval __user *tvp); 1000 fd_set __user *exp, struct timeval __user *tvp);
999asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, 1001asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,