linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/19] converting system calls to 64-bit time_t, part 1
@ 2015-05-06 16:30 Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 01/19] compat: remove compat_printk Arnd Bergmann
                   ` (19 more replies)
  0 siblings, 20 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This is my second draft of how we could modify the system call interface
in Linux to support user space with 64-bit time_t in addition to the
existing 32-bit time_t based interfaces. In order to avoid spamming people
too much, I've picked the first half of the patches only now, and left
some of the more complex ones for later.

If you are interested in the big picture, see
http://git.kernel.org/cgit/linux/kernel/git/arnd/playground.git/log/?h=y2038-syscalls
with currently 42 patches. That number may go up a bit over time, but
only because I plan to split some of the patches into smaller chunks
for review purposes, as opposed to adding more system calls.

As part 1 of the series only switches over half the system calls,
I've left out the bits that changes the ARM and x86 architectures.
There are 24 additional architectures that need to moved over to
the new system calls once the basic patches get merged.

The main part I'm not sure about is how the header files should be
structured in order to make it easy for every libc implementation
to pick out the right definitions of the data structures I had to
modify. Hopefully, people on libc-alpha can help me out here.

The overall approach I have taken here is as follows:

* Since 64-bit architectures already support two versions of each system
  call that passes a time value in order to run 32-bit user space,
  I'm not adding new system calls for the most part, but instead make
  32-bit architectures use the same compat handlers that 64-bit
  architectures already use.

* The existing syscall numbers are modified to point to the compat_sys_*
  functions, and new numbers are assigned to point to the existing handlers
  that now deal with 64-bit time_t based structures

* This series does not touch any ioctl implementation, but should be
  otherwise complete regarding the system calls. We are still trying
  to find out exactly which ioctls are affected and have not come
  up with a complete list at this point. It's probably a good idea
  though to do at least the essential ioctls before merging the series,
  so we can have a better understanding of how it will be done in the
  end.

* Each data structure we need to modify gets a new definition with a
  __kernel_ prefix, e.g. struct __kernel_timespec to replace struct
  timespec. This keeps the new structures out of the user libc
  namespace, but still allows the structure to be integrated into
  other data structures, e.g. for ioctl.

* There is no #ifdef in the UAPI headers at this point that would
  check for the kind of user space that is in use. Unfortunately,
  I believe we will need to add that in order to do some of the
  particularly tricky ioctls later.

* At first, all system call implementations are modified, but this
  is done in a way that is not supposed to have any ABI-visible
  effect on existing architectures.

* After all system calls are converted, we can change one architecture
  at a time to select ARCH_HAS_COMPAT_TIME, and modify its system
  call table accordingly. In this version, I do it for ARM32, x86-32,
  and x86-64 for demonstration purposes.

* A follow-up series changes over all other architectures.

* The last patch in the series changes the CONFIG_COMPAT_TIME
  Kconfig symbol to be user visible. Disabling this symbol will
  get you a kernel that intentionally breaks support for old tasks
  in order to provide an interface that will survive 2038.
  This is meant mostly as a debugging help for now, to let people
  build a y2038 safe distro, but at some point in the 2030s, we
  should remove that option and all the compat handling.

Arnd Bergmann (19):
  compat: remove compat_printk
  initramfs: use vfs_stat/lstat directly
  y2038: introduce linux/compat_time.h header
  y2038: introduce CONFIG_COMPAT_TIME
  y2038: make linux/compat_time.h usable on 32-bit
  y2038: compile compat time code even when CONFIG_COMPAT is not set
  y2038: add compat_sys_rt_sigtimedwait variants
  y2038: introduce struct __kernel_timespec
  y2038: introduce struct __kernel_stat
  y2038: use __kernel_stat for sys_newstat syscalls
  y2038: introduce and use struct __kernel_rusage
  y2038: add compat_{get,put}_timespec64
  y2038: add compat handling for sys_semtimedop
  y2038: use __kernel_timespec for sys_mq_timed{send,receive}
  y2038: introduce timespec64_to_jiffies
  y2038: use __kernel_timespec in sys_rt_sigtimedwait
  y2038: use __kernel_timespec in sys_futex
  y2038: introduce jiffies_to_timespec64
  y2038: use __kernel_timespec in sys_sched_rr_get_interval

 arch/Kconfig                           |  11 ++
 arch/alpha/include/uapi/asm/stat.h     |   4 +
 arch/alpha/kernel/osf_sys.c            |   4 +-
 arch/arm/include/uapi/asm/stat.h       |   2 +
 arch/arm64/include/asm/compat.h        |  11 --
 arch/avr32/include/uapi/asm/stat.h     |   2 +
 arch/blackfin/include/uapi/asm/stat.h  |   2 +
 arch/cris/include/uapi/asm/stat.h      |   2 +
 arch/frv/include/uapi/asm/stat.h       |   2 +
 arch/ia64/include/uapi/asm/stat.h      |   4 +
 arch/m32r/include/uapi/asm/stat.h      |   1 +
 arch/m68k/include/uapi/asm/stat.h      |   2 +
 arch/mips/include/asm/compat.h         |  11 --
 arch/mips/include/uapi/asm/stat.h      |   1 +
 arch/mn10300/include/uapi/asm/stat.h   |   2 +
 arch/parisc/include/asm/compat.h       |  11 --
 arch/parisc/include/uapi/asm/stat.h    |   1 +
 arch/powerpc/include/asm/compat.h      |  11 --
 arch/powerpc/include/uapi/asm/stat.h   |  25 +++
 arch/s390/include/asm/compat.h         |  11 --
 arch/s390/include/uapi/asm/stat.h      |  24 +++
 arch/sh/include/uapi/asm/stat.h        |   2 +
 arch/sparc/include/asm/compat.h        |  11 --
 arch/sparc/include/uapi/asm/stat.h     |  28 ++++
 arch/tile/include/asm/compat.h         |  11 --
 arch/x86/include/asm/compat.h          |  12 +-
 arch/x86/include/asm/ftrace.h          |   2 +-
 arch/x86/include/asm/sys_ia32.h        |   2 +-
 arch/x86/include/uapi/asm/stat.h       |  49 ++++--
 arch/x86/kernel/cpu/perf_event.c       |   2 +-
 arch/xtensa/include/uapi/asm/stat.h    |   2 +
 fs/Makefile                            |   1 +
 fs/compat.c                            |  26 ++-
 fs/stat.c                              |  12 +-
 include/linux/audit.h                  |   4 +-
 include/linux/compat.h                 | 232 +--------------------------
 include/linux/compat_time.h            | 285 +++++++++++++++++++++++++++++++++
 include/linux/jiffies.h                |  23 ++-
 include/linux/resource.h               |   8 +-
 include/linux/signal.h                 |   3 +-
 include/linux/stat.h                   |   3 +
 include/linux/syscalls.h               |  32 ++--
 include/linux/thread_info.h            |   2 +-
 include/linux/time64.h                 |  17 +-
 include/uapi/asm-generic/kernel_stat.h |  36 +++++
 include/uapi/asm-generic/stat.h        |  12 +-
 include/uapi/linux/resource.h          |  32 ++++
 include/uapi/linux/time.h              |  17 ++
 init/do_mounts.h                       |  22 +--
 init/initramfs.c                       |  12 +-
 ipc/compat.c                           |  10 --
 ipc/mqueue.c                           |  16 +-
 ipc/sem.c                              |  60 +++++--
 ipc/syscall.c                          |   7 +
 kernel/Makefile                        |   1 +
 kernel/audit.h                         |   2 +-
 kernel/auditsc.c                       |  14 +-
 kernel/compat.c                        | 184 ++++++++++++++++++---
 kernel/exit.c                          |   6 +-
 kernel/futex.c                         |  10 +-
 kernel/sched/core.c                    |  35 +++-
 kernel/signal.c                        |  13 +-
 kernel/sys.c                           |  23 +--
 kernel/sysctl.c                        |  10 --
 kernel/time/time.c                     |  45 ++++--
 65 files changed, 950 insertions(+), 530 deletions(-)
 create mode 100644 include/linux/compat_time.h
 create mode 100644 include/uapi/asm-generic/kernel_stat.h

-- 
2.1.0.rc2


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 01/19] compat: remove compat_printk
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 02/19] initramfs: use vfs_stat/lstat directly Arnd Bergmann
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

After 7e8e385aaf6e ("x86/compat: Remove sys32_vm86_warning"), this
function has become unused, so we can remove it as well.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 fs/compat.c            | 14 --------------
 include/linux/compat.h |  1 -
 kernel/sysctl.c        | 10 ----------
 3 files changed, 25 deletions(-)

diff --git a/fs/compat.c b/fs/compat.c
index 6fd272d455e4..7d78cde20fc3 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -54,20 +54,6 @@
 #include <asm/ioctls.h>
 #include "internal.h"
 
-int compat_log = 1;
-
-int compat_printk(const char *fmt, ...)
-{
-	va_list ap;
-	int ret;
-	if (!compat_log)
-		return 0;
-	va_start(ap, fmt);
-	ret = vprintk(fmt, ap);
-	va_end(ap);
-	return ret;
-}
-
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
diff --git a/include/linux/compat.h b/include/linux/compat.h
index ab25814690bc..d533d06146a8 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -424,7 +424,6 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
 
 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
 
-extern int compat_printk(const char *fmt, ...);
 extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat);
 extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set);
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 2082b1a88fb9..4020ade0ce4d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -105,7 +105,6 @@ extern unsigned int core_pipe_limit;
 extern int pid_max;
 extern int pid_max_min, pid_max_max;
 extern int percpu_pagelist_fraction;
-extern int compat_log;
 extern int latencytop_enabled;
 extern int sysctl_nr_open_min, sysctl_nr_open_max;
 #ifndef CONFIG_MMU
@@ -1043,15 +1042,6 @@ static struct ctl_table kern_table[] = {
 		.extra1		= &neg_one,
 	},
 #endif
-#ifdef CONFIG_COMPAT
-	{
-		.procname	= "compat-log",
-		.data		= &compat_log,
-		.maxlen		= sizeof (int),
-	 	.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-#endif
 #ifdef CONFIG_RT_MUTEXES
 	{
 		.procname	= "max_lock_depth",
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 02/19] initramfs: use vfs_stat/lstat directly
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 01/19] compat: remove compat_printk Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 03/19] y2038: introduce linux/compat_time.h header Arnd Bergmann
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

sys_newlstat is a system call implementation that is meant for user
space, and that copies kernel-internal data structure to the user
format, which is not needed for in-kernel users.

Further, as we rearrange the system call implementation so we can
extend it with 64-bit time_t, the prototype for sys_newlstat changes.

This changes the initramfs code to use vfs_lstat directly, to get
it out of the way of the time_t changes, and make it slightly more
efficient in the process. Along the same lines we also replace
sys_stat and sys_stat64 with vfs_stat.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 init/do_mounts.h | 22 ++++------------------
 init/initramfs.c | 12 ++++++------
 2 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/init/do_mounts.h b/init/do_mounts.h
index f5b978a9bb92..74e75bb20fe3 100644
--- a/init/do_mounts.h
+++ b/init/do_mounts.h
@@ -19,29 +19,15 @@ static inline int create_dev(char *name, dev_t dev)
 	return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
 }
 
-#if BITS_PER_LONG == 32
 static inline u32 bstat(char *name)
 {
-	struct stat64 stat;
-	if (sys_stat64(name, &stat) != 0)
+	struct kstat stat;
+	if (vfs_stat(name, &stat) != 0)
 		return 0;
-	if (!S_ISBLK(stat.st_mode))
+	if (!S_ISBLK(stat.mode))
 		return 0;
-	if (stat.st_rdev != (u32)stat.st_rdev)
-		return 0;
-	return stat.st_rdev;
-}
-#else
-static inline u32 bstat(char *name)
-{
-	struct stat stat;
-	if (sys_newstat(name, &stat) != 0)
-		return 0;
-	if (!S_ISBLK(stat.st_mode))
-		return 0;
-	return stat.st_rdev;
+	return stat.rdev;
 }
-#endif
 
 #ifdef CONFIG_BLK_DEV_RAM
 
diff --git a/init/initramfs.c b/init/initramfs.c
index ad1bd7787bbb..10c808e97023 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -311,10 +311,10 @@ static int __init maybe_link(void)
 
 static void __init clean_path(char *path, umode_t fmode)
 {
-	struct stat st;
+	struct kstat st;
 
-	if (!sys_newlstat(path, &st) && (st.st_mode ^ fmode) & S_IFMT) {
-		if (S_ISDIR(st.st_mode))
+	if (!vfs_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
+		if (S_ISDIR(st.mode))
 			sys_rmdir(path);
 		else
 			sys_unlink(path);
@@ -580,13 +580,13 @@ static void __init clean_rootfs(void)
 	num = sys_getdents64(fd, dirp, BUF_SIZE);
 	while (num > 0) {
 		while (num > 0) {
-			struct stat st;
+			struct kstat st;
 			int ret;
 
-			ret = sys_newlstat(dirp->d_name, &st);
+			ret = vfs_lstat(dirp->d_name, &st);
 			WARN_ON_ONCE(ret);
 			if (!ret) {
-				if (S_ISDIR(st.st_mode))
+				if (S_ISDIR(st.mode))
 					sys_rmdir(dirp->d_name);
 				else
 					sys_unlink(dirp->d_name);
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 03/19] y2038: introduce linux/compat_time.h header
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 01/19] compat: remove compat_printk Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 02/19] initramfs: use vfs_stat/lstat directly Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 04/19] y2038: introduce CONFIG_COMPAT_TIME Arnd Bergmann
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

We want to reuse all the compat syscall handling for native syscalls
on 32-bit architectures when dealing with 32-bit time_t types.

This moves all time-related system call declarations from
include/linux/compat.h to include/linux/compat_time.h, along
with the associated data structures and typedefs.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm64/include/asm/compat.h   |  11 --
 arch/mips/include/asm/compat.h    |  11 --
 arch/parisc/include/asm/compat.h  |  11 --
 arch/powerpc/include/asm/compat.h |  11 --
 arch/s390/include/asm/compat.h    |  11 --
 arch/sparc/include/asm/compat.h   |  11 --
 arch/tile/include/asm/compat.h    |  11 --
 arch/x86/include/asm/compat.h     |  12 +-
 arch/x86/include/asm/ftrace.h     |   2 +-
 arch/x86/include/asm/sys_ia32.h   |   2 +-
 arch/x86/kernel/cpu/perf_event.c  |   2 +-
 include/linux/compat.h            | 225 +--------------------------------
 include/linux/compat_time.h       | 255 ++++++++++++++++++++++++++++++++++++++
 13 files changed, 262 insertions(+), 313 deletions(-)
 create mode 100644 include/linux/compat_time.h

diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 7fbed6919b54..4d0786a73a93 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -34,7 +34,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		__compat_uid_t;
@@ -66,16 +65,6 @@ typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
 typedef u32		compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 #ifdef __AARCH64EB__
 	short		st_dev;
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index c4bd54a7f5ce..6495b37a6fbc 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -13,7 +13,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_suseconds_t;
 
@@ -45,16 +44,6 @@ typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
 typedef u32		compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t	st_dev;
 	s32		st_pad1[3];
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 94710cfc1ce8..cc20c7b203f4 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -12,7 +12,6 @@
 
 typedef u32	compat_size_t;
 typedef s32	compat_ssize_t;
-typedef s32	compat_time_t;
 typedef s32	compat_clock_t;
 typedef s32	compat_pid_t;
 typedef u32	__compat_uid_t;
@@ -39,16 +38,6 @@ typedef u32	compat_ulong_t;
 typedef u64	compat_u64;
 typedef u32	compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t		tv_sec;
-	s32			tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t		tv_sec;
-	s32			tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t		st_dev;	/* dev_t is 32 bits on parisc */
 	compat_ino_t		st_ino;	/* 32 bits */
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index b142b8e0ed9e..4f8901448eba 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -16,7 +16,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u32		__compat_uid_t;
@@ -44,16 +43,6 @@ typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
 typedef u32		compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t	st_dev;
 	compat_ino_t	st_ino;
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index d350ed9d0fbb..91398bb0695c 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -50,7 +50,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		__compat_uid_t;
@@ -94,16 +93,6 @@ typedef struct {
 	u32 gprs_high[NUM_GPRS];
 } s390_compat_regs_high;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t	st_dev;
 	u16		__pad1;
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 830502fe62b4..c7e71a6d7232 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -10,7 +10,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		__compat_uid_t;
@@ -38,16 +37,6 @@ typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
 typedef u32		compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t	st_dev;
 	compat_ino_t	st_ino;
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index c14e36f008c8..c3a326c9ae75 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -29,7 +29,6 @@ typedef u32		compat_ulong_t;
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
 typedef s32		compat_off_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef u32		compat_ino_t;
 typedef u32		compat_caddr_t;
@@ -59,16 +58,6 @@ typedef unsigned long compat_elf_greg_t;
 #define COMPAT_ELF_NGREG (sizeof(struct pt_regs) / sizeof(compat_elf_greg_t))
 typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 #define compat_stat stat
 #define compat_statfs statfs
 
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index acdee09228b3..b8ce4e15b511 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -15,7 +15,6 @@
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		__compat_uid_t;
@@ -43,16 +42,6 @@ typedef u32		compat_ulong_t;
 typedef u64 __attribute__((aligned(4))) compat_u64;
 typedef u32		compat_uptr_t;
 
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
 struct compat_stat {
 	compat_dev_t	st_dev;
 	u16		__pad1;
@@ -270,6 +259,7 @@ typedef struct user_regs_struct compat_elf_gregset_t;
   do { *(int *) (((void *) &((S)->pr_reg)) + PR_REG_SIZE(0)) = (V); } \
   while (0)
 
+#undef COMPAT_USE_64BIT_TIME
 #define COMPAT_USE_64BIT_TIME \
 	(!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT))
 #else
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index f45acad3c4b6..2c2a23cb716c 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -45,7 +45,7 @@ int ftrace_int3_handler(struct pt_regs *regs);
 #if !defined(__ASSEMBLY__) && !defined(COMPILE_OFFSETS)
 
 #if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_IA32_EMULATION)
-#include <asm/compat.h>
+#include <linux/compat.h>
 
 /*
  * Because ia32 syscalls do not map to x86_64 syscall numbers
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 82c34ee25a65..8527b26ad36f 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -16,7 +16,7 @@
 #include <linux/linkage.h>
 #include <linux/types.h>
 #include <linux/signal.h>
-#include <asm/compat.h>
+#include <linux/compat.h>
 #include <asm/ia32.h>
 
 /* ia32/sys_ia32.c */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 87848ebe2bb7..6649e07bfe66 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -2134,7 +2134,7 @@ static unsigned long get_segment_base(unsigned int segment)
 
 #ifdef CONFIG_COMPAT
 
-#include <asm/compat.h>
+#include <linux/compat.h>
 
 static inline int
 perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
diff --git a/include/linux/compat.h b/include/linux/compat.h
index d533d06146a8..41b0dae6203b 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -15,15 +15,12 @@
 #include <linux/fs.h>
 #include <linux/aio_abi.h>	/* for aio_context_t */
 #include <linux/unistd.h>
+#include <linux/compat_time.h>
 
 #include <asm/compat.h>
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 
-#ifndef COMPAT_USE_64BIT_TIME
-#define COMPAT_USE_64BIT_TIME 0
-#endif
-
 #ifndef __SC_DELOUSE
 #define __SC_DELOUSE(t,v) ((t)(unsigned long)(v))
 #endif
@@ -72,26 +69,9 @@ typedef struct compat_sigaltstack {
 typedef __compat_uid32_t	compat_uid_t;
 typedef __compat_gid32_t	compat_gid_t;
 
-typedef	compat_ulong_t		compat_aio_context_t;
-
 struct compat_sel_arg_struct;
 struct rusage;
 
-struct compat_itimerspec {
-	struct compat_timespec it_interval;
-	struct compat_timespec it_value;
-};
-
-struct compat_utimbuf {
-	compat_time_t		actime;
-	compat_time_t		modtime;
-};
-
-struct compat_itimerval {
-	struct compat_timeval	it_interval;
-	struct compat_timeval	it_value;
-};
-
 struct compat_tms {
 	compat_clock_t		tms_utime;
 	compat_clock_t		tms_stime;
@@ -99,39 +79,6 @@ struct compat_tms {
 	compat_clock_t		tms_cstime;
 };
 
-struct compat_timex {
-	compat_uint_t modes;
-	compat_long_t offset;
-	compat_long_t freq;
-	compat_long_t maxerror;
-	compat_long_t esterror;
-	compat_int_t status;
-	compat_long_t constant;
-	compat_long_t precision;
-	compat_long_t tolerance;
-	struct compat_timeval time;
-	compat_long_t tick;
-	compat_long_t ppsfreq;
-	compat_long_t jitter;
-	compat_int_t shift;
-	compat_long_t stabil;
-	compat_long_t jitcnt;
-	compat_long_t calcnt;
-	compat_long_t errcnt;
-	compat_long_t stbcnt;
-	compat_int_t tai;
-
-	compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32;
-	compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32;
-	compat_int_t:32; compat_int_t:32; compat_int_t:32;
-};
-
-#define _COMPAT_NSIG_WORDS	(_COMPAT_NSIG / _COMPAT_NSIG_BPW)
-
-typedef struct {
-	compat_sigset_word	sig[_COMPAT_NSIG_WORDS];
-} compat_sigset_t;
-
 struct compat_sigaction {
 #ifndef __ARCH_HAS_IRIX_SIGACTION
 	compat_uptr_t			sa_handler;
@@ -146,24 +93,6 @@ struct compat_sigaction {
 	compat_sigset_t			sa_mask __packed;
 };
 
-/*
- * These functions operate on 32- or 64-bit specs depending on
- * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
- */
-extern int compat_get_timespec(struct timespec *, const void __user *);
-extern int compat_put_timespec(const struct timespec *, void __user *);
-extern int compat_get_timeval(struct timeval *, const void __user *);
-extern int compat_put_timeval(const struct timeval *, void __user *);
-
-/*
- * This function convert a timespec if necessary and returns a *user
- * space* pointer.  If no conversion is necessary, it returns the
- * initial pointer.  NULL is a legitimate argument and will always
- * output NULL.
- */
-extern int compat_convert_timespec(struct timespec __user **,
-				   const void __user *);
-
 struct compat_iovec {
 	compat_uptr_t	iov_base;
 	compat_size_t	iov_len;
@@ -174,28 +103,6 @@ struct compat_rlimit {
 	compat_ulong_t	rlim_max;
 };
 
-struct compat_rusage {
-	struct compat_timeval ru_utime;
-	struct compat_timeval ru_stime;
-	compat_long_t	ru_maxrss;
-	compat_long_t	ru_ixrss;
-	compat_long_t	ru_idrss;
-	compat_long_t	ru_isrss;
-	compat_long_t	ru_minflt;
-	compat_long_t	ru_majflt;
-	compat_long_t	ru_nswap;
-	compat_long_t	ru_inblock;
-	compat_long_t	ru_oublock;
-	compat_long_t	ru_msgsnd;
-	compat_long_t	ru_msgrcv;
-	compat_long_t	ru_nsignals;
-	compat_long_t	ru_nvcsw;
-	compat_long_t	ru_nivcsw;
-};
-
-extern int put_compat_rusage(const struct rusage *,
-			     struct compat_rusage __user *);
-
 struct compat_siginfo;
 
 extern asmlinkage long compat_sys_waitid(int, compat_pid_t,
@@ -324,8 +231,6 @@ asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp,
 		compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg);
 long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmctl(int first, int second, void __user *uptr);
-long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
-		unsigned nsems, const struct compat_timespec __user *timeout);
 asmlinkage long compat_sys_keyctl(u32 option,
 			      u32 arg2, u32 arg3, u32 arg4, u32 arg5);
 asmlinkage long compat_sys_ustat(unsigned dev, struct compat_ustat __user *u32);
@@ -361,12 +266,6 @@ asmlinkage long compat_sys_execveat(int dfd, const char __user *filename,
 		     const compat_uptr_t __user *argv,
 		     const compat_uptr_t __user *envp, int flags);
 
-asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
-		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
-		struct compat_timeval __user *tvp);
-
-asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg);
-
 asmlinkage long compat_sys_wait4(compat_pid_t pid,
 				 compat_uint_t __user *stat_addr, int options,
 				 struct compat_rusage __user *ru);
@@ -392,38 +291,6 @@ asmlinkage long compat_sys_sigaction(int sig,
                                    struct compat_old_sigaction __user *oact);
 #endif
 
-static inline int compat_timeval_compare(struct compat_timeval *lhs,
-					struct compat_timeval *rhs)
-{
-	if (lhs->tv_sec < rhs->tv_sec)
-		return -1;
-	if (lhs->tv_sec > rhs->tv_sec)
-		return 1;
-	return lhs->tv_usec - rhs->tv_usec;
-}
-
-static inline int compat_timespec_compare(struct compat_timespec *lhs,
-					struct compat_timespec *rhs)
-{
-	if (lhs->tv_sec < rhs->tv_sec)
-		return -1;
-	if (lhs->tv_sec > rhs->tv_sec)
-		return 1;
-	return lhs->tv_nsec - rhs->tv_nsec;
-}
-
-extern int get_compat_itimerspec(struct itimerspec *dst,
-				 const struct compat_itimerspec __user *src);
-extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
-				 const struct itimerspec *src);
-
-asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
-		struct timezone __user *tz);
-asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
-		struct timezone __user *tz);
-
-asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
-
 extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat);
 extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set);
 
@@ -451,48 +318,20 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
 			const compat_sigset_t __user *sigmask,
 			compat_size_t sigsetsize);
 
-asmlinkage long compat_sys_utime(const char __user *filename,
-				 struct compat_utimbuf __user *t);
-asmlinkage long compat_sys_utimensat(unsigned int dfd,
-				     const char __user *filename,
-				     struct compat_timespec __user *t,
-				     int flags);
-
-asmlinkage long compat_sys_time(compat_time_t __user *tloc);
-asmlinkage long compat_sys_stime(compat_time_t __user *tptr);
 asmlinkage long compat_sys_signalfd(int ufd,
 				    const compat_sigset_t __user *sigmask,
 				    compat_size_t sigsetsize);
-asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
-				   const struct compat_itimerspec __user *utmr,
-				   struct compat_itimerspec __user *otmr);
-asmlinkage long compat_sys_timerfd_gettime(int ufd,
-				   struct compat_itimerspec __user *otmr);
-
 asmlinkage long compat_sys_move_pages(pid_t pid, compat_ulong_t nr_pages,
 				      __u32 __user *pages,
 				      const int __user *nodes,
 				      int __user *status,
 				      int flags);
-asmlinkage long compat_sys_futimesat(unsigned int dfd,
-				     const char __user *filename,
-				     struct compat_timeval __user *t);
-asmlinkage long compat_sys_utimes(const char __user *filename,
-				  struct compat_timeval __user *t);
-asmlinkage long compat_sys_newstat(const char __user *filename,
-				   struct compat_stat __user *statbuf);
-asmlinkage long compat_sys_newlstat(const char __user *filename,
-				    struct compat_stat __user *statbuf);
-asmlinkage long compat_sys_newfstatat(unsigned int dfd,
-				      const char __user *filename,
-				      struct compat_stat __user *statbuf,
-				      int flag);
-asmlinkage long compat_sys_newfstat(unsigned int fd,
-				    struct compat_stat __user *statbuf);
+struct compat_statfs;
 asmlinkage long compat_sys_statfs(const char __user *pathname,
 				  struct compat_statfs __user *buf);
 asmlinkage long compat_sys_fstatfs(unsigned int fd,
 				   struct compat_statfs __user *buf);
+struct compat_statfs64;
 asmlinkage long compat_sys_statfs64(const char __user *pathname,
 				    compat_size_t sz,
 				    struct compat_statfs64 __user *buf);
@@ -503,11 +342,6 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
 				 compat_ulong_t arg);
 asmlinkage long compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p);
-asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id,
-					compat_long_t min_nr,
-					compat_long_t nr,
-					struct io_event __user *events,
-					struct compat_timespec __user *timeout);
 asmlinkage long compat_sys_io_submit(compat_aio_context_t ctx_id, int nr,
 				     u32 __user *iocb);
 asmlinkage long compat_sys_mount(const char __user *dev_name,
@@ -536,16 +370,6 @@ asmlinkage long compat_sys_open_by_handle_at(int mountdirfd,
 					     int flags);
 asmlinkage long compat_sys_truncate(const char __user *, compat_off_t);
 asmlinkage long compat_sys_ftruncate(unsigned int, compat_ulong_t);
-asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
-				    compat_ulong_t __user *outp,
-				    compat_ulong_t __user *exp,
-				    struct compat_timespec __user *tsp,
-				    void __user *sig);
-asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
-				 unsigned int nfds,
-				 struct compat_timespec __user *tsp,
-				 const compat_sigset_t __user *sigmask,
-				 compat_size_t sigsetsize);
 asmlinkage long compat_sys_signalfd4(int ufd,
 				     const compat_sigset_t __user *sigmask,
 				     compat_size_t sigsetsize, int flags);
@@ -574,16 +398,6 @@ asmlinkage long compat_sys_recv(int fd, void __user *buf, compat_size_t len,
 asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len,
 			    unsigned flags, struct sockaddr __user *addr,
 			    int __user *addrlen);
-asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
-				    unsigned vlen, unsigned int flags,
-				    struct compat_timespec __user *timeout);
-asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
-				     struct compat_timespec __user *rmtp);
-asmlinkage long compat_sys_getitimer(int which,
-				     struct compat_itimerval __user *it);
-asmlinkage long compat_sys_setitimer(int which,
-				     struct compat_itimerval __user *in,
-				     struct compat_itimerval __user *out);
 asmlinkage long compat_sys_times(struct compat_tms __user *tbuf);
 asmlinkage long compat_sys_setrlimit(unsigned int resource,
 				     struct compat_rlimit __user *rlim);
@@ -599,25 +413,6 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid,
 asmlinkage long compat_sys_timer_create(clockid_t which_clock,
 			struct compat_sigevent __user *timer_event_spec,
 			timer_t __user *created_timer_id);
-asmlinkage long compat_sys_timer_settime(timer_t timer_id, int flags,
-					 struct compat_itimerspec __user *new,
-					 struct compat_itimerspec __user *old);
-asmlinkage long compat_sys_timer_gettime(timer_t timer_id,
-				 struct compat_itimerspec __user *setting);
-asmlinkage long compat_sys_clock_settime(clockid_t which_clock,
-					 struct compat_timespec __user *tp);
-asmlinkage long compat_sys_clock_gettime(clockid_t which_clock,
-					 struct compat_timespec __user *tp);
-asmlinkage long compat_sys_clock_adjtime(clockid_t which_clock,
-					 struct compat_timex __user *tp);
-asmlinkage long compat_sys_clock_getres(clockid_t which_clock,
-					struct compat_timespec __user *tp);
-asmlinkage long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
-					   struct compat_timespec __user *rqtp,
-					   struct compat_timespec __user *rmtp);
-asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese,
-		struct compat_siginfo __user *uinfo,
-		struct compat_timespec __user *uts, compat_size_t sigsetsize);
 asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset,
 					 compat_size_t sigsetsize);
 asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set,
@@ -636,9 +431,6 @@ asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig,
 asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info);
 asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
 				 compat_ulong_t arg);
-asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
-		struct compat_timespec __user *utime, u32 __user *uaddr2,
-		u32 val3);
 asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
 				      char __user *optval, int __user *optlen);
 asmlinkage long compat_sys_kexec_load(compat_ulong_t entry,
@@ -653,14 +445,6 @@ asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
 asmlinkage long compat_sys_mq_open(const char __user *u_name,
 			int oflag, compat_mode_t mode,
 			struct compat_mq_attr __user *u_attr);
-asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
-			const char __user *u_msg_ptr,
-			compat_size_t msg_len, unsigned int msg_prio,
-			const struct compat_timespec __user *u_abs_timeout);
-asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
-			char __user *u_msg_ptr,
-			compat_size_t msg_len, unsigned int __user *u_msg_prio,
-			const struct compat_timespec __user *u_abs_timeout);
 asmlinkage long compat_sys_socketcall(int call, u32 __user *args);
 asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args);
 
@@ -707,9 +491,6 @@ int __compat_save_altstack(compat_stack_t __user *, unsigned long);
 	put_user_ex(t->sas_ss_size, &__uss->ss_size); \
 } while (0);
 
-asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
-						 struct compat_timespec __user *interval);
-
 asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
 					    int, const char __user *);
 #else
diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
new file mode 100644
index 000000000000..37564582f6a5
--- /dev/null
+++ b/include/linux/compat_time.h
@@ -0,0 +1,255 @@
+#ifndef _LINUX_COMPAT_TIME_H
+#define _LINUX_COMPAT_TIME_H
+/*
+ * These are the type definitions for the architecture specific
+ * syscall compatibility layer for 32-bit time_t.
+ *
+ * The emulation is used both on 32-bit architectures that have
+ * been converted to 64-bit __kernel_time_t as well as on 64-bit
+ * architectures with 32-bit user space.
+ */
+#include <linux/resource.h>
+#include <linux/signal.h>
+
+#ifndef COMPAT_USE_64BIT_TIME
+#define COMPAT_USE_64BIT_TIME 0
+#endif
+
+typedef s32	compat_int_t;
+typedef u32	compat_uint_t;
+typedef s32	compat_long_t;
+typedef u32	compat_ulong_t;
+typedef u32	compat_size_t;
+typedef s32	compat_ssize_t;
+typedef s32	compat_time_t;
+typedef	u32	compat_aio_context_t;
+typedef u32	compat_uptr_t;
+typedef __kernel_pid_t compat_pid_t;
+
+struct compat_timespec {
+	compat_time_t	tv_sec;
+	s32		tv_nsec;
+};
+
+struct compat_timeval {
+	compat_time_t	tv_sec;
+	s32		tv_usec;
+};
+
+struct compat_itimerspec {
+	struct compat_timespec it_interval;
+	struct compat_timespec it_value;
+};
+
+struct compat_utimbuf {
+	compat_time_t		actime;
+	compat_time_t		modtime;
+};
+
+struct compat_itimerval {
+	struct compat_timeval	it_interval;
+	struct compat_timeval	it_value;
+};
+
+struct compat_timex {
+	compat_uint_t modes;
+	compat_long_t offset;
+	compat_long_t freq;
+	compat_long_t maxerror;
+	compat_long_t esterror;
+	compat_int_t status;
+	compat_long_t constant;
+	compat_long_t precision;
+	compat_long_t tolerance;
+	struct compat_timeval time;
+	compat_long_t tick;
+	compat_long_t ppsfreq;
+	compat_long_t jitter;
+	compat_int_t shift;
+	compat_long_t stabil;
+	compat_long_t jitcnt;
+	compat_long_t calcnt;
+	compat_long_t errcnt;
+	compat_long_t stbcnt;
+	compat_int_t tai;
+
+	compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32;
+	compat_int_t:32; compat_int_t:32; compat_int_t:32; compat_int_t:32;
+	compat_int_t:32; compat_int_t:32; compat_int_t:32;
+};
+
+
+/*
+ * These functions operate on 32- or 64-bit specs depending on
+ * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
+ */
+extern int compat_get_timespec(struct timespec *, const void __user *);
+extern int compat_put_timespec(const struct timespec *, void __user *);
+extern int compat_get_timeval(struct timeval *, const void __user *);
+extern int compat_put_timeval(const struct timeval *, void __user *);
+
+/*
+ * This function convert a timespec if necessary and returns a *user
+ * space* pointer.  If no conversion is necessary, it returns the
+ * initial pointer.  NULL is a legitimate argument and will always
+ * output NULL.
+ */
+extern int compat_convert_timespec(struct timespec __user **,
+				   const void __user *);
+
+struct compat_rusage {
+	struct compat_timeval ru_utime;
+	struct compat_timeval ru_stime;
+	compat_long_t	ru_maxrss;
+	compat_long_t	ru_ixrss;
+	compat_long_t	ru_idrss;
+	compat_long_t	ru_isrss;
+	compat_long_t	ru_minflt;
+	compat_long_t	ru_majflt;
+	compat_long_t	ru_nswap;
+	compat_long_t	ru_inblock;
+	compat_long_t	ru_oublock;
+	compat_long_t	ru_msgsnd;
+	compat_long_t	ru_msgrcv;
+	compat_long_t	ru_nsignals;
+	compat_long_t	ru_nvcsw;
+	compat_long_t	ru_nivcsw;
+};
+
+struct rusage;
+extern int put_compat_rusage(const struct rusage *,
+			     struct compat_rusage __user *);
+
+static inline int compat_timeval_compare(struct compat_timeval *lhs,
+					struct compat_timeval *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_usec - rhs->tv_usec;
+}
+
+static inline int compat_timespec_compare(struct compat_timespec *lhs,
+					struct compat_timespec *rhs)
+{
+	if (lhs->tv_sec < rhs->tv_sec)
+		return -1;
+	if (lhs->tv_sec > rhs->tv_sec)
+		return 1;
+	return lhs->tv_nsec - rhs->tv_nsec;
+}
+
+extern int get_compat_itimerspec(struct itimerspec *dst,
+				 const struct compat_itimerspec __user *src);
+extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
+				 const struct itimerspec *src);
+
+struct sembuf;
+asmlinkage long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
+		unsigned nsems, const struct compat_timespec __user *timeout);
+asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
+		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+		struct compat_timeval __user *tvp);
+struct compat_sel_arg_struct;
+asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg);
+asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
+				    compat_ulong_t __user *outp,
+				    compat_ulong_t __user *exp,
+				    struct compat_timespec __user *tsp,
+				    void __user *sig);
+asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
+		struct timezone __user *tz);
+asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
+		struct timezone __user *tz);
+
+asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
+
+asmlinkage long compat_sys_utime(const char __user *filename,
+				 struct compat_utimbuf __user *t);
+asmlinkage long compat_sys_utimensat(unsigned int dfd,
+				     const char __user *filename,
+				     struct compat_timespec __user *t,
+				     int flags);
+
+asmlinkage long compat_sys_time(compat_time_t __user *tloc);
+asmlinkage long compat_sys_stime(compat_time_t __user *tptr);
+
+asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
+				   const struct compat_itimerspec __user *utmr,
+				   struct compat_itimerspec __user *otmr);
+asmlinkage long compat_sys_timerfd_gettime(int ufd,
+				   struct compat_itimerspec __user *otmr);
+
+asmlinkage long compat_sys_futimesat(unsigned int dfd,
+				     const char __user *filename,
+				     struct compat_timeval __user *t);
+asmlinkage long compat_sys_utimes(const char __user *filename,
+				  struct compat_timeval __user *t);
+struct compat_stat;
+asmlinkage long compat_sys_newstat(const char __user *filename,
+				   struct compat_stat __user *statbuf);
+asmlinkage long compat_sys_newlstat(const char __user *filename,
+				    struct compat_stat __user *statbuf);
+asmlinkage long compat_sys_newfstatat(unsigned int dfd,
+				      const char __user *filename,
+				      struct compat_stat __user *statbuf,
+				      int flag);
+asmlinkage long compat_sys_newfstat(unsigned int fd,
+				    struct compat_stat __user *statbuf);
+struct io_event;
+asmlinkage long compat_sys_io_getevents(compat_aio_context_t ctx_id,
+					compat_long_t min_nr,
+					compat_long_t nr,
+					struct io_event __user *events,
+					struct compat_timespec __user *timeout);
+asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+				 unsigned int nfds,
+				 struct compat_timespec __user *tsp,
+				 const compat_sigset_t __user *sigmask,
+				 compat_size_t sigsetsize);
+struct compat_mmsghdr;
+asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
+				    unsigned vlen, unsigned int flags,
+				    struct compat_timespec __user *timeout);
+asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
+				     struct compat_timespec __user *rmtp);
+asmlinkage long compat_sys_getitimer(int which,
+				     struct compat_itimerval __user *it);
+asmlinkage long compat_sys_setitimer(int which,
+				     struct compat_itimerval __user *in,
+				     struct compat_itimerval __user *out);
+asmlinkage long compat_sys_timer_settime(timer_t timer_id, int flags,
+					 struct compat_itimerspec __user *new,
+					 struct compat_itimerspec __user *old);
+asmlinkage long compat_sys_timer_gettime(timer_t timer_id,
+				 struct compat_itimerspec __user *setting);
+asmlinkage long compat_sys_clock_settime(clockid_t which_clock,
+					 struct compat_timespec __user *tp);
+asmlinkage long compat_sys_clock_gettime(clockid_t which_clock,
+					 struct compat_timespec __user *tp);
+asmlinkage long compat_sys_clock_adjtime(clockid_t which_clock,
+					 struct compat_timex __user *tp);
+asmlinkage long compat_sys_clock_getres(clockid_t which_clock,
+					struct compat_timespec __user *tp);
+asmlinkage long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
+					   struct compat_timespec __user *rqtp,
+					   struct compat_timespec __user *rmtp);
+struct compat_siginfo;
+asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese,
+		struct compat_siginfo __user *uinfo,
+		struct compat_timespec __user *uts, compat_size_t sigsetsize);
+asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
+		struct compat_timespec __user *utime, u32 __user *uaddr2,
+		u32 val3);
+asmlinkage long compat_sys_mq_timedsend(mqd_t mqdes,
+			const char __user *u_msg_ptr,
+			compat_size_t msg_len, unsigned int msg_prio,
+			const struct compat_timespec __user *u_abs_timeout);
+asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
+			char __user *u_msg_ptr,
+			compat_size_t msg_len, unsigned int __user *u_msg_prio,
+			const struct compat_timespec __user *u_abs_timeout);
+asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
+						 struct compat_timespec __user *interval);
+#endif
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 04/19] y2038: introduce CONFIG_COMPAT_TIME
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (2 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 03/19] y2038: introduce linux/compat_time.h header Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 05/19] y2038: make linux/compat_time.h usable on 32-bit Arnd Bergmann
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

There are a total of system calls (aside from ioctl) that pass a time_t
or derived data structure as an argument, and in order to extend time_t
to 64-bit, we have to replace them with new system calls and keep providing
backwards compatibility.

To avoid adding completely new and untested code for this purpose, we
introduce a new CONFIG_COMPAT_TIME symbol that is always set on 64-bit
architectures with 32-bit compat mode, as well as all 32-bit architectures
that have been extended to provide the new system calls.

After this is done for all architectures, the CONFIG_COMPAT_TIME symbol
can be made a user-selected option, to enable users to build a kernel
that only provides y2038-safe system calls.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/Kconfig | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index a65eafb24997..630d3d289569 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -545,4 +545,15 @@ config OLD_SIGACTION
 config COMPAT_OLD_SIGACTION
 	bool
 
+config ARCH_HAS_COMPAT_TIME
+	def_bool COMPAT
+
+config COMPAT_TIME
+	def_bool ARCH_HAS_COMPAT_TIME
+	help
+	  This should be selected by all architectures that need to support
+	  system calls with a 32-bit time_t. Traditionally, this has been
+	  used on all 32-bit architectures, and needs to be supported on
+	  64-bit architectures as part of compat syscall handling.
+
 source "kernel/gcov/Kconfig"
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 05/19] y2038: make linux/compat_time.h usable on 32-bit
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (3 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 04/19] y2038: introduce CONFIG_COMPAT_TIME Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 06/19] y2038: compile compat time code even when CONFIG_COMPAT is not set Arnd Bergmann
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This adds the necessary type definitions to allow using the
linux/compat_time.h header file on 32-bit architectures without
adding an asm/compat.h header in each architecture.

The types we define here are used in the compat system call
definitions of some system calls that also pass a time_t
in another structure, but are themselves not depending on the
size of time_t.

This also adds a way to use COMPAT_SYSCALL_DEFINE() by
including the compat.h header file. Some code may need to
get reshuffled here.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/compat.h      |  6 ++++--
 include/linux/compat_time.h | 24 ++++++++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index 41b0dae6203b..fefc45094107 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -5,8 +5,6 @@
  * syscall compatibility layer.
  */
 
-#ifdef CONFIG_COMPAT
-
 #include <linux/stat.h>
 #include <linux/param.h>	/* for HZ */
 #include <linux/sem.h>
@@ -17,7 +15,9 @@
 #include <linux/unistd.h>
 #include <linux/compat_time.h>
 
+#ifdef CONFIG_COMPAT
 #include <asm/compat.h>
+#endif
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 
@@ -52,6 +52,8 @@
 	}								\
 	static inline long C_SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
 
+#ifdef CONFIG_COMPAT
+
 #ifndef compat_user_stack_pointer
 #define compat_user_stack_pointer() current_user_stack_pointer()
 #endif
diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
index 37564582f6a5..e17375a91f76 100644
--- a/include/linux/compat_time.h
+++ b/include/linux/compat_time.h
@@ -78,6 +78,30 @@ struct compat_timex {
 	compat_int_t:32; compat_int_t:32; compat_int_t:32;
 };
 
+#ifdef CONFIG_COMPAT
+#include <asm/compat.h>
+
+#define _COMPAT_NSIG_WORDS     (_COMPAT_NSIG / _COMPAT_NSIG_BPW)
+typedef struct {
+       compat_sigset_word      sig[_COMPAT_NSIG_WORDS];
+} compat_sigset_t;
+
+#else
+
+#define compat_mmsghdr mmsghdr
+#define compat_stat stat
+#define compat_siginfo siginfo
+#define compat_sigevent sigevent
+#define compat_sigset_t sigset_t
+#define __compat_uid_t __kernel_uid_t
+#define __compat_gid_t __kernel_gid_t
+#define compat_mode_t __kernel_mode_t
+#define copy_siginfo_to_user32(uinfo, info) copy_siginfo_to_user(uinfo, info)
+static inline void __user *compat_ptr(compat_uptr_t ptr)
+{
+	return (void __user*)ptr;
+}
+#endif
 
 /*
  * These functions operate on 32- or 64-bit specs depending on
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 06/19] y2038: compile compat time code even when CONFIG_COMPAT is not set
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (4 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 05/19] y2038: make linux/compat_time.h usable on 32-bit Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 07/19] y2038: add compat_sys_rt_sigtimedwait variants Arnd Bergmann
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

For the time being, we use conditional compilation in fs/compat.c
and kernel/compat.c to differentiate two cases:

a) code that is used for CONFIG_COMPAT_TIME is shared between
   32-bit and 64-bit architectures that provide support for
   existing 32-bit binaries with 32-bit time_t
b) code that is defined under CONFIG_COMPAT is only used on
   64-bit machines to provide support for 32-bit binaries,
   either system calls that do not use time_t or (rare) that use a
   64-bit time_t in compat mode.

We probably want to split those into separate files in the long
run, but at the moment, this makes it easier to avoid merge
conflicts.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 fs/Makefile                 |  1 +
 fs/compat.c                 | 12 +++++++++++-
 include/linux/thread_info.h |  2 +-
 kernel/Makefile             |  1 +
 kernel/compat.c             | 28 ++++++++++++++++++++++++++++
 5 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/fs/Makefile b/fs/Makefile
index cb92fd4c3172..77f876cd94be 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_AIO)               += aio.o
 obj-$(CONFIG_FS_DAX)		+= dax.o
 obj-$(CONFIG_FILE_LOCKING)      += locks.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
+obj-$(CONFIG_COMPAT_TIME)	+= compat.o
 obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
diff --git a/fs/compat.c b/fs/compat.c
index 7d78cde20fc3..c5065aa1852c 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -54,6 +54,7 @@
 #include <asm/ioctls.h>
 #include "internal.h"
 
+#ifdef CONFIG_COMPAT_TIME
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -194,7 +195,9 @@ COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
 		error = cp_compat_stat(&stat, statbuf);
 	return error;
 }
+#endif /* CONFIG_COMPAT_TIME */
 
+#ifdef CONFIG_COMPAT
 static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
 {
 	
@@ -505,7 +508,9 @@ COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_reqs, u32 __user *, ctx32p)
 		ret = put_user((u32) ctx64, ctx32p);
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
 		       compat_long_t, min_nr,
 		       compat_long_t, nr,
@@ -525,7 +530,9 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
 	} 
 	return sys_io_getevents(ctx_id, min_nr, nr, events, ut);
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 /* A write operation does a read from user space and vice versa */
 #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
 
@@ -1086,7 +1093,9 @@ COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, fla
 {
 	return do_sys_open(dfd, filename, flags, mode);
 }
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 #define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
 
 static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
@@ -1453,8 +1462,9 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
 
 	return ret;
 }
+#endif
 
-#ifdef CONFIG_FHANDLE
+#if defined(CONFIG_FHANDLE) && defined(CONFIG_COMPAT)
 /*
  * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
  * doesn't set the O_LARGEFILE flag.
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index ff307b548ed3..43686bb94374 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -32,7 +32,7 @@ struct restart_block {
 		struct {
 			clockid_t clockid;
 			struct timespec __user *rmtp;
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_COMPAT_TIME
 			struct compat_timespec __user *compat_rmtp;
 #endif
 			u64 expires;
diff --git a/kernel/Makefile b/kernel/Makefile
index 60c302cfb4d3..970f880a5f17 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT_TIME) += compat.o
 obj-$(CONFIG_CGROUPS) += cgroup.o
 obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
diff --git a/kernel/compat.c b/kernel/compat.c
index 24f00610c575..115ad84d4048 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -30,6 +30,7 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_COMPAT_TIME
 static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
 {
 	memset(txc, 0, sizeof(struct timex));
@@ -190,6 +191,7 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
 }
 EXPORT_SYMBOL_GPL(compat_put_timespec);
 
+#ifdef CONFIG_COMPAT
 int compat_convert_timespec(struct timespec __user **kts,
 			    const void __user *cts)
 {
@@ -212,6 +214,7 @@ int compat_convert_timespec(struct timespec __user **kts,
 	*kts = uts;
 	return 0;
 }
+#endif
 
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
@@ -339,7 +342,9 @@ COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
 		return -EFAULT;
 	return 0;
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
 {
 	return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));
@@ -507,7 +512,9 @@ COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
 	}
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
 {
 	if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
@@ -598,7 +605,9 @@ COMPAT_SYSCALL_DEFINE5(waitid,
 	info.si_code |= __SI_CHLD;
 	return copy_siginfo_to_user32(uinfo, &info);
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
 				    unsigned len, struct cpumask *new_mask)
 {
@@ -660,7 +669,9 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t,  pid, unsigned int, len,
 
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 int get_compat_itimerspec(struct itimerspec *dst,
 			  const struct compat_itimerspec __user *src)
 {
@@ -678,7 +689,9 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
 		return -EFAULT;
 	return 0;
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 		       struct compat_sigevent __user *, timer_event_spec,
 		       timer_t __user *, created_timer_id)
@@ -696,7 +709,9 @@ COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 
 	return sys_timer_create(which_clock, event, created_timer_id);
 }
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
 		       struct compat_itimerspec __user *, new,
 		       struct compat_itimerspec __user *, old)
@@ -865,7 +880,9 @@ COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 	}
 	return err;
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
@@ -991,6 +1008,7 @@ sigset_to_compat(compat_sigset_t *compat, const sigset_t *set)
 	}
 }
 
+#ifdef CONFIG_COMPAT_TIME
 COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 		struct compat_siginfo __user *, uinfo,
 		struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
@@ -1022,7 +1040,10 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 
 	return ret;
 }
+#endif
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
 
 /* compat_time_t is a 32 bit "long" and needs to get converted. */
@@ -1080,7 +1101,9 @@ COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
 
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 #ifdef CONFIG_NUMA
 COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
 		       compat_uptr_t __user *, pages32,
@@ -1135,7 +1158,9 @@ COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
 	return sys_migrate_pages(pid, nr_bits + 1, old, new);
 }
 #endif
+#endif
 
+#ifdef CONFIG_COMPAT_TIME
 COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
 		       compat_pid_t, pid,
 		       struct compat_timespec __user *, interval)
@@ -1151,7 +1176,9 @@ COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
 		return -EFAULT;
 	return ret;
 }
+#endif
 
+#ifdef CONFIG_COMPAT
 /*
  * Allocate user-space memory for the duration of a single system call,
  * in order to marshall parameters inside a compat thunk.
@@ -1172,3 +1199,4 @@ void __user *compat_alloc_user_space(unsigned long len)
 	return ptr;
 }
 EXPORT_SYMBOL_GPL(compat_alloc_user_space);
+#endif
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 07/19] y2038: add compat_sys_rt_sigtimedwait variants
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (5 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 06/19] y2038: compile compat time code even when CONFIG_COMPAT is not set Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 08/19] y2038: introduce struct __kernel_timespec Arnd Bergmann
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

rt_sigtimedwait takes sigevent and sigset arguments that are always
different between 32-bit and 64-bit user space. It also takes a
timespec argument that will be the same in the future between
architectures, and we want to share the compat system call handling.

We need to support all four combinations, and this adds the two new
ones:

- native sys_rt_sigtimedwait: now takes a __kernel_timespec that
  will at some point use 64-bit time_t on all architectures
- compat_sys_rt_sigtimedwait on 64-bit kernels: emulates the
  behavior of the old 32-bit user space
- compat_sys_rt_sigtimedwait on 32-bit kernels: emulates the
  old timespec but uses the native 32-bit sigevent and siginfo
  arguments
- compat_sys_rt_sigtimedwait_time64 on 64-bit kernels: emulates
  the 32-bit sigevent and siginfo structures but uses the native
  __kernel_timespec.

Having separate code for all four variants is a bit ugly, but
I could not come up with a better solution, and the code duplication
is fairly low in the end.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/compat_time.h |  5 ++++
 kernel/compat.c             | 66 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
index e17375a91f76..789b6415e90e 100644
--- a/include/linux/compat_time.h
+++ b/include/linux/compat_time.h
@@ -8,6 +8,7 @@
  * been converted to 64-bit __kernel_time_t as well as on 64-bit
  * architectures with 32-bit user space.
  */
+#include <linux/signal.h>
 #include <linux/resource.h>
 #include <linux/signal.h>
 
@@ -260,9 +261,13 @@ asmlinkage long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 					   struct compat_timespec __user *rqtp,
 					   struct compat_timespec __user *rmtp);
 struct compat_siginfo;
+struct __kernel_timespec;
 asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese,
 		struct compat_siginfo __user *uinfo,
 		struct compat_timespec __user *uts, compat_size_t sigsetsize);
+asmlinkage long compat_sys_rt_sigtimedwait_time64(compat_sigset_t __user *uthese,
+		struct compat_siginfo __user *uinfo,
+		struct __kernel_timespec __user *uts, compat_size_t sigsetsize);
 asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
 		struct compat_timespec __user *utime, u32 __user *uaddr2,
 		u32 val3);
diff --git a/kernel/compat.c b/kernel/compat.c
index 115ad84d4048..03bb63995027 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -27,6 +27,8 @@
 #include <linux/times.h>
 #include <linux/ptrace.h>
 #include <linux/gfp.h>
+#include <linux/signal.h>
+#include <asm/signal.h>
 
 #include <asm/uaccess.h>
 
@@ -1043,6 +1045,70 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 #endif
 #endif
 
+#if defined(CONFIG_COMPAT_TIME) && !defined(CONFIG_COMPAT)
+COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, sigset_t __user *, uthese,
+		struct siginfo __user *, uinfo,
+		struct compat_timespec __user *, uts, size_t, sigsetsize)
+{
+	sigset_t s;
+	struct timespec t;
+	siginfo_t info;
+	long ret;
+
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&s, uthese, sizeof(sigset_t)))
+		return -EFAULT;
+	if (uts) {
+		if (compat_get_timespec(&t, uts))
+			return -EFAULT;
+	}
+
+	ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
+
+	if (ret > 0 && uinfo) {
+		if (copy_siginfo_to_user(uinfo, &info))
+			ret = -EFAULT;
+	}
+
+	return ret;
+}
+#endif
+
+#ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time64, compat_sigset_t __user *, uthese,
+		struct compat_siginfo __user *, uinfo,
+		struct __kernel_timespec __user *, uts, compat_size_t, sigsetsize)
+{
+	compat_sigset_t s32;
+	sigset_t s;
+	struct timespec t;
+	siginfo_t info;
+	long ret;
+
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
+		return -EFAULT;
+	sigset_from_compat(&s, &s32);
+	if (uts) {
+		if (get_timespec64(&t, uts))
+			return -EFAULT;
+	}
+
+	ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
+
+	if (ret > 0 && uinfo) {
+		if (copy_siginfo_to_user32(uinfo, &info))
+			ret = -EFAULT;
+	}
+
+	return ret;
+}
+#endif
+
 #ifdef CONFIG_COMPAT_TIME
 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
 
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 08/19] y2038: introduce struct __kernel_timespec
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (6 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 07/19] y2038: add compat_sys_rt_sigtimedwait variants Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 09/19] y2038: introduce struct __kernel_stat Arnd Bergmann
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

A lot of system calls pass a 'struct timespec' from or to user space,
and we want to change that type to be based on a 64-bit time_t by
default.

This introduces a new type struct __kernel_timespec, which has the
format we want to use eventually, but also has an override so all
architectures that do not define CONFIG_COMPAT_TIME yet still get the
old behavior.
Once all architectures set this, we can remove that override.

This also introduces a get_timespec64/put_timespec64 set of functions
that convert between a __kernel_timespec in user space and a timespec64
in kernel space.

The current behavior of get_timespec64 explicitly zeroes the upper half
of the tv_nsec member, to allow user space to define its own 'struct
timespec' with some padding in it. Whether this is a good or bad idea
is open for discussion.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/time64.h    | 17 +++++++++++------
 include/uapi/linux/time.h | 17 +++++++++++++++++
 kernel/time/time.c        | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/include/linux/time64.h b/include/linux/time64.h
index a3831478d9cf..880ebe4b4ba4 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -1,14 +1,12 @@
 #ifndef _LINUX_TIME64_H
 #define _LINUX_TIME64_H
 
-#include <uapi/linux/time.h>
-
 typedef __s64 time64_t;
 
-/*
- * This wants to go into uapi/linux/time.h once we agreed about the
- * userspace interfaces.
- */
+#ifndef CONFIG_COMPAT_TIME
+# define __kernel_timespec timespec
+#endif
+
 #if __BITS_PER_LONG == 64
 # define timespec64 timespec
 #else
@@ -18,6 +16,8 @@ struct timespec64 {
 };
 #endif
 
+#include <uapi/linux/time.h>
+
 /* Parameters used to convert the timespec values: */
 #define MSEC_PER_SEC	1000L
 #define USEC_PER_MSEC	1000L
@@ -187,4 +187,9 @@ static __always_inline void timespec64_add_ns(struct timespec64 *a, u64 ns)
 
 #endif
 
+extern int get_timespec64(struct timespec64 *ts,
+			  const struct __kernel_timespec __user *uts);
+extern int put_timespec64(const struct timespec64 *ts,
+			  struct __kernel_timespec __user *uts);
+
 #endif /* _LINUX_TIME64_H */
diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h
index e75e1b6ff27f..72d894df3013 100644
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -66,4 +66,21 @@ struct itimerval {
  */
 #define TIMER_ABSTIME			0x01
 
+/* types based on 64-bit time_t */
+#ifndef __kernel_timespec
+typedef __s64 __kernel_time64_t;
+
+struct __kernel_timespec {
+	__kernel_time64_t	tv_sec;
+	__s64			tv_nsec;
+};
+#endif
+
+#ifndef __kernel_itimerspec
+struct __kernel_itimerspec {
+	struct __kernel_timespec it_interval;
+	struct __kernel_timespec it_value;
+};
+#endif
+
 #endif /* _UAPI_LINUX_TIME_H */
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 2c85b7724af4..845af1db66fa 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -30,6 +30,7 @@
 #include <linux/export.h>
 #include <linux/timex.h>
 #include <linux/capability.h>
+#include <linux/compat.h>
 #include <linux/timekeeper_internal.h>
 #include <linux/errno.h>
 #include <linux/syscalls.h>
@@ -37,6 +38,7 @@
 #include <linux/fs.h>
 #include <linux/math64.h>
 #include <linux/ptrace.h>
+#include <linux/time64.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -783,3 +785,33 @@ struct timespec timespec_add_safe(const struct timespec lhs,
 
 	return res;
 }
+
+int get_timespec64(struct timespec64 *ts,
+		   const struct __kernel_timespec __user *uts)
+{
+	struct __kernel_timespec kts;
+	int ret;
+
+	ret = copy_from_user(&kts, uts, sizeof(kts));
+	if (ret)
+		return -EFAULT;
+
+	ts->tv_sec = kts.tv_sec;
+	if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
+		kts.tv_nsec &= 0xfffffffful;
+	ts->tv_nsec = kts.tv_nsec;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(get_timespec64);
+
+int put_timespec64(const struct timespec64 *ts,
+		   struct __kernel_timespec __user *uts)
+{
+	struct __kernel_timespec kts = {
+		.tv_sec = ts->tv_sec,
+		.tv_nsec = ts->tv_nsec
+	};
+	return copy_to_user(uts, &kts, sizeof(kts)) ? -EFAULT : 0;
+}
+EXPORT_SYMBOL_GPL(put_timespec64);
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 09/19] y2038: introduce struct __kernel_stat
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (7 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 08/19] y2038: introduce struct __kernel_timespec Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 10/19] y2038: use __kernel_stat for sys_newstat syscalls Arnd Bergmann
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

The stat() family of system calls uses up to three different data
structures: 'struct __kernel_oldstat', 'struct stat', and 'struct
stat64', which were extended in various ways over time. Unfortunately,
on most 32-bit architectures and even some 64-bit machines (parisc),
all of them use 32-bit timestamps, which are already broken because
they cannot represent the range of times that can be stored on
typical file systems. When time_t overflows, things of course become
much worse.

This introduces a fourth data structure, 'struct __kernel_stat', which
is supposed to match the layout of 'struct stat' on 64-bit architectures,
so the compat handlers can be shared between native 64-bit and compat
32-bit syscalls. On architectures that are always 32-bit, the asm-generic
variant can be used.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/alpha/include/uapi/asm/stat.h     |  4 +++
 arch/arm/include/uapi/asm/stat.h       |  2 ++
 arch/avr32/include/uapi/asm/stat.h     |  2 ++
 arch/blackfin/include/uapi/asm/stat.h  |  2 ++
 arch/cris/include/uapi/asm/stat.h      |  2 ++
 arch/frv/include/uapi/asm/stat.h       |  2 ++
 arch/ia64/include/uapi/asm/stat.h      |  4 +++
 arch/m32r/include/uapi/asm/stat.h      |  1 +
 arch/m68k/include/uapi/asm/stat.h      |  2 ++
 arch/mips/include/uapi/asm/stat.h      |  1 +
 arch/mn10300/include/uapi/asm/stat.h   |  2 ++
 arch/parisc/include/uapi/asm/stat.h    |  1 +
 arch/powerpc/include/uapi/asm/stat.h   | 25 +++++++++++++++++
 arch/s390/include/uapi/asm/stat.h      | 24 +++++++++++++++++
 arch/sh/include/uapi/asm/stat.h        |  2 ++
 arch/sparc/include/uapi/asm/stat.h     | 28 +++++++++++++++++++
 arch/x86/include/uapi/asm/stat.h       | 49 ++++++++++++++++++++++++----------
 arch/xtensa/include/uapi/asm/stat.h    |  2 ++
 include/linux/syscalls.h               | 11 ++++----
 include/uapi/asm-generic/kernel_stat.h | 36 +++++++++++++++++++++++++
 include/uapi/asm-generic/stat.h        | 12 +++++----
 21 files changed, 189 insertions(+), 25 deletions(-)
 create mode 100644 include/uapi/asm-generic/kernel_stat.h

diff --git a/arch/alpha/include/uapi/asm/stat.h b/arch/alpha/include/uapi/asm/stat.h
index 07ad3e6b3f3e..ca566bc620f6 100644
--- a/arch/alpha/include/uapi/asm/stat.h
+++ b/arch/alpha/include/uapi/asm/stat.h
@@ -1,6 +1,10 @@
 #ifndef _ALPHA_STAT_H
 #define _ALPHA_STAT_H
 
+#ifndef __kernel_stat
+#define __kernel_stat stat
+#endif
+
 struct stat {
 	unsigned int	st_dev;
 	unsigned int	st_ino;
diff --git a/arch/arm/include/uapi/asm/stat.h b/arch/arm/include/uapi/asm/stat.h
index 42c0c13999d5..537a12553dd8 100644
--- a/arch/arm/include/uapi/asm/stat.h
+++ b/arch/arm/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef _ASMARM_STAT_H
 #define _ASMARM_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
 	unsigned short st_dev;
 	unsigned short st_ino;
diff --git a/arch/avr32/include/uapi/asm/stat.h b/arch/avr32/include/uapi/asm/stat.h
index c06acef7fce7..2b528ca17985 100644
--- a/arch/avr32/include/uapi/asm/stat.h
+++ b/arch/avr32/include/uapi/asm/stat.h
@@ -8,6 +8,8 @@
 #ifndef _UAPI__ASM_AVR32_STAT_H
 #define _UAPI__ASM_AVR32_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
         unsigned short st_dev;
         unsigned short st_ino;
diff --git a/arch/blackfin/include/uapi/asm/stat.h b/arch/blackfin/include/uapi/asm/stat.h
index d3068a750b94..99ee343aec23 100644
--- a/arch/blackfin/include/uapi/asm/stat.h
+++ b/arch/blackfin/include/uapi/asm/stat.h
@@ -7,6 +7,8 @@
 #ifndef _UAPI_BFIN_STAT_H
 #define _UAPI_BFIN_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct stat {
 	unsigned short st_dev;
 	unsigned short __pad1;
diff --git a/arch/cris/include/uapi/asm/stat.h b/arch/cris/include/uapi/asm/stat.h
index 9e558cc3c43b..4837884cd2d3 100644
--- a/arch/cris/include/uapi/asm/stat.h
+++ b/arch/cris/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef _CRIS_STAT_H
 #define _CRIS_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 /* Keep this a verbatim copy of i386 version; tweak CRIS-specific bits in
    the kernel if necessary.  */
 
diff --git a/arch/frv/include/uapi/asm/stat.h b/arch/frv/include/uapi/asm/stat.h
index ce56de9b37ba..5448b198fbb6 100644
--- a/arch/frv/include/uapi/asm/stat.h
+++ b/arch/frv/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_STAT_H
 #define _ASM_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
 	unsigned short st_dev;
 	unsigned short st_ino;
diff --git a/arch/ia64/include/uapi/asm/stat.h b/arch/ia64/include/uapi/asm/stat.h
index 367bb90cdffa..cde68a31e183 100644
--- a/arch/ia64/include/uapi/asm/stat.h
+++ b/arch/ia64/include/uapi/asm/stat.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_IA64_STAT_H
 #define _ASM_IA64_STAT_H
 
+#ifndef __kernel_stat
+#define __kernel_stat stat
+#endif
+
 /*
  * Modified 1998, 1999
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
diff --git a/arch/m32r/include/uapi/asm/stat.h b/arch/m32r/include/uapi/asm/stat.h
index 98470fe483b6..d0ffa70f73c0 100644
--- a/arch/m32r/include/uapi/asm/stat.h
+++ b/arch/m32r/include/uapi/asm/stat.h
@@ -2,6 +2,7 @@
 #define _ASM_M32R_STAT_H
 
 #include <asm/byteorder.h>
+#include <asm-generic/kernel_stat.h>
 
 struct __old_kernel_stat {
 	unsigned short st_dev;
diff --git a/arch/m68k/include/uapi/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h
index dd38bc2e9f98..6f455db47b4e 100644
--- a/arch/m68k/include/uapi/asm/stat.h
+++ b/arch/m68k/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef _M68K_STAT_H
 #define _M68K_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
 	unsigned short st_dev;
 	unsigned short st_ino;
diff --git a/arch/mips/include/uapi/asm/stat.h b/arch/mips/include/uapi/asm/stat.h
index b47bc541bbc0..53e58fbd83fa 100644
--- a/arch/mips/include/uapi/asm/stat.h
+++ b/arch/mips/include/uapi/asm/stat.h
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 
 #include <asm/sgidefs.h>
+#include <asm-generic/kernel_stat.h>
 
 #if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32)
 
diff --git a/arch/mn10300/include/uapi/asm/stat.h b/arch/mn10300/include/uapi/asm/stat.h
index 63ff8371cf2c..af3b4d6b7b7a 100644
--- a/arch/mn10300/include/uapi/asm/stat.h
+++ b/arch/mn10300/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_STAT_H
 #define _ASM_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
 	unsigned short st_dev;
 	unsigned short st_ino;
diff --git a/arch/parisc/include/uapi/asm/stat.h b/arch/parisc/include/uapi/asm/stat.h
index b606b366d0a7..f06ce7ba0115 100644
--- a/arch/parisc/include/uapi/asm/stat.h
+++ b/arch/parisc/include/uapi/asm/stat.h
@@ -2,6 +2,7 @@
 #define _PARISC_STAT_H
 
 #include <linux/types.h>
+#include <asm-generic/kernel_stat.h>
 
 struct stat {
 	unsigned int	st_dev;		/* dev_t is 32 bits on parisc */
diff --git a/arch/powerpc/include/uapi/asm/stat.h b/arch/powerpc/include/uapi/asm/stat.h
index 84880b80cc1c..248d8072267f 100644
--- a/arch/powerpc/include/uapi/asm/stat.h
+++ b/arch/powerpc/include/uapi/asm/stat.h
@@ -78,4 +78,29 @@ struct stat64 {
 	unsigned int	__unused5;
 };
 
+#ifndef __kernel_stat
+/* this matches the powerpc64 'struct stat' for compat tasks */
+struct __kernel_stat {
+	unsigned long long	st_dev;
+	unsigned long long	st_ino;
+	unsigned long long	st_nlink;
+	unsigned int		st_mode;
+	unsigned int		st_uid;
+	unsigned int		st_gid;
+	unsigned long long	st_rdev;
+	unsigned long long	st_size;
+	unsigned long long	st_blksize;
+	unsigned long long	st_blocks;
+	unsigned long long	st_atime;
+	unsigned long long	st_atime_nsec;
+	unsigned long long	st_mtime;
+	unsigned long long	st_mtime_nsec;
+	unsigned long long	st_ctime;
+	unsigned long long	st_ctime_nsec;
+	unsigned long long	__unused4;
+	unsigned long long	__unused5;
+	unsigned long long	__unused6;
+};
+#endif
+
 #endif /* _ASM_POWERPC_STAT_H */
diff --git a/arch/s390/include/uapi/asm/stat.h b/arch/s390/include/uapi/asm/stat.h
index b4ca97d91466..d4c2711249dd 100644
--- a/arch/s390/include/uapi/asm/stat.h
+++ b/arch/s390/include/uapi/asm/stat.h
@@ -100,4 +100,28 @@ struct stat {
 
 #define STAT_HAVE_NSEC 1
 
+/* same layout as 'struct stat on s390x' for both 32-bit and 64-bit tasks */
+#ifndef __kernel_stat
+struct __kernel_stat {
+	unsigned long long st_dev;
+	unsigned long long st_ino;
+	unsigned long long st_nlink;
+	unsigned int	   st_mode;
+	unsigned int	   st_uid;
+	unsigned int	   st_gid;
+	unsigned int	   __pad1;
+	unsigned long long st_rdev;
+	unsigned long long st_size;
+	unsigned long long st_atime;
+	unsigned long long st_atime_nsec;
+	unsigned long long st_mtime;
+	unsigned long long st_mtime_nsec;
+	unsigned long long st_ctime;
+	unsigned long long st_ctime_nsec;
+	unsigned long long st_blksize;
+	long long	   st_blocks;
+	unsigned long long __unused[3];
+};
+#endif
+
 #endif
diff --git a/arch/sh/include/uapi/asm/stat.h b/arch/sh/include/uapi/asm/stat.h
index e1810cc6e3da..a13ffbcccd50 100644
--- a/arch/sh/include/uapi/asm/stat.h
+++ b/arch/sh/include/uapi/asm/stat.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_STAT_H
 #define __ASM_SH_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 struct __old_kernel_stat {
 	unsigned short st_dev;
 	unsigned short st_ino;
diff --git a/arch/sparc/include/uapi/asm/stat.h b/arch/sparc/include/uapi/asm/stat.h
index a232e9e1f4e5..6d19c7bdc641 100644
--- a/arch/sparc/include/uapi/asm/stat.h
+++ b/arch/sparc/include/uapi/asm/stat.h
@@ -104,4 +104,32 @@ struct stat64 {
 	unsigned int	__unused5;
 };
 #endif /* defined(__sparc__) && defined(__arch64__) */
+
+#ifndef __kernel_stat
+/* This matches the sparc64 'struct stat64' in compat tasks */
+struct __kernel_stat {
+	unsigned long long	st_dev;
+	unsigned long long	st_ino;
+	unsigned long long	st_nlink;
+
+	unsigned int		st_mode;
+	unsigned int		st_uid;
+	unsigned int		st_gid;
+	unsigned int		__pad0;
+
+	unsigned long long	st_rdev;
+	long long		st_size;
+	long long		st_blksize;
+	long long		st_blocks;
+
+	unsigned long long	st_atime;
+	unsigned long long	st_atime_nsec;
+	unsigned long long	st_mtime;
+	unsigned long long	st_mtime_nsec;
+	unsigned long long	st_ctime;
+	unsigned long long	st_ctime_nsec;
+	long long		__unused[3];
+};
+#endif
+
 #endif /* __SPARC_STAT_H */
diff --git a/arch/x86/include/uapi/asm/stat.h b/arch/x86/include/uapi/asm/stat.h
index bc03eb5d6360..5d5754fc3d36 100644
--- a/arch/x86/include/uapi/asm/stat.h
+++ b/arch/x86/include/uapi/asm/stat.h
@@ -27,12 +27,6 @@ struct stat {
 	unsigned long  __unused5;
 };
 
-/* We don't need to memset the whole thing just to initialize the padding */
-#define INIT_STRUCT_STAT_PADDING(st) do {	\
-	st.__unused4 = 0;			\
-	st.__unused5 = 0;			\
-} while (0)
-
 #define STAT64_HAS_BROKEN_ST_INO	1
 
 /* This matches struct stat64 in glibc2.1, hence the absolutely
@@ -102,14 +96,6 @@ struct stat {
 	__kernel_long_t		__unused[3];
 };
 
-/* We don't need to memset the whole thing just to initialize the padding */
-#define INIT_STRUCT_STAT_PADDING(st) do {	\
-	st.__pad0 = 0;				\
-	st.__unused[0] = 0;			\
-	st.__unused[1] = 0;			\
-	st.__unused[2] = 0;			\
-} while (0)
-
 #endif
 
 /* for 32bit emulation and 32 bit kernels */
@@ -134,4 +120,39 @@ struct __old_kernel_stat {
 #endif
 };
 
+#ifndef __kernel_stat
+/* This matches the 64-bit version of 'struct stat' on i386 */
+struct __kernel_stat {
+	unsigned long long	st_dev;
+	unsigned long long	st_ino;
+	unsigned long long	st_nlink;
+
+	unsigned int		st_mode;
+	unsigned int		st_uid;
+	unsigned int		st_gid;
+	unsigned int		__pad0;
+	unsigned long long	st_rdev;
+	long long		st_size;
+	long long		st_blksize;
+	long long		st_blocks;	/* Number 512-byte blocks allocated. */
+
+	unsigned long long	st_atime;
+	unsigned long long	st_atime_nsec;
+	unsigned long long	st_mtime;
+	unsigned long long	st_mtime_nsec;
+	unsigned long long	st_ctime;
+	unsigned long long	st_ctime_nsec;
+	long long		__unused[3];
+};
+
+/* We don't need to memset the whole thing just to initialize the padding */
+#define INIT_STRUCT_STAT_PADDING(st) do {	\
+	st.__pad0 = 0;				\
+	st.__unused[0] = 0;			\
+	st.__unused[1] = 0;			\
+	st.__unused[2] = 0;			\
+} while (0)
+
+#endif
+
 #endif /* _ASM_X86_STAT_H */
diff --git a/arch/xtensa/include/uapi/asm/stat.h b/arch/xtensa/include/uapi/asm/stat.h
index c4992038cee0..8d9c1d9d82d0 100644
--- a/arch/xtensa/include/uapi/asm/stat.h
+++ b/arch/xtensa/include/uapi/asm/stat.h
@@ -11,6 +11,8 @@
 #ifndef _XTENSA_STAT_H
 #define _XTENSA_STAT_H
 
+#include <asm-generic/kernel_stat.h>
+
 #define STAT_HAVE_NSEC 1
 
 struct stat {
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 76d1e38aabe1..71b574b0365e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -44,8 +44,6 @@ struct semaphore;
 struct sembuf;
 struct shmid_ds;
 struct sockaddr;
-struct stat;
-struct stat64;
 struct statfs;
 struct statfs64;
 struct __sysctl_args;
@@ -79,6 +77,7 @@ union bpf_attr;
 #include <linux/quota.h>
 #include <linux/key.h>
 #include <trace/syscall.h>
+#include <linux/stat.h>
 
 /*
  * __MAP - apply a macro to syscall arguments
@@ -405,10 +404,10 @@ asmlinkage long sys_lstat(const char __user *filename,
 asmlinkage long sys_fstat(unsigned int fd,
 			struct __old_kernel_stat __user *statbuf);
 asmlinkage long sys_newstat(const char __user *filename,
-				struct stat __user *statbuf);
+				struct __kernel_stat __user *statbuf);
 asmlinkage long sys_newlstat(const char __user *filename,
-				struct stat __user *statbuf);
-asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf);
+				struct __kernel_stat __user *statbuf);
+asmlinkage long sys_newfstat(unsigned int fd, struct __kernel_stat __user *statbuf);
 asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf);
 #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
 asmlinkage long sys_stat64(const char __user *filename,
@@ -774,7 +773,7 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
 asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
 			   umode_t mode);
 asmlinkage long sys_newfstatat(int dfd, const char __user *filename,
-			       struct stat __user *statbuf, int flag);
+			       struct __kernel_stat __user *statbuf, int flag);
 asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
 			       int bufsiz);
 asmlinkage long sys_utimensat(int dfd, const char __user *filename,
diff --git a/include/uapi/asm-generic/kernel_stat.h b/include/uapi/asm-generic/kernel_stat.h
new file mode 100644
index 000000000000..d1db22583046
--- /dev/null
+++ b/include/uapi/asm-generic/kernel_stat.h
@@ -0,0 +1,36 @@
+#ifndef __ASM_GENERIC_KERNEL_STAT_H
+#define __ASM_GENERIC_KERNEL_STAT_H
+
+/*
+ * The new structure that works on both 32-bit and 64-bit and survives y2038
+ * The layout matches 'struct stat' from asm-generic/stat.h on 64-bit
+ * architecture, but is identical on 32-bit architectures and uses 64-bit
+ * st_?time members so we don't wrap around in 2038.
+ */
+
+#ifndef __kernel_stat
+struct __kernel_stat {
+	unsigned long long st_dev;	/* Device.  */
+	unsigned long long st_ino;	/* File serial number.  */
+	unsigned int	   st_mode;	/* File mode.  */
+	unsigned int	   st_nlink;	/* Link count.  */
+	unsigned int	   st_uid;	/* User ID of the file's owner.  */
+	unsigned int	   st_gid;	/* Group ID of the file's group. */
+	unsigned long long st_rdev;	/* Device number, if device.  */
+	unsigned long long __pad1;
+	long long	   st_size;	/* Size of file, in bytes.  */
+	int		   st_blksize;	/* Optimal block size for I/O.  */
+	int		   __pad2;
+	long long	   st_blocks;	/* Number 512-byte blocks allocated. */
+	long long	   st_atime;	/* Time of last access.  */
+	unsigned long long st_atime_nsec;
+	long long	   st_mtime;	/* Time of last modification.  */
+	unsigned long long st_mtime_nsec;
+	long long	   st_ctime;	/* Time of last status change.  */
+	unsigned long long st_ctime_nsec;
+	unsigned int	   __unused4;
+	unsigned int	   __unused5;
+};
+#endif
+
+#endif /* __ASM_GENERIC_KERNEL_STAT_H */
diff --git a/include/uapi/asm-generic/stat.h b/include/uapi/asm-generic/stat.h
index bd8cad21998e..64c32ba7c1a9 100644
--- a/include/uapi/asm-generic/stat.h
+++ b/include/uapi/asm-generic/stat.h
@@ -8,15 +8,17 @@
  *
  * stat64 is copied from powerpc64, with explicit padding added.
  * stat is the same structure layout on 64-bit, without the 'long long'
- * types.
+ * types. Unfortunately, we started out using '32-bit st_*time here,
+ * which was a huge mistake.
  *
- * By convention, 64 bit architectures use the stat interface, while
- * 32 bit architectures use the stat64 interface. Note that we don't
- * provide an __old_kernel_stat here, which new architecture should
- * not have to start with.
+ * New architectures use only the __kernel_stat interface with
+ * 'sys_newfstatat', everything else is provided for backwards
+ * compatibility. Note that we don't provide an __old_kernel_stat here,
+ * which new architecture should not have to start with.
  */
 
 #include <asm/bitsperlong.h>
+#include <asm-generic/kernel_stat.h>
 
 #define STAT_HAVE_NSEC 1
 
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 10/19] y2038: use __kernel_stat for sys_newstat syscalls
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (8 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 09/19] y2038: introduce struct __kernel_stat Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 11/19] y2038: introduce and use struct __kernel_rusage Arnd Bergmann
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This moves over the sys_new{stat,lstat,fstat,fstatat} system calls
to use the newly introduced __kernel_stat. On all 64-bit architectures,
the layout is the same as 'struct stat', so nothing changes.

On 32-bit architectures, we use a trick to '#define __kernel_stat stat'
as long as CONFIG_COMPAT_TIME is not set, and hide the new definitions
from the kernel as long as this is the case, so the behavior does not
change until we change over the architectures individually to use
compat_sys_stat() in place of sys_stat() so we can reuse the sys_stat()
implementation for the new structure.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 fs/stat.c            | 12 ++++++------
 include/linux/stat.h |  3 +++
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/fs/stat.c b/fs/stat.c
index cccc1aab9a8b..12efbdd258fc 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -226,9 +226,9 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, stat
 #  define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
 #endif
 
-static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
+static int cp_new_stat(struct kstat *stat, struct __kernel_stat __user *statbuf)
 {
-	struct stat tmp;
+	struct __kernel_stat tmp;
 
 	if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
 		return -EOVERFLOW;
@@ -264,7 +264,7 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
 }
 
 SYSCALL_DEFINE2(newstat, const char __user *, filename,
-		struct stat __user *, statbuf)
+		struct __kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
 	int error = vfs_stat(filename, &stat);
@@ -275,7 +275,7 @@ SYSCALL_DEFINE2(newstat, const char __user *, filename,
 }
 
 SYSCALL_DEFINE2(newlstat, const char __user *, filename,
-		struct stat __user *, statbuf)
+		struct __kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
 	int error;
@@ -289,7 +289,7 @@ SYSCALL_DEFINE2(newlstat, const char __user *, filename,
 
 #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
 SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
-		struct stat __user *, statbuf, int, flag)
+		struct __kernel_stat __user *, statbuf, int, flag)
 {
 	struct kstat stat;
 	int error;
@@ -301,7 +301,7 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
 }
 #endif
 
-SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
+SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct __kernel_stat __user *, statbuf)
 {
 	struct kstat stat;
 	int error = vfs_fstat(fd, &stat);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 075cb0c7eb2a..9efc32774e98 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -1,6 +1,9 @@
 #ifndef _LINUX_STAT_H
 #define _LINUX_STAT_H
 
+#ifndef CONFIG_COMPAT_TIME
+#define __kernel_stat stat
+#endif
 
 #include <asm/stat.h>
 #include <uapi/linux/stat.h>
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 11/19] y2038: introduce and use struct __kernel_rusage
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (9 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 10/19] y2038: use __kernel_stat for sys_newstat syscalls Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 12/19] y2038: add compat_{get,put}_timespec64 Arnd Bergmann
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

'struct rusage' is not compatible with user space that defines time_t
as 64-bit. While there will never be an overflow of the timeval
members in this structure, the current definition breaks any program
that relies on the member to be a timeval.

This introduces a new struct __kernel_rusage that is defined to match
the 64-bit version of struct rusage. 32-bit architectures that use
CONFIG_COMPAT_TIME can then use compat_sys_getrusage() etc to get
the original structure, while the normal sys_getrusage() function
will provide the new layout in both native and compat32 mode.

On 32-bit architectures that do not set CONFIG_COMPAT_TIME, as well
as all 64-bit architectures, this patch is intented to have no
user-visible impact.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/alpha/kernel/osf_sys.c   |  4 ++--
 include/linux/compat_time.h   |  3 +--
 include/linux/resource.h      |  8 ++++++--
 include/linux/syscalls.h      |  7 +++----
 include/uapi/linux/resource.h | 32 ++++++++++++++++++++++++++++++++
 kernel/compat.c               | 42 +++++++++++++++++++++++++++++++++++++-----
 kernel/exit.c                 |  6 +++---
 kernel/sys.c                  | 23 ++++++++++++++---------
 8 files changed, 98 insertions(+), 27 deletions(-)

diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index e51f578636a5..6824e68d32ad 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1166,7 +1166,7 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
 SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
 		struct rusage32 __user *, ur)
 {
-	struct rusage r;
+	struct __kernel_rusage r;
 	long ret, err;
 	unsigned int status = 0;
 	mm_segment_t old_fs;
@@ -1178,7 +1178,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
 		
 	set_fs (KERNEL_DS);
 	ret = sys_wait4(pid, (unsigned int __user *) &status, options,
-			(struct rusage __user *) &r);
+			(struct __kernel_rusage __user *) &r);
 	set_fs (old_fs);
 
 	if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
index 789b6415e90e..e3b43bd79801 100644
--- a/include/linux/compat_time.h
+++ b/include/linux/compat_time.h
@@ -141,8 +141,7 @@ struct compat_rusage {
 	compat_long_t	ru_nivcsw;
 };
 
-struct rusage;
-extern int put_compat_rusage(const struct rusage *,
+extern int put_compat_rusage(const struct __kernel_rusage *,
 			     struct compat_rusage __user *);
 
 static inline int compat_timeval_compare(struct compat_timeval *lhs,
diff --git a/include/linux/resource.h b/include/linux/resource.h
index 5bc3116e649c..8cdecf204607 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -1,12 +1,16 @@
 #ifndef _LINUX_RESOURCE_H
 #define _LINUX_RESOURCE_H
 
-#include <uapi/linux/resource.h>
+#ifndef CONFIG_COMPAT_TIME
+#define __kernel_rusage rusage
+#endif
 
+#include <uapi/linux/resource.h>
 
 struct task_struct;
 
-int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
+int getrusage(struct task_struct *p, int who,
+	      struct __kernel_rusage __user *ru);
 int do_prlimit(struct task_struct *tsk, unsigned int resource,
 		struct rlimit *new_rlim, struct rlimit *old_rlim);
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 71b574b0365e..f3fdc312627b 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -36,7 +36,6 @@ struct old_utsname;
 struct pollfd;
 struct rlimit;
 struct rlimit64;
-struct rusage;
 struct sched_param;
 struct sched_attr;
 struct sel_arg_struct;
@@ -325,10 +324,10 @@ asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd,
 asmlinkage long sys_exit(int error_code);
 asmlinkage long sys_exit_group(int error_code);
 asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
-				int options, struct rusage __user *ru);
+				int options, struct __kernel_rusage __user *ru);
 asmlinkage long sys_waitid(int which, pid_t pid,
 			   struct siginfo __user *infop,
-			   int options, struct rusage __user *ru);
+			   int options, struct __kernel_rusage __user *ru);
 asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);
 asmlinkage long sys_set_tid_address(int __user *tidptr);
 asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
@@ -650,7 +649,7 @@ asmlinkage long sys_setrlimit(unsigned int resource,
 asmlinkage long sys_prlimit64(pid_t pid, unsigned int resource,
 				const struct rlimit64 __user *new_rlim,
 				struct rlimit64 __user *old_rlim);
-asmlinkage long sys_getrusage(int who, struct rusage __user *ru);
+asmlinkage long sys_getrusage(int who, struct __kernel_rusage __user *ru);
 asmlinkage long sys_umask(int mask);
 
 asmlinkage long sys_msgget(key_t key, int msgflg);
diff --git a/include/uapi/linux/resource.h b/include/uapi/linux/resource.h
index 36fb3b5fb181..c4f3ba44db00 100644
--- a/include/uapi/linux/resource.h
+++ b/include/uapi/linux/resource.h
@@ -39,6 +39,38 @@ struct	rusage {
 	__kernel_long_t	ru_nivcsw;	/* involuntary " */
 };
 
+
+/*
+ * __kernel_rusage replaces rusage, and matches the layout of 64-bit rusage
+ * on both 32-bit and 64-bit machines, to let 32-bit user space migrate to
+ * 64-bit tv_sec.
+ */
+#ifndef __kernel_rusage
+struct __kernel_rusage_timeval {
+	__s64	tv_sec;
+	__s64	tv_usec;
+};
+
+struct	__kernel_rusage {
+	struct __kernel_rusage_timeval ru_utime; /* user time used */
+	struct __kernel_rusage_timeval ru_stime; /* system time used */
+	__s64	ru_maxrss;	/* maximum resident set size */
+	__s64	ru_ixrss;	/* integral shared memory size */
+	__s64	ru_idrss;	/* integral unshared data size */
+	__s64	ru_isrss;	/* integral unshared stack size */
+	__s64	ru_minflt;	/* page reclaims */
+	__s64	ru_majflt;	/* page faults */
+	__s64	ru_nswap;	/* swaps */
+	__s64	ru_inblock;	/* block input operations */
+	__s64	ru_oublock;	/* block output operations */
+	__s64	ru_msgsnd;	/* messages sent */
+	__s64	ru_msgrcv;	/* messages received */
+	__s64	ru_nsignals;	/* signals received */
+	__s64	ru_nvcsw;	/* voluntary context switches */
+	__s64	ru_nivcsw;	/* involuntary " */
+};
+#endif
+
 struct rlimit {
 	__kernel_ulong_t	rlim_cur;
 	__kernel_ulong_t	rlim_max;
diff --git a/kernel/compat.c b/kernel/compat.c
index 03bb63995027..e56ee6a23c0f 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -517,7 +517,7 @@ COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
 #endif
 
 #ifdef CONFIG_COMPAT_TIME
-int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
+int put_compat_rusage(const struct __kernel_rusage *r, struct compat_rusage __user *ru)
 {
 	if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
 	    __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
@@ -551,7 +551,7 @@ COMPAT_SYSCALL_DEFINE4(wait4,
 	if (!ru) {
 		return sys_wait4(pid, stat_addr, options, NULL);
 	} else {
-		struct rusage r;
+		struct __kernel_rusage r;
 		int ret;
 		unsigned int status;
 		mm_segment_t old_fs = get_fs();
@@ -560,7 +560,7 @@ COMPAT_SYSCALL_DEFINE4(wait4,
 		ret = sys_wait4(pid,
 				(stat_addr ?
 				 (unsigned int __user *) &status : NULL),
-				options, (struct rusage __user *) &r);
+				options, (struct __kernel_rusage __user *) &r);
 		set_fs (old_fs);
 
 		if (ret > 0) {
@@ -579,7 +579,7 @@ COMPAT_SYSCALL_DEFINE5(waitid,
 		struct compat_rusage __user *, uru)
 {
 	siginfo_t info;
-	struct rusage ru;
+	struct __kernel_rusage ru;
 	long ret;
 	mm_segment_t old_fs = get_fs();
 
@@ -587,7 +587,7 @@ COMPAT_SYSCALL_DEFINE5(waitid,
 
 	set_fs(KERNEL_DS);
 	ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
-			 uru ? (struct rusage __user *)&ru : NULL);
+			 uru ? (struct __kernel_rusage __user *)&ru : NULL);
 	set_fs(old_fs);
 
 	if ((ret < 0) || (info.si_signo == 0))
@@ -610,6 +610,38 @@ COMPAT_SYSCALL_DEFINE5(waitid,
 #endif
 
 #ifdef CONFIG_COMPAT
+COMPAT_SYSCALL_DEFINE5(waitid_time64,
+		int, which, compat_pid_t, pid,
+		struct compat_siginfo __user *, uinfo, int, options,
+		struct compat_rusage __user *, uru)
+{
+	siginfo_t info;
+	struct __kernel_rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	memset(&info, 0, sizeof(info));
+
+	set_fs(KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
+			 uru ? (struct __kernel_rusage __user *)&ru : NULL);
+	set_fs(old_fs);
+
+	if ((ret < 0) || (info.si_signo == 0))
+		return ret;
+
+	if (uru) {
+		/* sys_waitid() overwrites everything in ru */
+		ret = copy_to_user(uru, &ru, sizeof(ru));
+		if (ret)
+			return -EFAULT;
+	}
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
+
 static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
 				    unsigned len, struct cpumask *new_mask)
 {
diff --git a/kernel/exit.c b/kernel/exit.c
index 22fcc05dec40..bf2de12e6ae1 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -894,7 +894,7 @@ struct wait_opts {
 
 	struct siginfo __user	*wo_info;
 	int __user		*wo_stat;
-	struct rusage __user	*wo_rusage;
+	struct __kernel_rusage __user *wo_rusage;
 
 	wait_queue_t		child_wait;
 	int			notask_error;
@@ -1514,7 +1514,7 @@ end:
 }
 
 SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
-		infop, int, options, struct rusage __user *, ru)
+		infop, int, options, struct __kernel_rusage __user *, ru)
 {
 	struct wait_opts wo;
 	struct pid *pid = NULL;
@@ -1582,7 +1582,7 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
 }
 
 SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
-		int, options, struct rusage __user *, ru)
+		int, options, struct __kernel_rusage __user *, ru)
 {
 	struct wait_opts wo;
 	struct pid *pid = NULL;
diff --git a/kernel/sys.c b/kernel/sys.c
index a4e372b798a5..e578f33a286e 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1529,7 +1529,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
  *
  */
 
-static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
+static void accumulate_thread_rusage(struct task_struct *t, struct __kernel_rusage *r)
 {
 	r->ru_nvcsw += t->nvcsw;
 	r->ru_nivcsw += t->nivcsw;
@@ -1539,12 +1539,13 @@ static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
 	r->ru_oublock += task_io_get_oublock(t);
 }
 
-static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+static void k_getrusage(struct task_struct *p, int who, struct __kernel_rusage *r)
 {
 	struct task_struct *t;
 	unsigned long flags;
 	cputime_t tgutime, tgstime, utime, stime;
 	unsigned long maxrss = 0;
+	struct timeval tv;
 
 	memset((char *)r, 0, sizeof (*r));
 	utime = stime = 0;
@@ -1599,8 +1600,12 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 	unlock_task_sighand(p, &flags);
 
 out:
-	cputime_to_timeval(utime, &r->ru_utime);
-	cputime_to_timeval(stime, &r->ru_stime);
+	cputime_to_timeval(utime, &tv);
+	r->ru_utime.tv_sec = tv.tv_sec;
+	r->ru_utime.tv_usec = tv.tv_usec;
+	cputime_to_timeval(stime, &tv);
+	r->ru_stime.tv_sec = tv.tv_sec;
+	r->ru_stime.tv_usec = tv.tv_usec;
 
 	if (who != RUSAGE_CHILDREN) {
 		struct mm_struct *mm = get_task_mm(p);
@@ -1613,15 +1618,15 @@ out:
 	r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
 }
 
-int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+int getrusage(struct task_struct *p, int who, struct __kernel_rusage __user *ru)
 {
-	struct rusage r;
+	struct __kernel_rusage r;
 
 	k_getrusage(p, who, &r);
 	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
-SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
+SYSCALL_DEFINE2(getrusage, int, who, struct __kernel_rusage __user *, ru)
 {
 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
 	    who != RUSAGE_THREAD)
@@ -1629,10 +1634,10 @@ SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
 	return getrusage(current, who, ru);
 }
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_COMPAT_TIME
 COMPAT_SYSCALL_DEFINE2(getrusage, int, who, struct compat_rusage __user *, ru)
 {
-	struct rusage r;
+	struct __kernel_rusage r;
 
 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
 	    who != RUSAGE_THREAD)
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 12/19] y2038: add compat_{get,put}_timespec64
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (10 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 11/19] y2038: introduce and use struct __kernel_rusage Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 13/19] y2038: add compat handling for sys_semtimedop Arnd Bergmann
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

These are new helper functions that convert between a user compat_timespec
and a kernel timespec64 structure.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/compat_time.h |  2 ++
 kernel/compat.c             | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
index e3b43bd79801..d91d0d9c753b 100644
--- a/include/linux/compat_time.h
+++ b/include/linux/compat_time.h
@@ -112,6 +112,8 @@ extern int compat_get_timespec(struct timespec *, const void __user *);
 extern int compat_put_timespec(const struct timespec *, void __user *);
 extern int compat_get_timeval(struct timeval *, const void __user *);
 extern int compat_put_timeval(const struct timeval *, void __user *);
+extern int compat_get_timespec64(struct timespec64 *ts, const void __user *uts);
+extern int compat_put_timespec64(const struct timespec64 *ts, void __user *uts);
 
 /*
  * This function convert a timespec if necessary and returns a *user
diff --git a/kernel/compat.c b/kernel/compat.c
index e56ee6a23c0f..d8d0a4711cc7 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -157,6 +157,20 @@ static int __compat_put_timespec(const struct timespec *ts, struct compat_timesp
 			__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
 
+static int __compat_get_timespec64(struct timespec64 *ts, const struct compat_timespec __user *cts)
+{
+	return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
+			__get_user(ts->tv_sec, &cts->tv_sec) ||
+			__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
+}
+
+static int __compat_put_timespec64(const struct timespec64 *ts, struct compat_timespec __user *cts)
+{
+	return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
+			__put_user(ts->tv_sec, &cts->tv_sec) ||
+			__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
+}
+
 int compat_get_timeval(struct timeval *tv, const void __user *utv)
 {
 	if (COMPAT_USE_64BIT_TIME)
@@ -193,6 +207,24 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
 }
 EXPORT_SYMBOL_GPL(compat_put_timespec);
 
+int compat_get_timespec64(struct timespec64 *ts, const void __user *uts)
+{
+	if (COMPAT_USE_64BIT_TIME)
+		return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
+	else
+		return __compat_get_timespec64(ts, uts);
+}
+EXPORT_SYMBOL_GPL(compat_get_timespec64);
+
+int compat_put_timespec64(const struct timespec64 *ts, void __user *uts)
+{
+	if (COMPAT_USE_64BIT_TIME)
+		return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
+	else
+		return __compat_put_timespec64(ts, uts);
+}
+EXPORT_SYMBOL_GPL(compat_put_timespec64);
+
 #ifdef CONFIG_COMPAT
 int compat_convert_timespec(struct timespec __user **kts,
 			    const void __user *cts)
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 13/19] y2038: add compat handling for sys_semtimedop
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (11 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 12/19] y2038: add compat_{get,put}_timespec64 Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-15 22:46   ` Thomas Gleixner
  2015-05-06 16:30 ` [PATCH 14/19] y2038: use __kernel_timespec for sys_mq_timed{send,receive} Arnd Bergmann
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This moves the compat_sys_semtimedop function to ipc/sem.c so it
can be shared with 32-bit architectures efficiently. Instead of
copying the timespec back to user space, we take a shortcut and
pass the jiffies value to the low-level implementation directly.

The native sys_semtimedop() function is modified to take a
__kernel_timespec structure, which will be based on a 64-bit
time_t in the future.

There is a small API change here: if multiple errors are present,
and the timespec argument is invalid (bad pointer or bad tv_nsec),
we now return that error before checking any of the other
error conditions. If that is a problem, we need a more sophisticated
approach.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/syscalls.h |  2 +-
 ipc/compat.c             | 10 --------
 ipc/sem.c                | 60 ++++++++++++++++++++++++++++++++++--------------
 ipc/syscall.c            |  7 ++++++
 4 files changed, 51 insertions(+), 28 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index f3fdc312627b..c2a70a8f907d 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -665,7 +665,7 @@ asmlinkage long sys_semop(int semid, struct sembuf __user *sops,
 asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg);
 asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
 				unsigned nsops,
-				const struct timespec __user *timeout);
+				const struct __kernel_timespec __user *timeout);
 asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg);
 asmlinkage long sys_shmget(key_t key, size_t size, int flag);
 asmlinkage long sys_shmdt(char __user *shmaddr);
diff --git a/ipc/compat.c b/ipc/compat.c
index 9b3c85f8a538..2bbdb093d1be 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -745,13 +745,3 @@ COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
 	}
 	return err;
 }
-
-COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
-		       unsigned, nsops,
-		       const struct compat_timespec __user *, timeout)
-{
-	struct timespec __user *ts64;
-	if (compat_convert_timespec(&ts64, timeout))
-		return -EFAULT;
-	return sys_semtimedop(semid, tsems, nsops, ts64);
-}
diff --git a/ipc/sem.c b/ipc/sem.c
index d1a6edd17eba..a6ff6754651c 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -72,6 +72,7 @@
  *   The worst-case behavior is nevertheless O(N^2) for N wakeups.
  */
 
+#include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -1779,8 +1780,9 @@ static int get_queue_result(struct sem_queue *q)
 	return error;
 }
 
-SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
-		unsigned, nsops, const struct timespec __user *, timeout)
+static long semtimedop(int semid, struct sembuf __user * tsops,
+		       unsigned nsops, unsigned long jiffies_left,
+		       bool timeout)
 {
 	int error = -EINVAL;
 	struct sem_array *sma;
@@ -1789,7 +1791,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 	struct sem_undo *un;
 	int undos = 0, alter = 0, max, locknum;
 	struct sem_queue queue;
-	unsigned long jiffies_left = 0;
 	struct ipc_namespace *ns;
 	struct list_head tasks;
 
@@ -1808,19 +1809,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		error =  -EFAULT;
 		goto out_free;
 	}
-	if (timeout) {
-		struct timespec _timeout;
-		if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
-			error = -EFAULT;
-			goto out_free;
-		}
-		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
-			_timeout.tv_nsec >= 1000000000L) {
-			error = -EINVAL;
-			goto out_free;
-		}
-		jiffies_left = timespec_to_jiffies(&_timeout);
-	}
 	max = 0;
 	for (sop = sops; sop < sops + nsops; sop++) {
 		if (sop->sem_num >= max)
@@ -2014,10 +2002,48 @@ out_free:
 	return error;
 }
 
+SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
+		unsigned, nsops,
+		const struct __kernel_timespec  __user *, timeout)
+{
+	unsigned long jiffies_left = 0;
+
+	if (timeout) {
+		struct timespec64 _timeout;
+		if (get_timespec64(&_timeout, timeout))
+			return -EFAULT;
+		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
+			_timeout.tv_nsec >= 1000000000L)
+			return -EINVAL;
+		jiffies_left = nsecs_to_jiffies(timespec64_to_ns(&_timeout));
+	}
+	return semtimedop(semid, tsops, nsops, jiffies_left, timeout);
+}
+
+#ifdef CONFIG_COMPAT_TIME
+COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
+		unsigned, nsops,
+		const struct compat_timespec  __user *, timeout)
+{
+	unsigned long jiffies_left = 0;
+
+	if (timeout) {
+		struct timespec64 _timeout;
+		if (compat_get_timespec64(&_timeout, timeout))
+			return -EFAULT;
+		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
+			_timeout.tv_nsec >= 1000000000L)
+			return -EINVAL;
+		jiffies_left = nsecs_to_jiffies(timespec64_to_ns(&_timeout));
+	}
+	return semtimedop(semid, tsops, nsops, jiffies_left, timeout);
+}
+#endif
+
 SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops)
 {
-	return sys_semtimedop(semid, tsops, nsops, NULL);
+	return semtimedop(semid, tsops, nsops, 0, 0);
 }
 
 /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 52429489cde0..d7b17355d870 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -7,6 +7,7 @@
 #include <linux/unistd.h>
 
 #ifdef __ARCH_WANT_SYS_IPC
+#include <linux/compat_time.h>
 #include <linux/errno.h>
 #include <linux/ipc.h>
 #include <linux/shm.h>
@@ -26,9 +27,15 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
 				      second, NULL);
 	case SEMTIMEDOP:
+#if defined(CONFIG_ARCH_HAS_COMPAT_TIME) && !defined(CONFIG_64BIT)
+		return compat_sys_semtimedop(first, (struct sembuf __user *)ptr,
+					     second,
+					     (const struct compat_timespec __user *)fifth);
+#else
 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
 				      second,
 				      (const struct timespec __user *)fifth);
+#endif
 
 	case SEMGET:
 		return sys_semget(first, second, third);
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 14/19] y2038: use __kernel_timespec for sys_mq_timed{send,receive}
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (12 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 13/19] y2038: add compat handling for sys_semtimedop Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-06 16:30 ` [PATCH 15/19] y2038: introduce timespec64_to_jiffies Arnd Bergmann
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This performs a complete conversion of the ipc/mqueue code to
use 64-bit time_t both internally and on the user-facing side
of 32-bit architectures that use CONFIG_COMPAT_TIME. For
compatibility with existing user space, these now use
compat_sys_mq_timed{send,receive}.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/audit.h    |  4 ++--
 include/linux/syscalls.h |  4 ++--
 ipc/mqueue.c             | 16 ++++++++--------
 kernel/audit.h           |  2 +-
 kernel/auditsc.c         | 14 +++++++-------
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index c2e7e3a83965..ab696322bb72 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -242,7 +242,7 @@ extern int __audit_socketcall(int nargs, unsigned long *args);
 extern int __audit_sockaddr(int len, void *addr);
 extern void __audit_fd_pair(int fd1, int fd2);
 extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
-extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
+extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout);
 extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
 extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
 extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
@@ -288,7 +288,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
 	if (unlikely(!audit_dummy_context()))
 		__audit_mq_open(oflag, mode, attr);
 }
-static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout)
+static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout)
 {
 	if (unlikely(!audit_dummy_context()))
 		__audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c2a70a8f907d..c3f15b5a9b79 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -675,8 +675,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
 
 asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr);
 asmlinkage long sys_mq_unlink(const char __user *name);
-asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec __user *abs_timeout);
-asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct timespec __user *abs_timeout);
+asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout);
+asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout);
 asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification);
 asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat);
 
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 3aaea7ffd077..f3f27ad1ca44 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -672,15 +672,15 @@ static void __do_notify(struct mqueue_inode_info *info)
 	wake_up(&info->wait_q);
 }
 
-static int prepare_timeout(const struct timespec __user *u_abs_timeout,
-			   ktime_t *expires, struct timespec *ts)
+static int prepare_timeout(const struct __kernel_timespec __user *u_abs_timeout,
+			   ktime_t *expires, struct timespec64 *ts)
 {
-	if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec)))
+	if (get_timespec64(ts, u_abs_timeout))
 		return -EFAULT;
 	if (!timespec_valid(ts))
 		return -EINVAL;
 
