summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-04-19 16:27:44 +0200
committerThomas Gleixner <tglx@linutronix.de>2018-04-19 16:27:44 +0200
commit1cfd904f16740df21b2df7b41c7a0dc00cbd434c (patch)
treeaa247a7d84377f5ca089199aba609fb7ab74aa7e /include/linux
parent87ef12027b9b1dd0e0b12cf311fbcb19f9d92539 (diff)
parent01909974b41036a6a8d3907c66cc7b41c9a73da9 (diff)
Merge tag 'y2038-timekeeping' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground into timers/core
Pull y2038 timekeeping syscall changes from Arnd Bergmann: This is the first set of system call entry point changes to enable 32-bit architectures to have variants on both 32-bit and 64-bit time_t. Typically these system calls take a 'struct timespec' argument, but that structure is defined in user space by the C library and its layout will change. The kernel already supports handling the 32-bit time_t on 64-bit architectures through the CONFIG_COMPAT mechanism. As there are a total of 51 system calls suffering from this problem, reusing that mechanism on 32-bit architectures. We already have patches for most of the remaining system calls, but this set contains most of the complexity and is best tested. There was one last-minute regression that prevented it from going into 4.17, but that is fixed now. More details from Deepa's patch series description: Big picture is as per the lwn article: https://lwn.net/Articles/643234/ [2] The series is directed at converting posix clock syscalls: clock_gettime, clock_settime, clock_getres and clock_nanosleep to use a new data structure __kernel_timespec at syscall boundaries. __kernel_timespec maintains 64 bit time_t across all execution modes. vdso will be handled as part of each architecture when they enable support for 64 bit time_t. The compat syscalls are repurposed to provide backward compatibility by using them as native syscalls as well for 32 bit architectures. They will continue to use timespec at syscall boundaries. CONFIG_64_BIT_TIME controls whether the syscalls use __kernel_timespec or timespec at syscall boundaries. The series does the following: 1. Enable compat syscalls on 32 bit architectures. 2. Add a new __kernel_timespec type to be used as the data structure for all the new syscalls. 3. Add new config CONFIG_64BIT_TIME(intead of the CONFIG_COMPAT_TIME in [1] and [2] to switch to new definition of __kernel_timespec. It is the same as struct timespec otherwise. 4. Add new CONFIG_32BIT_TIME to conditionally compile compat syscalls.
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/compat.h12
-rw-r--r--include/linux/compat_time.h23
-rw-r--r--include/linux/restart_block.h7
-rw-r--r--include/linux/syscalls.h13
-rw-r--r--include/linux/time.h4
-rw-r--r--include/linux/time64.h10
6 files changed, 51 insertions, 18 deletions
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 081281ad5772..cfc1b6383ae0 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -7,8 +7,7 @@
*/
#include <linux/types.h>
-
-#ifdef CONFIG_COMPAT
+#include <linux/compat_time.h>
#include <linux/stat.h>
#include <linux/param.h> /* for HZ */
@@ -21,8 +20,11 @@
#include <linux/unistd.h>
#include <asm/compat.h>
+
+#ifdef CONFIG_COMPAT
#include <asm/siginfo.h>
#include <asm/signal.h>
+#endif
#ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
/*
@@ -83,6 +85,8 @@
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#endif /* COMPAT_SYSCALL_DEFINEx */
+#ifdef CONFIG_COMPAT
+
#ifndef compat_user_stack_pointer
#define compat_user_stack_pointer() current_user_stack_pointer()
#endif
@@ -290,8 +294,6 @@ 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 *, const void __user *);
-extern int compat_put_timespec64(const struct timespec64 *, void __user *);
extern int get_compat_itimerspec64(struct itimerspec64 *its,
const struct compat_itimerspec __user *uits);
extern int put_compat_itimerspec64(const struct itimerspec64 *its,
@@ -1016,7 +1018,9 @@ static inline struct compat_timeval ns_to_compat_timeval(s64 nsec)
#else /* !CONFIG_COMPAT */
#define is_compat_task() (0)
+#ifndef in_compat_syscall
static inline bool in_compat_syscall(void) { return false; }
+#endif
#endif /* CONFIG_COMPAT */
diff --git a/include/linux/compat_time.h b/include/linux/compat_time.h
new file mode 100644
index 000000000000..31f2774f1994
--- /dev/null
+++ b/include/linux/compat_time.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_COMPAT_TIME_H
+#define _LINUX_COMPAT_TIME_H
+
+#include <linux/types.h>
+#include <linux/time64.h>
+
+typedef s32 compat_time_t;
+
+struct compat_timespec {
+ compat_time_t tv_sec;
+ s32 tv_nsec;
+};
+
+struct compat_timeval {
+ compat_time_t tv_sec;
+ s32 tv_usec;
+};
+
+extern int compat_get_timespec64(struct timespec64 *, const void __user *);
+extern int compat_put_timespec64(const struct timespec64 *, void __user *);
+
+#endif /* _LINUX_COMPAT_TIME_H */
diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
index bcfdb918cd81..5d83d0c1d06c 100644
--- a/include/linux/restart_block.h
+++ b/include/linux/restart_block.h
@@ -7,6 +7,7 @@
#include <linux/compiler.h>
#include <linux/types.h>
+#include <linux/time64.h>
struct timespec;
struct compat_timespec;
@@ -15,9 +16,7 @@ struct pollfd;
enum timespec_type {
TT_NONE = 0,
TT_NATIVE = 1,
-#ifdef CONFIG_COMPAT
TT_COMPAT = 2,
-#endif
};
/*
@@ -40,10 +39,8 @@ struct restart_block {
clockid_t clockid;
enum timespec_type type;
union {
- struct timespec __user *rmtp;
-#ifdef CONFIG_COMPAT
+ struct __kernel_timespec __user *rmtp;
struct compat_timespec __user *compat_rmtp;
-#endif
};
u64 expires;
} nanosleep;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 70fcda1a9049..c9a2a2601852 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -536,7 +536,8 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
size_t len);
/* kernel/hrtimer.c */
-asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp);
+asmlinkage long sys_nanosleep(struct __kernel_timespec __user *rqtp,
+ struct __kernel_timespec __user *rmtp);
/* kernel/itimer.c */
asmlinkage long sys_getitimer(int which, struct itimerval __user *value);
@@ -567,14 +568,14 @@ asmlinkage long sys_timer_settime(timer_t timer_id, int flags,
struct itimerspec __user *old_setting);
asmlinkage long sys_timer_delete(timer_t timer_id);
asmlinkage long sys_clock_settime(clockid_t which_clock,
- const struct timespec __user *tp);
+ const struct __kernel_timespec __user *tp);
asmlinkage long sys_clock_gettime(clockid_t which_clock,
- struct timespec __user *tp);
+ struct __kernel_timespec __user *tp);
asmlinkage long sys_clock_getres(clockid_t which_clock,
- struct timespec __user *tp);
+ struct __kernel_timespec __user *tp);
asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
- const struct timespec __user *rqtp,
- struct timespec __user *rmtp);
+ const struct __kernel_timespec __user *rqtp,
+ struct __kernel_timespec __user *rmtp);
/* kernel/printk.c */
asmlinkage long sys_syslog(int type, char __user *buf, int len);
diff --git a/include/linux/time.h b/include/linux/time.h
index 4b62a2c0a661..aed74463592d 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -10,9 +10,9 @@
extern struct timezone sys_tz;
int get_timespec64(struct timespec64 *ts,
- const struct timespec __user *uts);
+ const struct __kernel_timespec __user *uts);
int put_timespec64(const struct timespec64 *ts,
- struct timespec __user *uts);
+ struct __kernel_timespec __user *uts);
int get_itimerspec64(struct itimerspec64 *it,
const struct itimerspec __user *uit);
int put_itimerspec64(const struct itimerspec64 *it,
diff --git a/include/linux/time64.h b/include/linux/time64.h
index 93d39499838e..0d96887ba4e0 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -2,12 +2,20 @@
#ifndef _LINUX_TIME64_H
#define _LINUX_TIME64_H
-#include <uapi/linux/time.h>
#include <linux/math64.h>
typedef __s64 time64_t;
typedef __u64 timeu64_t;
+/* CONFIG_64BIT_TIME enables new 64 bit time_t syscalls in the compat path
+ * and 32-bit emulation.
+ */
+#ifndef CONFIG_64BIT_TIME
+#define __kernel_timespec timespec
+#endif
+
+#include <uapi/linux/time.h>
+
#if __BITS_PER_LONG == 64
/* this trick allows us to optimize out timespec64_to_timespec */
# define timespec64 timespec