-	*expires = timespec_to_ktime(*ts);
+	*expires = timespec64_to_ktime(*ts);
 	return 0;
 }
 
@@ -953,7 +953,7 @@ static inline void pipelined_receive(struct mqueue_inode_info *info)
 
 SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
 		size_t, msg_len, unsigned int, msg_prio,
-		const struct timespec __user *, u_abs_timeout)
+		const struct __kernel_timespec __user *, u_abs_timeout)
 {
 	struct fd f;
 	struct inode *inode;
@@ -962,7 +962,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
 	struct msg_msg *msg_ptr;
 	struct mqueue_inode_info *info;
 	ktime_t expires, *timeout = NULL;
-	struct timespec ts;
+	struct timespec64 ts;
 	struct posix_msg_tree_node *new_leaf = NULL;
 	int ret = 0;
 
@@ -1073,7 +1073,7 @@ out:
 
 SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
 		size_t, msg_len, unsigned int __user *, u_msg_prio,
-		const struct timespec __user *, u_abs_timeout)
+		const struct __kernel_timespec __user *, u_abs_timeout)
 {
 	ssize_t ret;
 	struct msg_msg *msg_ptr;
@@ -1082,7 +1082,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
 	struct mqueue_inode_info *info;
 	struct ext_wait_queue wait;
 	ktime_t expires, *timeout = NULL;
-	struct timespec ts;
+	struct timespec64 ts;
 	struct posix_msg_tree_node *new_leaf = NULL;
 
 	if (u_abs_timeout) {
diff --git a/kernel/audit.h b/kernel/audit.h
index d641f9bb3ed0..b83e7aaca647 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -179,7 +179,7 @@ struct audit_context {
 			mqd_t			mqdes;
 			size_t			msg_len;
 			unsigned int		msg_prio;
-			struct timespec		abs_timeout;
+			struct timespec64	abs_timeout;
 		} mq_sendrecv;
 		struct {
 			int			oflag;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9fb9d1cb83ce..6af873dcad55 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1230,12 +1230,12 @@ static void show_special(struct audit_context *context, int *call_panic)
 	case AUDIT_MQ_SENDRECV: {
 		audit_log_format(ab,
 			"mqdes=%d msg_len=%zd msg_prio=%u "
-			"abs_timeout_sec=%ld abs_timeout_nsec=%ld",
+			"abs_timeout_sec=%lld abs_timeout_nsec=%lld",
 			context->mq_sendrecv.mqdes,
 			context->mq_sendrecv.msg_len,
 			context->mq_sendrecv.msg_prio,
-			context->mq_sendrecv.abs_timeout.tv_sec,
-			context->mq_sendrecv.abs_timeout.tv_nsec);
+			(s64)context->mq_sendrecv.abs_timeout.tv_sec,
+			(s64)context->mq_sendrecv.abs_timeout.tv_nsec);
 		break; }
 	case AUDIT_MQ_NOTIFY: {
 		audit_log_format(ab, "mqdes=%d sigev_signo=%d",
@@ -2062,15 +2062,15 @@ void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
  *
  */
 void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
-			const struct timespec *abs_timeout)
+			const struct timespec64 *abs_timeout)
 {
 	struct audit_context *context = current->audit_context;
-	struct timespec *p = &context->mq_sendrecv.abs_timeout;
+	struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
 
 	if (abs_timeout)
-		memcpy(p, abs_timeout, sizeof(struct timespec));
+		memcpy(p, abs_timeout, sizeof(struct timespec64));
 	else
-		memset(p, 0, sizeof(struct timespec));
+		memset(p, 0, sizeof(struct timespec64));
 
 	context->mq_sendrecv.mqdes = mqdes;
 	context->mq_sendrecv.msg_len = msg_len;
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 15/19] y2038: introduce timespec64_to_jiffies
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (13 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 14/19] y2038: use __kernel_timespec for sys_mq_timed{send,receive} Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-19  9:28   ` Thomas Gleixner
  2015-05-06 16:30 ` [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait Arnd Bergmann
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This is needed to convert do_sigtimedwait to use timespec64.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/jiffies.h | 13 ++++++++++++-
 kernel/time/time.c      | 11 ++---------
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index c367cbdf73ab..2aeb872f5547 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -290,7 +290,18 @@ static inline u64 jiffies_to_nsecs(const unsigned long j)
 
 extern unsigned long msecs_to_jiffies(const unsigned int m);
 extern unsigned long usecs_to_jiffies(const unsigned int u);
-extern unsigned long timespec_to_jiffies(const struct timespec *value);
+extern unsigned long __timespec_to_jiffies(unsigned long sec, long nsec);
+static inline unsigned long timespec_to_jiffies(const struct timespec *value)
+{
+	return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
+}
+
+static inline unsigned long timespec64_to_jiffies(const struct timespec64 *value)
+{
+	return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
+}
+
+
 extern void jiffies_to_timespec(const unsigned long jiffies,
 				struct timespec *value);
 extern unsigned long timeval_to_jiffies(const struct timeval *value);
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 845af1db66fa..4d96236c07b0 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -571,7 +571,7 @@ EXPORT_SYMBOL(usecs_to_jiffies);
  * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
  * value to a scaled second value.
  */
-static unsigned long
+unsigned long
 __timespec_to_jiffies(unsigned long sec, long nsec)
 {
 	nsec = nsec + TICK_NSEC - 1;
@@ -585,14 +585,7 @@ __timespec_to_jiffies(unsigned long sec, long nsec)
 		 (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
 
 }
-
-unsigned long
-timespec_to_jiffies(const struct timespec *value)
-{
-	return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
-}
-
-EXPORT_SYMBOL(timespec_to_jiffies);
+EXPORT_SYMBOL(__timespec_to_jiffies);
 
 void
 jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (14 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 15/19] y2038: introduce timespec64_to_jiffies Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-19  9:28   ` Thomas Gleixner
  2015-05-06 16:30 ` [PATCH 17/19] y2038: use __kernel_timespec in sys_futex Arnd Bergmann
                   ` (3 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

This is a straightforward conversion of the native and compat
sys_rt_sigtimedwait functions to use __kernel_timespec, so
32-bit user space can pass a 64-bit time_t into the native
syscall and use the compat syscall for the traditional 32-bit
time_t.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/signal.h   |  3 ++-
 include/linux/syscalls.h |  2 +-
 kernel/compat.c          | 10 +++++-----
 kernel/signal.c          | 13 +++++++------
 4 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/include/linux/signal.h b/include/linux/signal.h
index ab1e0392b5ac..31970d22f6c1 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -2,6 +2,7 @@
 #define _LINUX_SIGNAL_H
 
 #include <linux/list.h>
+#include <linux/time.h>
 #include <linux/bug.h>
 #include <uapi/linux/signal.h>
 
@@ -234,7 +235,7 @@ extern int do_send_sig_info(int sig, struct siginfo *info,
 extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
 extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
 extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
-				const struct timespec *);
+				const struct timespec64 *);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern void set_current_blocked(sigset_t *);
 extern void __set_current_blocked(const sigset_t *);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c3f15b5a9b79..017aa1c970e6 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -365,7 +365,7 @@ asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set,
 asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize);
 asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese,
 				siginfo_t __user *uinfo,
-				const struct timespec __user *uts,
+				const struct __kernel_timespec __user *uts,
 				size_t sigsetsize);
 asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t  pid, int sig,
 		siginfo_t __user *uinfo);
diff --git a/kernel/compat.c b/kernel/compat.c
index d8d0a4711cc7..ec09c6e1d594 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1081,7 +1081,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 {
 	compat_sigset_t s32;
 	sigset_t s;
-	struct timespec t;
+	struct timespec64 t;
 	siginfo_t info;
 	long ret;
 
@@ -1093,7 +1093,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
 	sigset_from_compat(&s, &s32);
 
 	if (uts) {
-		if (compat_get_timespec(&t, uts))
+		if (compat_get_timespec64(&t, uts))
 			return -EFAULT;
 	}
 
@@ -1115,7 +1115,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, sigset_t __user *, uthese,
 		struct compat_timespec __user *, uts, size_t, sigsetsize)
 {
 	sigset_t s;
-	struct timespec t;
+	struct timespec64 t;
 	siginfo_t info;
 	long ret;
 
@@ -1125,7 +1125,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, sigset_t __user *, uthese,
 	if (copy_from_user(&s, uthese, sizeof(sigset_t)))
 		return -EFAULT;
 	if (uts) {
-		if (compat_get_timespec(&t, uts))
+		if (compat_get_timespec64(&t, uts))
 			return -EFAULT;
 	}
 
@@ -1147,7 +1147,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait_time64, compat_sigset_t __user *, uthese,
 {
 	compat_sigset_t s32;
 	sigset_t s;
-	struct timespec t;
+	struct timespec64 t;
 	siginfo_t info;
 	long ret;
 
diff --git a/kernel/signal.c b/kernel/signal.c
index d51c5ddd855c..1f12483ddf9a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2798,7 +2798,7 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
  *  @ts: upper bound on process time suspension
  */
 int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
-			const struct timespec *ts)
+			const struct timespec64 *ts)
 {
 	struct task_struct *tsk = current;
 	long timeout = MAX_SCHEDULE_TIMEOUT;
@@ -2806,9 +2806,9 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
 	int sig;
 
 	if (ts) {
-		if (!timespec_valid(ts))
+		if (!timespec64_valid(ts))
 			return -EINVAL;
-		timeout = timespec_to_jiffies(ts);
+		timeout = timespec64_to_jiffies(ts);
 		/*
 		 * We can be close to the next tick, add another one
 		 * to ensure we will wait at least the time asked for.
@@ -2860,11 +2860,12 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
  *  @sigsetsize: size of sigset_t type
  */
 SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
-		siginfo_t __user *, uinfo, const struct timespec __user *, uts,
+		siginfo_t __user *, uinfo,
+		const struct __kernel_timespec __user *, uts,
 		size_t, sigsetsize)
 {
 	sigset_t these;
-	struct timespec ts;
+	struct timespec64 ts;
 	siginfo_t info;
 	int ret;
 
@@ -2872,7 +2873,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
 	if (sigsetsize != sizeof(sigset_t))
 		return -EINVAL;
 
-	if (copy_from_user(&these, uthese, sizeof(these)))
+	if (get_timespec64(&ts, uts))
 		return -EFAULT;
 
 	if (uts) {
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 17/19] y2038: use __kernel_timespec in sys_futex
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (15 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-15 22:53   ` Thomas Gleixner
  2015-05-19  9:24   ` Thomas Gleixner
  2015-05-06 16:30 ` [PATCH 18/19] y2038: introduce jiffies_to_timespec64 Arnd Bergmann
                   ` (2 subsequent siblings)
  19 siblings, 2 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

Conversion for sys_futex is particularly easy, we can use the unmodified
compat_sys_futex on 32-bit systems to provide compatibility for 32-bit
time_t, and change sys_futex to pass a __kernel_timespec, which matches
what future libc implementations will use as their struct timespec.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/syscalls.h |  4 ++--
 kernel/futex.c           | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 017aa1c970e6..90c3cd889387 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -331,8 +331,8 @@ asmlinkage long sys_waitid(int which, pid_t pid,
 asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);
 asmlinkage long sys_set_tid_address(int __user *tidptr);
 asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
-			struct timespec __user *utime, u32 __user *uaddr2,
-			u32 val3);
+			struct __kernel_timespec __user *utime,
+			u32 __user *uaddr2, u32 val3);
 
 asmlinkage long sys_init_module(void __user *umod, unsigned long len,
 				const char __user *uargs);
diff --git a/kernel/futex.c b/kernel/futex.c
index 2579e407ff67..199e4f94a80c 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -2970,10 +2970,10 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 
 
 SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
-		struct timespec __user *, utime, u32 __user *, uaddr2,
+		struct __kernel_timespec __user *, utime, u32 __user *, uaddr2,
 		u32, val3)
 {
-	struct timespec ts;
+	struct timespec64 ts;
 	ktime_t t, *tp = NULL;
 	u32 val2 = 0;
 	int cmd = op & FUTEX_CMD_MASK;
@@ -2981,12 +2981,12 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val,
 	if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
 		      cmd == FUTEX_WAIT_BITSET ||
 		      cmd == FUTEX_WAIT_REQUEUE_PI)) {
-		if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
+		if (get_timespec64(&ts, utime))
 			return -EFAULT;
-		if (!timespec_valid(&ts))
+		if (!timespec64_valid(&ts))
 			return -EINVAL;
 
-		t = timespec_to_ktime(ts);
+		t = timespec64_to_ktime(ts);
 		if (cmd == FUTEX_WAIT)
 			t = ktime_add_safe(ktime_get(), t);
 		tp = &t;
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 18/19] y2038: introduce jiffies_to_timespec64
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (16 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 17/19] y2038: use __kernel_timespec in sys_futex Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-19  9:25   ` Thomas Gleixner
  2015-05-06 16:30 ` [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval Arnd Bergmann
  2015-05-07  7:27 ` [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Paul Bolle
  19 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

Needed for converting sys_sched_rr_get_interval

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/jiffies.h | 12 +++++++++---
 kernel/time/time.c      |  2 +-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 2aeb872f5547..6647257fa3da 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -301,9 +301,15 @@ static inline unsigned long timespec64_to_jiffies(const struct timespec64 *value
 	return __timespec_to_jiffies(value->tv_sec, value->tv_nsec);
 }
 
-
-extern void jiffies_to_timespec(const unsigned long jiffies,
-				struct timespec *value);
+extern void jiffies_to_timespec64(const unsigned long jiffies,
+				  struct timespec64 *value);
+static inline void jiffies_to_timespec(const unsigned long jiffies,
+				       struct timespec *value)
+{
+	struct timespec64 ts64;
+	jiffies_to_timespec64(jiffies, &ts64);
+	*value = timespec64_to_timespec(ts64);
+}
 extern unsigned long timeval_to_jiffies(const struct timeval *value);
 extern void jiffies_to_timeval(const unsigned long jiffies,
 			       struct timeval *value);
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 4d96236c07b0..5e71dbd36fff 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -588,7 +588,7 @@ __timespec_to_jiffies(unsigned long sec, long nsec)
 EXPORT_SYMBOL(__timespec_to_jiffies);
 
 void
-jiffies_to_timespec(const unsigned long jiffies, struct timespec *value)
+jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value)
 {
 	/*
 	 * Convert jiffies to nanoseconds and separate with
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (17 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 18/19] y2038: introduce jiffies_to_timespec64 Arnd Bergmann
@ 2015-05-06 16:30 ` Arnd Bergmann
  2015-05-19  9:27   ` Thomas Gleixner
  2015-05-07  7:27 ` [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Paul Bolle
  19 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-06 16:30 UTC (permalink / raw)
  To: y2038
  Cc: baolin.wang, tglx, albert.aribaud, john.stultz, bamvor.zhangjian,
	ruchandani.tina, linux-api, linux-kernel, libc-alpha,
	Arnd Bergmann

sys_sched_rr_get_interval is easily converted to use __kernel_timespec,
by changing the function prototype. In order to allow compat handling
on 32-bit architectures, we also move compat_sys_sched_getaffinity
into the same file and unify the implementation, which avoids converting
the structure multiple times.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 include/linux/syscalls.h |  2 +-
 kernel/compat.c          | 20 --------------------
 kernel/sched/core.c      | 35 ++++++++++++++++++++++++++++-------
 3 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 90c3cd889387..ce41abb4cd0a 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -305,7 +305,7 @@ asmlinkage long sys_sched_yield(void);
 asmlinkage long sys_sched_get_priority_max(int policy);
 asmlinkage long sys_sched_get_priority_min(int policy);
 asmlinkage long sys_sched_rr_get_interval(pid_t pid,
-					struct timespec __user *interval);
+				struct __kernel_timespec __user *interval);
 asmlinkage long sys_setpriority(int which, int who, int niceval);
 asmlinkage long sys_getpriority(int which, int who);
 
diff --git a/kernel/compat.c b/kernel/compat.c
index ec09c6e1d594..f6d17f06ec3d 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1288,27 +1288,7 @@ COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
 	return sys_migrate_pages(pid, nr_bits + 1, old, new);
 }
 #endif
-#endif
-
-#ifdef CONFIG_COMPAT_TIME
-COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval,
-		       compat_pid_t, pid,
-		       struct compat_timespec __user *, interval)
-{
-	struct timespec t;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
-	set_fs(old_fs);
-	if (compat_put_timespec(&t, interval))
-		return -EFAULT;
-	return ret;
-}
-#endif
 
-#ifdef CONFIG_COMPAT
 /*
  * Allocate user-space memory for the duration of a single system call,
  * in order to marshall parameters inside a compat thunk.
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index fe22f7510bce..498ab3ab46dc 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -35,6 +35,8 @@
 #include <asm/mmu_context.h>
 #include <linux/interrupt.h>
 #include <linux/capability.h>
+#include <linux/compat.h>
+#include <linux/compat_time.h>
 #include <linux/completion.h>
 #include <linux/kernel_stat.h>
 #include <linux/debug_locks.h>
@@ -4468,15 +4470,13 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
  * Return: On success, 0 and the timeslice is in @interval. Otherwise,
  * an error code.
  */
-SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
-		struct timespec __user *, interval)
+static int sched_rr_get_interval(pid_t pid, struct timespec64 *t)
 {
 	struct task_struct *p;
 	unsigned int time_slice;
 	unsigned long flags;
 	struct rq *rq;
 	int retval;
-	struct timespec t;
 
 	if (pid < 0)
 		return -EINVAL;
@@ -4497,16 +4497,37 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 		time_slice = p->sched_class->get_rr_interval(rq, p);
 	task_rq_unlock(rq, p, &flags);
 
-	rcu_read_unlock();
-	jiffies_to_timespec(time_slice, &t);
-	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
-	return retval;
+	jiffies_to_timespec64(time_slice, t);
 
 out_unlock:
 	rcu_read_unlock();
 	return retval;
 }
 
+SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
+		struct __kernel_timespec __user *, interval)
+{
+	struct timespec64 t;
+	int ret = sched_rr_get_interval(pid, &t);
+	if (ret)
+		return ret;
+
+	return put_timespec64(&t, interval);
+}
+
+#ifdef CONFIG_COMPAT_TIME
+COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, compat_pid_t, pid,
+		       struct compat_timespec __user *, interval)
+{
+	struct timespec64 t;
+	int ret = sched_rr_get_interval(pid, &t);
+	if (ret)
+		return ret;
+
+	return compat_put_timespec64(&t, interval);
+}
+#endif
+
 static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
 
 void sched_show_task(struct task_struct *p)
-- 
2.1.0.rc2


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/19] converting system calls to 64-bit time_t, part 1
  2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
                   ` (18 preceding siblings ...)
  2015-05-06 16:30 ` [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval Arnd Bergmann
@ 2015-05-07  7:27 ` Paul Bolle
  2015-05-07  7:39   ` Paul Bolle
  19 siblings, 1 reply; 35+ messages in thread
From: Paul Bolle @ 2015-05-07  7:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, tglx, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 2015-05-06 at 18:30 +0200, Arnd Bergmann wrote:
> * After all system calls are converted, we can change one architecture
>   at a time to select ARCH_HAS_COMPAT_TIME, and modify its system
>   call table accordingly. In this version, I do it for ARM32, x86-32,
>   and x86-64 for demonstration purposes.

Perhaps this was correct for your first draft. Because this series adds
ARCH_HAS_COMPAT_TIME in 04/19, but it doesn't add any selects of that
symbol, does it? As far as I can see ARCH_HAS_COMPAT_TIME simply
functions as an alias for COMPAT in this series.

> * A follow-up series changes over all other architectures.
> 
> * The last patch in the series changes the CONFIG_COMPAT_TIME
>   Kconfig symbol to be user visible. Disabling this symbol will
>   get you a kernel that intentionally breaks support for old tasks
>   in order to provide an interface that will survive 2038.

This doesn't happen in 19/19, or in any other patch in this series.
Maybe also something that has changed since the first draft.

>   This is meant mostly as a debugging help for now, to let people
>   build a y2038 safe distro, but at some point in the 2030s, we
>   should remove that option and all the compat handling.

Thanks,


Paul Bolle


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/19] converting system calls to 64-bit time_t, part 1
  2015-05-07  7:27 ` [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Paul Bolle
@ 2015-05-07  7:39   ` Paul Bolle
  2015-05-07  8:52     ` Arnd Bergmann
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Bolle @ 2015-05-07  7:39 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, tglx, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Thu, 2015-05-07 at 09:27 +0200, Paul Bolle wrote:
> On Wed, 2015-05-06 at 18:30 +0200, Arnd Bergmann wrote:
> > * After all system calls are converted, we can change one architecture
> >   at a time to select ARCH_HAS_COMPAT_TIME, and modify its system
> >   call table accordingly. In this version, I do it for ARM32, x86-32,
> >   and x86-64 for demonstration purposes.
> 
> Perhaps this was correct for your first draft. Because this series adds
> ARCH_HAS_COMPAT_TIME in 04/19, but it doesn't add any selects of that
> symbol, does it? As far as I can see ARCH_HAS_COMPAT_TIME simply
> functions as an alias for COMPAT in this series.
> 
> > * A follow-up series changes over all other architectures.
> > 
> > * The last patch in the series changes the CONFIG_COMPAT_TIME
> >   Kconfig symbol to be user visible. Disabling this symbol will
> >   get you a kernel that intentionally breaks support for old tasks
> >   in order to provide an interface that will survive 2038.
> 
> This doesn't happen in 19/19, or in any other patch in this series.
> Maybe also something that has changed since the first draft.
> 
> >   This is meant mostly as a debugging help for now, to let people
> >   build a y2038 safe distro, but at some point in the 2030s, we
> >   should remove that option and all the compat handling.

And then it occurred to me to check the y2038-syscalls git branch you
referenced. After which the above made much more sense. (Though my
remark that ARCH_HAS_COMPAT_TIME simply functions as an alias for COMPAT
also seems to hold for that branch.)


Paul Bolle


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/19] converting system calls to 64-bit time_t, part 1
  2015-05-07  7:39   ` Paul Bolle
@ 2015-05-07  8:52     ` Arnd Bergmann
  2015-05-07  9:24       ` Paul Bolle
  0 siblings, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-07  8:52 UTC (permalink / raw)
  To: Paul Bolle
  Cc: y2038, baolin.wang, tglx, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Thursday 07 May 2015 09:39:18 Paul Bolle wrote:
> On Thu, 2015-05-07 at 09:27 +0200, Paul Bolle wrote:
> > On Wed, 2015-05-06 at 18:30 +0200, Arnd Bergmann wrote:
> > > * After all system calls are converted, we can change one architecture
> > >   at a time to select ARCH_HAS_COMPAT_TIME, and modify its system
> > >   call table accordingly. In this version, I do it for ARM32, x86-32,
> > >   and x86-64 for demonstration purposes.
> > 
> > Perhaps this was correct for your first draft. Because this series adds
> > ARCH_HAS_COMPAT_TIME in 04/19, but it doesn't add any selects of that
> > symbol, does it? As far as I can see ARCH_HAS_COMPAT_TIME simply
> > functions as an alias for COMPAT in this series.

It is still the intention of the patch to add the selects in the later
patches that are required to see any benefit of the earlier patches.

ARCH_HAS_COMPAT_TIME is in the "x86: use COMPAT_SYS_TIME" and
"ARM: use CONFIG_COMPAT_TIME" patches of the full series available
on my git tree.

I realize the downsides of not posting the entire series at once
here, but it seemed better to avoid spamming everyone too much,
while I try to find out if we have agreement on the overall
strategy.

For reference, see below for the ARM patch.

> > > * A follow-up series changes over all other architectures.
> > > 
> > > * The last patch in the series changes the CONFIG_COMPAT_TIME
> > >   Kconfig symbol to be user visible. Disabling this symbol will
> > >   get you a kernel that intentionally breaks support for old tasks
> > >   in order to provide an interface that will survive 2038.
> > 
> > This doesn't happen in 19/19, or in any other patch in this series.
> > Maybe also something that has changed since the first draft.
> > 
> > >   This is meant mostly as a debugging help for now, to let people
> > >   build a y2038 safe distro, but at some point in the 2030s, we
> > >   should remove that option and all the compat handling.
> 
> And then it occurred to me to check the y2038-syscalls git branch you
> referenced. After which the above made much more sense. (Though my
> remark that ARCH_HAS_COMPAT_TIME simply functions as an alias for COMPAT
> also seems to hold for that branch.)

Right, in fact both of these happen at the end of the git tree.

	Arnd

8<-------
commit 93a8526e02b6e29888df516e5750cd6483ee4472
Author: Arnd Bergmann <arnd@arndb.de>
Date:   Fri Apr 24 17:12:08 2015 +0200

    ARM: use CONFIG_COMPAT_TIME
    
    This changes the ARM architecture to use the new compat system call
    definitions that were added in previous patches. All system calls
    that use 32-bit time_t now go through the COMPAT framework, while
    a set of 25 new system calls gets added to replace them using 64-bit
    data structures __kernel_timespec, __kernel_itimerspec,
    __kernel_rusage, __kernel_msqid_ds, __kernel_semid_ds, __kernel_shmid_ds
    and __kernel_stat.
    
    Similarly, we add all the new system calls to the arm64 compat syscall
    table.
    
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
--
 arch/arm/Kconfig                   |   1 +
 arch/arm/include/asm/unistd.h      |  11 ++--
 arch/arm/include/uapi/asm/unistd.h |  22 ++++++++
 arch/arm/kernel/calls.S            | 101 +++++++++++++++++++++++--------------
 arch/arm/kernel/sys_oabi-compat.c  |   9 ++--
 arch/arm64/include/asm/unistd32.h  |  44 ++++++++++++++++
 6 files changed, 142 insertions(+), 46 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 45df48ba0b12..491896833c76 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2,6 +2,7 @@ config ARM
 	bool
 	default y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+	select ARCH_HAS_COMPAT_TIME
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_HAVE_CUSTOM_GPIO_H
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 32640c431a08..ad7588eb9d58 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -19,7 +19,7 @@
  * This may need to be greater than __NR_last_syscall+1 in order to
  * account for the padding in the syscall table
  */
-#define __NR_syscalls  (388)
+#define __NR_syscalls  (412)
 
 /*
  * *NOTE*: This is a ghost syscall private to the kernel.  Only the
@@ -28,7 +28,9 @@
  */
 #define __ARM_NR_cmpxchg		(__ARM_NR_BASE+0x00fff0)
 
+#ifdef CONFIG_COMPAT_TIME
 #define __ARCH_WANT_STAT64
+#endif
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_GETPGRP
@@ -40,11 +42,13 @@
 #define __ARCH_WANT_SYS_OLD_SELECT
 
 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
-#define __ARCH_WANT_SYS_TIME
+#ifdef CONFIG_COMPAT_TIME
+#define __ARCH_WANT_COMPAT_SYS_TIME
 #define __ARCH_WANT_SYS_IPC
+#define __ARCH_WANT_SYS_UTIME
+#endif
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
@@ -52,6 +56,7 @@
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_NEWFSTATAT
 
 /*
  * Unimplemented (or alternatively implemented) syscalls
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index 0c3f5a0dafd3..4ea2d7312f15 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -414,6 +414,28 @@
 #define __NR_memfd_create		(__NR_SYSCALL_BASE+385)
 #define __NR_bpf			(__NR_SYSCALL_BASE+386)
 #define __NR_execveat			(__NR_SYSCALL_BASE+387)
+#define __NR_clock_gettime64		(__NR_SYSCALL_BASE+388)
+#define __NR_clock_settime64		(__NR_SYSCALL_BASE+389)
+#define __NR_clock_adjtime64		(__NR_SYSCALL_BASE+390)
+#define __NR_clock_getres64		(__NR_SYSCALL_BASE+391)
+#define __NR_clock_nanosleep64		(__NR_SYSCALL_BASE+392)
+#define __NR_timer_gettime64		(__NR_SYSCALL_BASE+393)
+#define __NR_timer_settime64		(__NR_SYSCALL_BASE+394)
+#define __NR_timerfd_gettime64		(__NR_SYSCALL_BASE+395)
+#define __NR_timerfd_settime64		(__NR_SYSCALL_BASE+396)
+#define __NR_pselect64			(__NR_SYSCALL_BASE+397)
+#define __NR_ppoll64			(__NR_SYSCALL_BASE+398)
+#define __NR_io_getevents64		(__NR_SYSCALL_BASE+399)
+#define __NR_recvmmsg64			(__NR_SYSCALL_BASE+400)
+#define __NR_semtimedop64		(__NR_SYSCALL_BASE+401)
+#define __NR_mq_timedsend64		(__NR_SYSCALL_BASE+402)
+#define __NR_mq_timedreceive64		(__NR_SYSCALL_BASE+403)
+#define __NR_utimensat64		(__NR_SYSCALL_BASE+404)
+#define __NR_newfstat64			(__NR_SYSCALL_BASE+405)
+#define __NR_newfstatat64		(__NR_SYSCALL_BASE+406)
+#define __NR_rt_sigtimedwait64		(__NR_SYSCALL_BASE+407)
+#define __NR_getrusage64		(__NR_SYSCALL_BASE+408)
+#define __NR_waitid64			(__NR_SYSCALL_BASE+409)
 
 /*
  * The following SWIs are ARM private.
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 05745eb838c5..092a2e1d979c 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -22,7 +22,7 @@
 /* 10 */	CALL(sys_unlink)
 		CALL(sys_execve)
 		CALL(sys_chdir)
-		CALL(OBSOLETE(sys_time))	/* used by libc4 */
+		CALL(OBSOLETE(compat_sys_time))	/* used by libc4 */
 		CALL(sys_mknod)
 /* 15 */	CALL(sys_chmod)
 		CALL(sys_lchown16)
@@ -34,12 +34,12 @@
 		CALL(OBSOLETE(sys_oldumount))	/* used by libc4 */
 		CALL(sys_setuid16)
 		CALL(sys_getuid16)
-/* 25 */	CALL(OBSOLETE(sys_stime))
+/* 25 */	CALL(OBSOLETE(compat_sys_stime))
 		CALL(sys_ptrace)
 		CALL(OBSOLETE(sys_alarm))	/* used by libc4 */
 		CALL(sys_ni_syscall)		/* was sys_fstat */
 		CALL(sys_pause)
-/* 30 */	CALL(OBSOLETE(sys_utime))	/* used by libc4 */
+/* 30 */	CALL(OBSOLETE(compat_sys_utime))/* used by libc4 */
 		CALL(sys_ni_syscall)		/* was sys_stty */
 		CALL(sys_ni_syscall)		/* was sys_getty */
 		CALL(sys_access)
@@ -86,12 +86,12 @@
 		CALL(sys_sethostname)
 /* 75 */	CALL(sys_setrlimit)
 		CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */
-		CALL(sys_getrusage)
-		CALL(sys_gettimeofday)
-		CALL(sys_settimeofday)
+		CALL(compat_sys_getrusage)
+		CALL(compat_sys_gettimeofday)
+		CALL(compat_sys_settimeofday)
 /* 80 */	CALL(sys_getgroups16)
 		CALL(sys_setgroups16)
-		CALL(OBSOLETE(sys_old_select))	/* used by libc4 */
+		CALL(OBSOLETE(compat_sys_old_select))	/* used by libc4 */
 		CALL(sys_symlink)
 		CALL(sys_ni_syscall)		/* was sys_lstat */
 /* 85 */	CALL(sys_readlink)
@@ -113,17 +113,17 @@
 		CALL(sys_ni_syscall)		/* sys_ioperm */
 		CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall)))
 		CALL(sys_syslog)
-		CALL(sys_setitimer)
-/* 105 */	CALL(sys_getitimer)
-		CALL(sys_newstat)
-		CALL(sys_newlstat)
-		CALL(sys_newfstat)
+		CALL(compat_sys_setitimer)
+/* 105 */	CALL(compat_sys_getitimer)
+		CALL(compat_sys_newstat)
+		CALL(compat_sys_newlstat)
+		CALL(compat_sys_newfstat)
 		CALL(sys_ni_syscall)		/* was sys_uname */
 /* 110 */	CALL(sys_ni_syscall)		/* was sys_iopl */
 		CALL(sys_vhangup)
 		CALL(sys_ni_syscall)
 		CALL(OBSOLETE(sys_syscall))	/* call a syscall */
-		CALL(sys_wait4)
+		CALL(compat_sys_wait4)
 /* 115 */	CALL(sys_swapoff)
 		CALL(sys_sysinfo)
 		CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
@@ -133,7 +133,7 @@
 		CALL(sys_setdomainname)
 		CALL(sys_newuname)
 		CALL(sys_ni_syscall)		/* modify_ldt */
-		CALL(sys_adjtimex)
+		CALL(compat_sys_adjtimex)
 /* 125 */	CALL(sys_mprotect)
 		CALL(sys_sigprocmask)
 		CALL(sys_ni_syscall)		/* was sys_create_module */
@@ -151,7 +151,7 @@
 		CALL(sys_setfsgid16)
 /* 140 */	CALL(sys_llseek)
 		CALL(sys_getdents)
-		CALL(sys_select)
+		CALL(compat_sys_select)
 		CALL(sys_flock)
 		CALL(sys_msync)
 /* 145 */	CALL(sys_readv)
@@ -170,8 +170,8 @@
 		CALL(sys_sched_yield)
 		CALL(sys_sched_get_priority_max)
 /* 160 */	CALL(sys_sched_get_priority_min)
-		CALL(sys_sched_rr_get_interval)
-		CALL(sys_nanosleep)
+		CALL(compat_sys_sched_rr_get_interval)
+		CALL(compat_sys_nanosleep)
 		CALL(sys_mremap)
 		CALL(sys_setresuid16)
 /* 165 */	CALL(sys_getresuid16)
@@ -186,7 +186,7 @@
 		CALL(sys_rt_sigaction)
 /* 175 */	CALL(sys_rt_sigprocmask)
 		CALL(sys_rt_sigpending)
-		CALL(sys_rt_sigtimedwait)
+		CALL(compat_sys_rt_sigtimedwait)
 		CALL(sys_rt_sigqueueinfo)
 		CALL(sys_rt_sigsuspend)
 /* 180 */	CALL(ABI(sys_pread64, sys_oabi_pread64))
@@ -249,12 +249,12 @@
 		CALL(sys_fremovexattr)
 		CALL(sys_tkill)
 		CALL(sys_sendfile64)
-/* 240 */	CALL(sys_futex)
+/* 240 */	CALL(compat_sys_futex)
 		CALL(sys_sched_setaffinity)
 		CALL(sys_sched_getaffinity)
 		CALL(sys_io_setup)
 		CALL(sys_io_destroy)
-/* 245 */	CALL(sys_io_getevents)
+/* 245 */	CALL(compat_sys_io_getevents)
 		CALL(sys_io_submit)
 		CALL(sys_io_cancel)
 		CALL(sys_exit_group)
@@ -267,29 +267,29 @@
 /* 255 */	CALL(sys_ni_syscall)	/* sys_get_thread_area */
 		CALL(sys_set_tid_address)
 		CALL(sys_timer_create)
-		CALL(sys_timer_settime)
-		CALL(sys_timer_gettime)
+		CALL(compat_sys_timer_settime)
+		CALL(compat_sys_timer_gettime)
 /* 260 */	CALL(sys_timer_getoverrun)
 		CALL(sys_timer_delete)
-		CALL(sys_clock_settime)
-		CALL(sys_clock_gettime)
-		CALL(sys_clock_getres)
-/* 265 */	CALL(sys_clock_nanosleep)
+		CALL(compat_sys_clock_settime)
+		CALL(compat_sys_clock_gettime)
+		CALL(compat_sys_clock_getres)
+/* 265 */	CALL(compat_sys_clock_nanosleep)
 		CALL(sys_statfs64_wrapper)
 		CALL(sys_fstatfs64_wrapper)
 		CALL(sys_tgkill)
-		CALL(sys_utimes)
+		CALL(compat_sys_utimes)
 /* 270 */	CALL(sys_arm_fadvise64_64)
 		CALL(sys_pciconfig_iobase)
 		CALL(sys_pciconfig_read)
 		CALL(sys_pciconfig_write)
 		CALL(sys_mq_open)
 /* 275 */	CALL(sys_mq_unlink)
-		CALL(sys_mq_timedsend)
-		CALL(sys_mq_timedreceive)
+		CALL(compat_sys_mq_timedsend)
+		CALL(compat_sys_mq_timedreceive)
 		CALL(sys_mq_notify)
 		CALL(sys_mq_getsetattr)
-/* 280 */	CALL(sys_waitid)
+/* 280 */	CALL(compat_sys_waitid)
 		CALL(sys_socket)
 		CALL(ABI(sys_bind, sys_oabi_bind))
 		CALL(ABI(sys_connect, sys_oabi_connect))
@@ -321,7 +321,7 @@
 		CALL(sys_add_key)
 /* 310 */	CALL(sys_request_key)
 		CALL(sys_keyctl)
-		CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
+		CALL(ABI(compat_sys_semtimedop, sys_oabi_semtimedop))
 /* vserver */	CALL(sys_ni_syscall)
 		CALL(sys_ioprio_set)
 /* 315 */	CALL(sys_ioprio_get)
@@ -335,7 +335,7 @@
 		CALL(sys_mkdirat)
 		CALL(sys_mknodat)
 /* 325 */	CALL(sys_fchownat)
-		CALL(sys_futimesat)
+		CALL(compat_sys_futimesat)
 		CALL(ABI(sys_fstatat64,  sys_oabi_fstatat64))
 		CALL(sys_unlinkat)
 		CALL(sys_renameat)
@@ -344,8 +344,8 @@
 		CALL(sys_readlinkat)
 		CALL(sys_fchmodat)
 		CALL(sys_faccessat)
-/* 335 */	CALL(sys_pselect6)
-		CALL(sys_ppoll)
+/* 335 */	CALL(compat_sys_pselect6)
+		CALL(compat_sys_ppoll)
 		CALL(sys_unshare)
 		CALL(sys_set_robust_list)
 		CALL(sys_get_robust_list)
@@ -357,13 +357,13 @@
 /* 345 */	CALL(sys_getcpu)
 		CALL(sys_epoll_pwait)
 		CALL(sys_kexec_load)
-		CALL(sys_utimensat)
+		CALL(compat_sys_utimensat)
 		CALL(sys_signalfd)
 /* 350 */	CALL(sys_timerfd_create)
 		CALL(sys_eventfd)
 		CALL(sys_fallocate)
-		CALL(sys_timerfd_settime)
-		CALL(sys_timerfd_gettime)
+		CALL(compat_sys_timerfd_settime)
+		CALL(compat_sys_timerfd_gettime)
 /* 355 */	CALL(sys_signalfd4)
 		CALL(sys_eventfd2)
 		CALL(sys_epoll_create1)
@@ -374,14 +374,14 @@
 		CALL(sys_pwritev)
 		CALL(sys_rt_tgsigqueueinfo)
 		CALL(sys_perf_event_open)
-/* 365 */	CALL(sys_recvmmsg)
+/* 365 */	CALL(compat_sys_recvmmsg)
 		CALL(sys_accept4)
 		CALL(sys_fanotify_init)
 		CALL(sys_fanotify_mark)
 		CALL(sys_prlimit64)
 /* 370 */	CALL(sys_name_to_handle_at)
 		CALL(sys_open_by_handle_at)
-		CALL(sys_clock_adjtime)
+		CALL(compat_sys_clock_adjtime)
 		CALL(sys_syncfs)
 		CALL(sys_sendmmsg)
 /* 375 */	CALL(sys_setns)
@@ -397,6 +397,29 @@
 /* 385 */	CALL(sys_memfd_create)
 		CALL(sys_bpf)
 		CALL(sys_execveat)
+		CALL(sys_clock_gettime)
+		CALL(sys_clock_settime)
+/* 390 */	CALL(sys_clock_adjtime)
+		CALL(sys_clock_getres)
+		CALL(sys_clock_nanosleep)
+		CALL(sys_timer_gettime)
+		CALL(sys_timer_settime)
+/* 395 */	CALL(sys_timerfd_gettime)
+		CALL(sys_timerfd_settime)
+		CALL(sys_pselect6)
+		CALL(sys_ppoll)
+		CALL(sys_io_getevents)
+/* 400 */	CALL(sys_recvmmsg)
+		CALL(sys_semtimedop)
+		CALL(sys_mq_timedsend)
+		CALL(sys_mq_timedreceive)
+		CALL(sys_utimensat)
+/* 405 */	CALL(sys_newfstat)
+		CALL(sys_newfstatat)
+		CALL(sys_rt_sigtimedwait)
+		CALL(sys_getrusage)
+		CALL(sys_waitid)
+
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index b83f3b7737fb..2e990b564371 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -73,6 +73,7 @@
  *   wrappers provided below.
  */
 
+#include <linux/compat_time.h>
 #include <linux/syscalls.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -307,10 +308,10 @@ struct oabi_sembuf {
 asmlinkage long sys_oabi_semtimedop(int semid,
 				    struct oabi_sembuf __user *tsops,
 				    unsigned nsops,
-				    const struct timespec __user *timeout)
+				    const struct compat_timespec __user *timeout)
 {
 	struct sembuf *sops;
-	struct timespec local_timeout;
+	struct compat_timespec local_timeout;
 	long err;
 	int i;
 
@@ -336,7 +337,7 @@ asmlinkage long sys_oabi_semtimedop(int semid,
 	} else {
 		mm_segment_t fs = get_fs();
 		set_fs(KERNEL_DS);
-		err = sys_semtimedop(semid, sops, nsops, timeout);
+		err = compat_sys_semtimedop(semid, sops, nsops, timeout);
 		set_fs(fs);
 	}
 	kfree(sops);
@@ -361,7 +362,7 @@ asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
 		return  sys_oabi_semtimedop(first,
 					    (struct oabi_sembuf __user *)ptr,
 					    second,
-					    (const struct timespec __user *)fifth);
+					    (const struct compat_timespec __user *)fifth);
 	default:
 		return sys_ipc(call, first, second, third, ptr, fifth);
 	}
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index cef934a90f17..1659a0c68ea3 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -797,3 +797,47 @@ __SYSCALL(__NR_memfd_create, sys_memfd_create)
 __SYSCALL(__NR_bpf, sys_bpf)
 #define __NR_execveat 387
 __SYSCALL(__NR_execveat, compat_sys_execveat)
+#define __NR_clock_gettime64 388
+_SYSCALL(__NR_clock_gettime64, sys_clock_gettime)
+#define __NR_clock_settime64 389
+_SYSCALL(__NR_clock_settime64, sys_clock_settime)
+#define __NR_clock_adjtime64 390
+_SYSCALL(__NR_clock_adjtime64, sys_clock_adjtime)
+#define __NR_clock_getres64 391
+_SYSCALL(__NR_clock_getres64, sys_clock_getres)
+#define __NR_clock_nanosleep64 392
+_SYSCALL(__NR_clock_nanosleep64, sys_clock_nanosleep)
+#define __NR_timer_gettime64 393
+_SYSCALL(__NR_timer_gettime64, sys_timer_gettime)
+#define __NR_timer_settime64 394
+_SYSCALL(__NR_timer_settime64, sys_timer_settime)
+#define __NR_timerfd_gettime64 395
+_SYSCALL(__NR_timerfd_gettime64, sys_timerfd_gettime)
+#define __NR_timerfd_settime64 396
+_SYSCALL(__NR_timerfd_settime64, sys_timerfd_settime)
+#define __NR_pselect64 397
+_SYSCALL(__NR_pselect64, compat_sys_pselect6_time64)
+#define __NR_ppoll64 398
+_SYSCALL(__NR_ppoll64, compat_sys_ppoll_time64)
+#define __NR_io_getevents64 399
+_SYSCALL(__NR_io_getevents64, sys_io_getevents)
+#define __NR_recvmmsg64 400
+_SYSCALL(__NR_recvmmsg64, compat_sys_recvmmsg64)
+#define __NR_semtimedop64 401
+_SYSCALL(__NR_semtimedop64, sys_semtimedop)
+#define __NR_mq_timedsend64 402
+_SYSCALL(__NR_mq_timedsend64, sys_mq_timedsend)
+#define __NR_mq_timedreceive64 403
+_SYSCALL(__NR_mq_timedreceive64, sys_mq_timedreceive)
+#define __NR_utimensat64 404
+_SYSCALL(__NR_utimensat64, sys_utimensat)
+#define __NR_newfstat64 405
+_SYSCALL(__NR_newfstat64, sys_newfstat)
+#define __NR_newfstatat64 406
+_SYSCALL(__NR_newfstatat64, sys_newfstatat)
+#define __NR_rt_sigtimedwait64 407
+_SYSCALL(__NR_rt_sigtimedwait64, compat_sys_rt_sigtimedwait_time64)
+#define __NR_getrusage64 408
+_SYSCALL(__NR_getrusage64, sys_getrusage)
+#define __NR_waitid64 409
+_SYSCALL(__NR_waitid64, compat_sys_waitid_time64)


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/19] converting system calls to 64-bit time_t, part 1
  2015-05-07  8:52     ` Arnd Bergmann
@ 2015-05-07  9:24       ` Paul Bolle
  0 siblings, 0 replies; 35+ messages in thread
From: Paul Bolle @ 2015-05-07  9:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, tglx, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Thu, 2015-05-07 at 10:52 +0200, Arnd Bergmann wrote:
> On Thursday 07 May 2015 09:39:18 Paul Bolle wrote:
> I realize the downsides of not posting the entire series at once
> here, but it seemed better to avoid spamming everyone too much,
> while I try to find out if we have agreement on the overall
> strategy.

That downside is worse when people only quickly skim your message for
clues while thinking about the problem they _think_ they've spotted
(like I did).

> For reference, see below for the ARM patch.

> > And then it occurred to me to check the y2038-syscalls git branch you
> > referenced. After which the above made much more sense. (Though my
> > remark that ARCH_HAS_COMPAT_TIME simply functions as an alias for COMPAT
> > also seems to hold for that branch.)
> 
> Right, in fact both of these happen at the end of the git tree.

Still, you might consider making ARCH_HAS_COMPAT_TIME a plain bool and
adding "select ARCH_HAS_COMPAT_TIME" to the eight or so COMPAT entries.
But, clearly, I'm now wasting even more of your time by trying to save
face here.

Thanks,


Paul Bolle


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 13/19] y2038: add compat handling for sys_semtimedop
  2015-05-06 16:30 ` [PATCH 13/19] y2038: add compat handling for sys_semtimedop Arnd Bergmann
@ 2015-05-15 22:46   ` Thomas Gleixner
  2015-05-16  7:28     ` Arnd Bergmann
  2015-05-16 19:54     ` Arnd Bergmann
  0 siblings, 2 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-15 22:46 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:
> +SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
> +		unsigned, nsops,
> +		const struct __kernel_timespec  __user *, timeout)
> +{
> +	unsigned long jiffies_left = 0;
> +
> +	if (timeout) {
> +		struct timespec64 _timeout;
> +		if (get_timespec64(&_timeout, timeout))

Moo. I had to look 3 times to get not confused by the extra
underscore. What's wrong with a proper variable name which is easy to
distinguish?

> +			return -EFAULT;

> +		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
> +			_timeout.tv_nsec >= 1000000000L)
> +			return -EINVAL;

We have proper helper functions to validate time specs.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 17/19] y2038: use __kernel_timespec in sys_futex
  2015-05-06 16:30 ` [PATCH 17/19] y2038: use __kernel_timespec in sys_futex Arnd Bergmann
@ 2015-05-15 22:53   ` Thomas Gleixner
  2015-05-16  7:21     ` Thomas Gleixner
  2015-05-19  9:24   ` Thomas Gleixner
  1 sibling, 1 reply; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-15 22:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:

> Conversion for sys_futex is particularly easy, we can use the unmodified
> compat_sys_futex on 32-bit systems to provide compatibility for 32-bit
> time_t, and change sys_futex to pass a __kernel_timespec, which matches
> what future libc implementations will use as their struct timespec.

Unless I'm missing something I doubt that you get away that easy. It
works on 32bit, but not on 64 bit with 32bit app support:

Native 64bit: 	   sys_futex()
32bit timespec32:  compat_sys_futex()
32bit timespec64:  ?????

You cannot map that to sys_futex() because the pointer size differs.
 
Thanks,

	tglx

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 17/19] y2038: use __kernel_timespec in sys_futex
  2015-05-15 22:53   ` Thomas Gleixner
@ 2015-05-16  7:21     ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-16  7:21 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Sat, 16 May 2015, Thomas Gleixner wrote:
> On Wed, 6 May 2015, Arnd Bergmann wrote:
> 
> > Conversion for sys_futex is particularly easy, we can use the unmodified
> > compat_sys_futex on 32-bit systems to provide compatibility for 32-bit
> > time_t, and change sys_futex to pass a __kernel_timespec, which matches
> > what future libc implementations will use as their struct timespec.
> 
> Unless I'm missing something I doubt that you get away that easy. It
> works on 32bit, but not on 64 bit with 32bit app support:
> 
> Native 64bit: 	   sys_futex()
> 32bit timespec32:  compat_sys_futex()
> 32bit timespec64:  ?????
> 
> You cannot map that to sys_futex() because the pointer size differs.

Ignore that. You are right. Review induced brainmelt....

       tglx

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 13/19] y2038: add compat handling for sys_semtimedop
  2015-05-15 22:46   ` Thomas Gleixner
@ 2015-05-16  7:28     ` Arnd Bergmann
  2015-05-16 19:54     ` Arnd Bergmann
  1 sibling, 0 replies; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-16  7:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Saturday 16 May 2015 00:46:44 Thomas Gleixner wrote:
> On Wed, 6 May 2015, Arnd Bergmann wrote:
> > +SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
> > +             unsigned, nsops,
> > +             const struct __kernel_timespec  __user *, timeout)
> > +{
> > +     unsigned long jiffies_left = 0;
> > +
> > +     if (timeout) {
> > +             struct timespec64 _timeout;
> > +             if (get_timespec64(&_timeout, timeout))
> 
> Moo. I had to look 3 times to get not confused by the extra
> underscore. What's wrong with a proper variable name which is easy to
> distinguish?
> 
> > +                     return -EFAULT;
> 
> > +             if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
> > +                     _timeout.tv_nsec >= 1000000000L)
> > +                     return -EINVAL;
> 
> We have proper helper functions to validate time specs.

I tried to change the existing code as little as possible, but I agree
with your points here. I'll add a cleanup patch to fix the current code
before my own patches.

	Arnd

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 13/19] y2038: add compat handling for sys_semtimedop
  2015-05-15 22:46   ` Thomas Gleixner
  2015-05-16  7:28     ` Arnd Bergmann
@ 2015-05-16 19:54     ` Arnd Bergmann
  2015-05-19  9:19       ` Thomas Gleixner
  1 sibling, 1 reply; 35+ messages in thread
From: Arnd Bergmann @ 2015-05-16 19:54 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Saturday 16 May 2015 00:46:44 Thomas Gleixner wrote:
> On Wed, 6 May 2015, Arnd Bergmann wrote:
> > +SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
> > +		unsigned, nsops,
> > +		const struct __kernel_timespec  __user *, timeout)
> > +{
> > +	unsigned long jiffies_left = 0;
> > +
> > +	if (timeout) {
> > +		struct timespec64 _timeout;
> > +		if (get_timespec64(&_timeout, timeout))
> 
> Moo. I had to look 3 times to get not confused by the extra
> underscore. What's wrong with a proper variable name which is easy to
> distinguish?
> 
> > +			return -EFAULT;
> 
> > +		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
> > +			_timeout.tv_nsec >= 1000000000L)
> > +			return -EINVAL;
> 
> We have proper helper functions to validate time specs.

I ended up fixing both issues you noticed in the same patch
after all, and also simplified it slightly more.

Finally, I also noticed that I had not done a timespec64_to_jiffies()
call at the time when I wrote this patch, but it actually exists now,
so I've reordered my series and am using it in the new version, as
I should have done to start with.

	Arnd

8<----

>From e04b14d49273c27d92f1799233b82bcdafb43d9a Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Mon, 27 Apr 2015 23:30:39 +0200
Subject: [UPDATED PATCH] y2038: add compat handling for sys_semtimedop

This moves the compat_sys_semtimedop function to ipc/sem.c so it
can be shared with 32-bit architectures efficiently. Instead of
copying the timespec back to user space, we take a shortcut and
pass the kernel timespec64 value to the low-level implementation
directly.

The native sys_semtimedop() function is modified to take a
__kernel_timespec structure, which will be based on a 64-bit
time_t in the future.

There is a small API change here: if multiple errors are present,
and the timespec argument is an invalid pointer, we now return
-EFAULT before checking any of the other error conditions.
This is what the compat version has always done, but if it is a
problem, we need a more sophisticated approach.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index f3fdc312627b..c2a70a8f907d 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -665,7 +665,7 @@ asmlinkage long sys_semop(int semid, struct sembuf __user *sops,
 asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg);
 asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
 				unsigned nsops,
-				const struct timespec __user *timeout);
+				const struct __kernel_timespec __user *timeout);
 asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg);
 asmlinkage long sys_shmget(key_t key, size_t size, int flag);
 asmlinkage long sys_shmdt(char __user *shmaddr);
diff --git a/ipc/compat.c b/ipc/compat.c
index 9b3c85f8a538..2bbdb093d1be 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -745,13 +745,3 @@ COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
 	}
 	return err;
 }
-
-COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
-		       unsigned, nsops,
-		       const struct compat_timespec __user *, timeout)
-{
-	struct timespec __user *ts64;
-	if (compat_convert_timespec(&ts64, timeout))
-		return -EFAULT;
-	return sys_semtimedop(semid, tsems, nsops, ts64);
-}
diff --git a/ipc/sem.c b/ipc/sem.c
index d1a6edd17eba..84d354a34df3 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -72,6 +72,7 @@
  *   The worst-case behavior is nevertheless O(N^2) for N wakeups.
  */
 
+#include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -1779,8 +1780,8 @@ static int get_queue_result(struct sem_queue *q)
 	return error;
 }
 
-SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
-		unsigned, nsops, const struct timespec __user *, timeout)
+static long semtimedop(int semid, struct sembuf __user * tsops,
+		       unsigned nsops, struct timespec64 *timeout)
 {
 	int error = -EINVAL;
 	struct sem_array *sma;
@@ -1809,17 +1810,11 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		goto out_free;
 	}
 	if (timeout) {
-		struct timespec _timeout;
-		if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
-			error = -EFAULT;
-			goto out_free;
-		}
-		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
-			_timeout.tv_nsec >= 1000000000L) {
+		if (!timespec64_valid(timeout)) {
 			error = -EINVAL;
 			goto out_free;
 		}
-		jiffies_left = timespec_to_jiffies(&_timeout);
+		jiffies_left = timespec64_to_jiffies(timeout);
 	}
 	max = 0;
 	for (sop = sops; sop < sops + nsops; sop++) {
@@ -2014,10 +2009,36 @@ out_free:
 	return error;
 }
 
+SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
+		unsigned, nsops,
+		const struct __kernel_timespec  __user *, p)
+{
+	struct timespec64 timeout;
+
+	if (p && get_timespec64(&timeout, p))
+		return -EFAULT;
+
+	return semtimedop(semid, tsops, nsops, p ? &timeout : NULL);
+}
+
+#ifdef CONFIG_COMPAT_TIME
+COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
+		unsigned, nsops,
+		const struct compat_timespec  __user *, p)
+{
+	struct timespec64 timeout;
+
+	if (p && compat_get_timespec64(&timeout, p))
+		return -EFAULT;
+
+	return semtimedop(semid, tsops, nsops, p ? &timeout : NULL);
+}
+#endif
+
 SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops)
 {
-	return sys_semtimedop(semid, tsops, nsops, NULL);
+	return semtimedop(semid, tsops, nsops, NULL);
 }
 
 /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 52429489cde0..d7b17355d870 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -7,6 +7,7 @@
 #include <linux/unistd.h>
 
 #ifdef __ARCH_WANT_SYS_IPC
+#include <linux/compat_time.h>
 #include <linux/errno.h>
 #include <linux/ipc.h>
 #include <linux/shm.h>
@@ -26,9 +27,15 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
 				      second, NULL);
 	case SEMTIMEDOP:
+#if defined(CONFIG_ARCH_HAS_COMPAT_TIME) && !defined(CONFIG_64BIT)
+		return compat_sys_semtimedop(first, (struct sembuf __user *)ptr,
+					     second,
+					     (const struct compat_timespec __user *)fifth);
+#else
 		return sys_semtimedop(first, (struct sembuf __user *)ptr,
 				      second,
 				      (const struct timespec __user *)fifth);
+#endif
 
 	case SEMGET:
 		return sys_semget(first, second, third);


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH 13/19] y2038: add compat handling for sys_semtimedop
  2015-05-16 19:54     ` Arnd Bergmann
@ 2015-05-19  9:19       ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Sat, 16 May 2015, Arnd Bergmann wrote:
> On Saturday 16 May 2015 00:46:44 Thomas Gleixner wrote:
> > On Wed, 6 May 2015, Arnd Bergmann wrote:
> > > +SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
> > > +		unsigned, nsops,
> > > +		const struct __kernel_timespec  __user *, timeout)
> > > +{
> > > +	unsigned long jiffies_left = 0;
> > > +
> > > +	if (timeout) {
> > > +		struct timespec64 _timeout;
> > > +		if (get_timespec64(&_timeout, timeout))
> > 
> > Moo. I had to look 3 times to get not confused by the extra
> > underscore. What's wrong with a proper variable name which is easy to
> > distinguish?
> > 
> > > +			return -EFAULT;
> > 
> > > +		if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
> > > +			_timeout.tv_nsec >= 1000000000L)
> > > +			return -EINVAL;
> > 
> > We have proper helper functions to validate time specs.
> 
> I ended up fixing both issues you noticed in the same patch
> after all, and also simplified it slightly more.
> 
> Finally, I also noticed that I had not done a timespec64_to_jiffies()
> call at the time when I wrote this patch, but it actually exists now,
> so I've reordered my series and am using it in the new version, as
> I should have done to start with.

Indeed. I didn't notice either.
 
> >From e04b14d49273c27d92f1799233b82bcdafb43d9a Mon Sep 17 00:00:00 2001
> From: Arnd Bergmann <arnd@arndb.de>
> Date: Mon, 27 Apr 2015 23:30:39 +0200
> Subject: [UPDATED PATCH] y2038: add compat handling for sys_semtimedop
> 
> This moves the compat_sys_semtimedop function to ipc/sem.c so it
> can be shared with 32-bit architectures efficiently. Instead of
> copying the timespec back to user space, we take a shortcut and
> pass the kernel timespec64 value to the low-level implementation
> directly.
> 
> The native sys_semtimedop() function is modified to take a
> __kernel_timespec structure, which will be based on a 64-bit
> time_t in the future.
> 
> There is a small API change here: if multiple errors are present,
> and the timespec argument is an invalid pointer, we now return
> -EFAULT before checking any of the other error conditions.
> This is what the compat version has always done, but if it is a
> problem, we need a more sophisticated approach.

The important part of error checks is that they catch all
cases and combinations. In which order is completely irrelevant.

If something relies on the ordering of error check returns, it's
broken by definition.
 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 17/19] y2038: use __kernel_timespec in sys_futex
  2015-05-06 16:30 ` [PATCH 17/19] y2038: use __kernel_timespec in sys_futex Arnd Bergmann
  2015-05-15 22:53   ` Thomas Gleixner
@ 2015-05-19  9:24   ` Thomas Gleixner
  1 sibling, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:

> Conversion for sys_futex is particularly easy, we can use the unmodified
> compat_sys_futex on 32-bit systems to provide compatibility for 32-bit
> time_t, and change sys_futex to pass a __kernel_timespec, which matches
> what future libc implementations will use as their struct timespec.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 18/19] y2038: introduce jiffies_to_timespec64
  2015-05-06 16:30 ` [PATCH 18/19] y2038: introduce jiffies_to_timespec64 Arnd Bergmann
@ 2015-05-19  9:25   ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:

> Needed for converting sys_sched_rr_get_interval
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval
  2015-05-06 16:30 ` [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval Arnd Bergmann
@ 2015-05-19  9:27   ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:

> sys_sched_rr_get_interval is easily converted to use __kernel_timespec,
> by changing the function prototype. In order to allow compat handling
> on 32-bit architectures, we also move compat_sys_sched_getaffinity
> into the same file and unify the implementation, which avoids converting
> the structure multiple times.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait
  2015-05-06 16:30 ` [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait Arnd Bergmann
@ 2015-05-19  9:28   ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, John Stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, LKML, libc-alpha,
	Oleg Nesterov

On Wed, 6 May 2015, Arnd Bergmann wrote:

> This is a straightforward conversion of the native and compat
> sys_rt_sigtimedwait functions to use __kernel_timespec, so
> 32-bit user space can pass a 64-bit time_t into the native
> syscall and use the compat syscall for the traditional 32-bit
> time_t.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 15/19] y2038: introduce timespec64_to_jiffies
  2015-05-06 16:30 ` [PATCH 15/19] y2038: introduce timespec64_to_jiffies Arnd Bergmann
@ 2015-05-19  9:28   ` Thomas Gleixner
  0 siblings, 0 replies; 35+ messages in thread
From: Thomas Gleixner @ 2015-05-19  9:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: y2038, baolin.wang, albert.aribaud, john.stultz,
	bamvor.zhangjian, ruchandani.tina, linux-api, linux-kernel,
	libc-alpha

On Wed, 6 May 2015, Arnd Bergmann wrote:

> This is needed to convert do_sigtimedwait to use timespec64.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2015-05-19  9:28 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-06 16:30 [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Arnd Bergmann
2015-05-06 16:30 ` [PATCH 01/19] compat: remove compat_printk Arnd Bergmann
2015-05-06 16:30 ` [PATCH 02/19] initramfs: use vfs_stat/lstat directly Arnd Bergmann
2015-05-06 16:30 ` [PATCH 03/19] y2038: introduce linux/compat_time.h header Arnd Bergmann
2015-05-06 16:30 ` [PATCH 04/19] y2038: introduce CONFIG_COMPAT_TIME Arnd Bergmann
2015-05-06 16:30 ` [PATCH 05/19] y2038: make linux/compat_time.h usable on 32-bit Arnd Bergmann
2015-05-06 16:30 ` [PATCH 06/19] y2038: compile compat time code even when CONFIG_COMPAT is not set Arnd Bergmann
2015-05-06 16:30 ` [PATCH 07/19] y2038: add compat_sys_rt_sigtimedwait variants Arnd Bergmann
2015-05-06 16:30 ` [PATCH 08/19] y2038: introduce struct __kernel_timespec Arnd Bergmann
2015-05-06 16:30 ` [PATCH 09/19] y2038: introduce struct __kernel_stat Arnd Bergmann
2015-05-06 16:30 ` [PATCH 10/19] y2038: use __kernel_stat for sys_newstat syscalls Arnd Bergmann
2015-05-06 16:30 ` [PATCH 11/19] y2038: introduce and use struct __kernel_rusage Arnd Bergmann
2015-05-06 16:30 ` [PATCH 12/19] y2038: add compat_{get,put}_timespec64 Arnd Bergmann
2015-05-06 16:30 ` [PATCH 13/19] y2038: add compat handling for sys_semtimedop Arnd Bergmann
2015-05-15 22:46   ` Thomas Gleixner
2015-05-16  7:28     ` Arnd Bergmann
2015-05-16 19:54     ` Arnd Bergmann
2015-05-19  9:19       ` Thomas Gleixner
2015-05-06 16:30 ` [PATCH 14/19] y2038: use __kernel_timespec for sys_mq_timed{send,receive} Arnd Bergmann
2015-05-06 16:30 ` [PATCH 15/19] y2038: introduce timespec64_to_jiffies Arnd Bergmann
2015-05-19  9:28   ` Thomas Gleixner
2015-05-06 16:30 ` [PATCH 16/19] y2038: use __kernel_timespec in sys_rt_sigtimedwait Arnd Bergmann
2015-05-19  9:28   ` Thomas Gleixner
2015-05-06 16:30 ` [PATCH 17/19] y2038: use __kernel_timespec in sys_futex Arnd Bergmann
2015-05-15 22:53   ` Thomas Gleixner
2015-05-16  7:21     ` Thomas Gleixner
2015-05-19  9:24   ` Thomas Gleixner
2015-05-06 16:30 ` [PATCH 18/19] y2038: introduce jiffies_to_timespec64 Arnd Bergmann
2015-05-19  9:25   ` Thomas Gleixner
2015-05-06 16:30 ` [PATCH 19/19] y2038: use __kernel_timespec in sys_sched_rr_get_interval Arnd Bergmann
2015-05-19  9:27   ` Thomas Gleixner
2015-05-07  7:27 ` [PATCH 00/19] converting system calls to 64-bit time_t, part 1 Paul Bolle
2015-05-07  7:39   ` Paul Bolle
2015-05-07  8:52     ` Arnd Bergmann
2015-05-07  9:24       ` Paul Bolle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).