This patch series changes the 32-bit time type (timespec/itimerspec) to the 64-bit one
(timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type,
and removes the old ones with timespec/itimerspec type for posix_clock_operations
and k_clock structure.
Also introduces some new functions with timespec64/itimerspec64 type, like current_kernel_time64(),
hrtimer_get_res64(), cputime_to_timespec64() and timespec64_to_cputime().
Changes since V1:
-Split some patch into small patch.
-Add some default function for new 64bit methods for syscall function.
-Move do_sys_settimeofday() function to head file.
-Modify the EXPORT_SYMPOL issue.
-Add new 64bit methods in cputime_nsecs.h file.
Baolin Wang (15):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
posix timers:Introduce the 64bit methods with timespec64 type for
k_clock structure
posix-timers:Split out the guts of the syscall and change the
implementation
posix-timers:Convert to the 64bit methods for the syscall function
time:Introduce the do_sys_settimeofday64() function with timespec64
type
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
function
time/alarmtimer:Convert to the new methods for k_clock structure
time/posix-clock:Convert to the 64bit methods for k_clock and
posix_clock_operations structure
time/time:Introduce the timespec64_to_jiffies/jiffies_to_timespec64
function
cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec/itimerspec type
arch/powerpc/include/asm/cputime.h | 6 +-
arch/s390/include/asm/cputime.h | 8 +-
drivers/char/mmtimer.c | 36 +++--
drivers/ptp/ptp_clock.c | 26 +---
include/asm-generic/cputime_jiffies.h | 10 +-
include/asm-generic/cputime_nsecs.h | 4 +-
include/linux/cputime.h | 15 ++
include/linux/hrtimer.h | 12 +-
include/linux/jiffies.h | 21 ++-
include/linux/posix-clock.h | 10 +-
include/linux/posix-timers.h | 18 +--
include/linux/time64.h | 35 +++++
include/linux/timekeeping.h | 26 +++-
kernel/time/alarmtimer.c | 43 +++---
kernel/time/hrtimer.c | 10 +-
kernel/time/posix-clock.c | 20 +--
kernel/time/posix-cpu-timers.c | 83 +++++-----
kernel/time/posix-timers.c | 269 ++++++++++++++++++++++-----------
kernel/time/time.c | 22 +--
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 2 +-
21 files changed, 428 insertions(+), 254 deletions(-)
--
1.7.9.5
This patch series changes the 32-bit time type (timespec/itimerspec) to the 64-bit one
(timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type,
and removes the old ones with timespec/itimerspec type for posix_clock_operations
and k_clock structure.
Also introduces some new functions with timespec64/itimerspec64 type, like current_kernel_time64(),
hrtimer_get_res64(), cputime_to_timespec64() and timespec64_to_cputime().
Changes since V0:
-Split some patch into small patch.
-Modify some patch logs.
-Change the methods for converting the syscall function.
-Introduce the new function do_sys_settimeofday64().
Baolin Wang (14):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
posix timers:Introduce the 64bit methods with timespec64 type for
k_clock structure
posix-timers:Introduce the 64bit methods for posix-timer.c file
time:Introduce the do_sys_settimeofday64() function with timespec64
type
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
function
time/alarmtimer:Convert to the new methods for k_clock structure
time/posix-clock:Convert to the 64bit methods for k_clock and
posix_clock_operations structure
time/time:Introduce the timespec64_to_jiffies/jiffies_to_timespec64
function
cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec type
arch/powerpc/include/asm/cputime.h | 6 +-
arch/s390/include/asm/cputime.h | 8 +-
drivers/char/mmtimer.c | 36 +++--
drivers/ptp/ptp_clock.c | 26 +---
include/asm-generic/cputime_jiffies.h | 10 +-
include/linux/cputime.h | 15 ++
include/linux/hrtimer.h | 12 +-
include/linux/jiffies.h | 3 +
include/linux/posix-clock.h | 10 +-
include/linux/posix-timers.h | 18 +--
include/linux/time64.h | 25 +++
include/linux/timekeeping.h | 16 +-
kernel/time/alarmtimer.c | 43 +++---
kernel/time/hrtimer.c | 10 +-
kernel/time/posix-clock.c | 20 +--
kernel/time/posix-cpu-timers.c | 83 +++++-----
kernel/time/posix-timers.c | 269 ++++++++++++++++++++++-----------
kernel/time/time.c | 41 ++++-
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 2 +-
20 files changed, 414 insertions(+), 245 deletions(-)
--
1.7.9.5
This patch series changes the 32-bit time type (timespec/itimerspec) to the 64-bit one
(timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduces new methods with timespec64/itimerspec64 type,
and removes the old ones with timespec/itimerspec type for posix_clock_operations
and k_clock structure.
Also introduces some new functions with timespec64/itimerspec64 type, like current_kernel_time64(),
hrtimer_get_res64(), cputime_to_timespec64() and timespec64_to_cputime().
Baolin Wang (11):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
posix timers:Introduce the 64bit methods with timespec64 type for
k_clock structure
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
function
time/alarmtimer:Convert to the new methods for k_clock structure
time/posix-clock:Convert to the 64bit methods for k_clock and
posix_clock_operations structure
cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec type
arch/powerpc/include/asm/cputime.h | 6 +-
arch/s390/include/asm/cputime.h | 8 +-
drivers/char/mmtimer.c | 36 ++++----
drivers/ptp/ptp_clock.c | 26 ++----
include/asm-generic/cputime_jiffies.h | 10 +--
include/linux/cputime.h | 15 ++++
include/linux/hrtimer.h | 12 ++-
include/linux/jiffies.h | 3 +
include/linux/posix-clock.h | 10 +--
include/linux/posix-timers.h | 18 ++--
include/linux/time64.h | 13 +++
include/linux/timekeeping.h | 14 ++-
kernel/time/alarmtimer.c | 43 ++++-----
kernel/time/hrtimer.c | 10 +--
kernel/time/posix-clock.c | 20 ++---
kernel/time/posix-cpu-timers.c | 83 +++++++++--------
kernel/time/posix-timers.c | 157 +++++++++++++++++++--------------
kernel/time/time.c | 21 +++++
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 2 +-
20 files changed, 302 insertions(+), 211 deletions(-)
--
1.7.9.5
This patch series change the 32-bit time type (timespec/itimerspec) to the 64-bit one
(timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduce new methods with timespec64/itimerspec64 type,
and remove the old ones with timespec/itimerspec type for posix_clock_operations
and k_clock structure.
Changes since v4:
- Modify the conversion between the itimerspec64 and itimerspec for 64bit.
- Continue to split up and merge the patch.
- Explain more for the patch log.
- Re-order the patch of the patch series.
Next step will replace the other callback pointers of k_clock structure.
Baolin Wang (11):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
posix timers:Introduce the 64bit methods with timespec64 type for
k_clock structure
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
function
time/alarmtimer:Convert to the new methods for k_clock structure
time/posix-clock:Convert to the 64bit methods for k_clock and
posix_clock_operations structure
cputime:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec type
arch/powerpc/include/asm/cputime.h | 24 +++++
arch/s390/include/asm/cputime.h | 26 ++++++
drivers/char/mmtimer.c | 36 ++++----
drivers/ptp/ptp_clock.c | 26 ++----
include/asm-generic/cputime_jiffies.h | 8 ++
include/linux/hrtimer.h | 12 ++-
include/linux/jiffies.h | 3 +
include/linux/posix-clock.h | 10 +--
include/linux/posix-timers.h | 18 ++--
include/linux/time64.h | 45 ++++++++++
include/linux/timekeeping.h | 14 ++-
kernel/time/alarmtimer.c | 43 ++++-----
kernel/time/hrtimer.c | 10 +--
kernel/time/posix-clock.c | 20 ++---
kernel/time/posix-cpu-timers.c | 83 +++++++++--------
kernel/time/posix-timers.c | 157 +++++++++++++++++++--------------
kernel/time/time.c | 21 +++++
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 2 +-
19 files changed, 365 insertions(+), 199 deletions(-)
--
1.7.9.5
This patch series change the 32-bit time type (timespec/itimerspec) to the 64-bit one
(timespec64/itimerspec64), since 32-bit time types will break in the year 2038.
This patch series introduce new methods with timespec64/itimerspec64 type,
and remove the old ones with timespec/itimerspec type for posix clock operation
and k_clock structure.
Changes since v3:
- Introduce the new structure 'itimerspec64' for 64bit and the conversion function.
- Separate original one patch into two patches.
- Remove the 32bit unused code
- Re-order the patch of the patch series.
Next step will replace the other callback pointers of k_clock structure.
Baolin Wang (12):
linux/time64.h:Introduce the 'struct itimerspec64' for 64bit
posix_clock:Introduce the new methods with explicit 64 bit seconds
timekeeping:Introduce the current_kernel_time64() function with
timespec64 type
time/hrtimer:Introduce hrtimer_get_res64() with timespec64 type for
getting the timer resolution
posix timers:Introduce the 64bit methods with timespec64 type for
k_clock structure
time/posix-timers:Convert to the 64bit methods for k_clock callback
functions
char/mmtimer:Convert to the 64bit methods for k_clock callback
function
time/alarmtimer:Convert to the new methods for k_clock structure
time/posix-clock:Convert to the 64bit methods for k_clock structure
time:Introduce the cputime_to_timespec64/timespec64_to_cputime
function
time/posix-cpu-timers:Convert to the 64bit methods for k_clock
structure
k_clock:Remove the 32bit methods with timespec type
arch/powerpc/include/asm/cputime.h | 24 +++++
arch/s390/include/asm/cputime.h | 26 ++++++
drivers/char/mmtimer.c | 38 ++++----
drivers/ptp/ptp_clock.c | 26 ++----
include/asm-generic/cputime_jiffies.h | 8 ++
include/linux/hrtimer.h | 12 ++-
include/linux/jiffies.h | 3 +
include/linux/posix-clock.h | 10 +--
include/linux/posix-timers.h | 18 ++--
include/linux/time64.h | 37 ++++++++
include/linux/timekeeping.h | 14 ++-
kernel/time/alarmtimer.c | 43 ++++-----
kernel/time/hrtimer.c | 10 +--
kernel/time/posix-clock.c | 21 ++---
kernel/time/posix-cpu-timers.c | 83 +++++++++--------
kernel/time/posix-timers.c | 159 +++++++++++++++++++--------------
kernel/time/time.c | 21 +++++
kernel/time/timekeeping.c | 6 +-
kernel/time/timekeeping.h | 2 +-
19 files changed, 361 insertions(+), 200 deletions(-)
--
1.7.9.5
On Wednesday 15 April 2015 17:41:28 Miroslav Lichvar wrote:
> On systems with 32-bit time_t, it seems there are quite a few problems
> that applications may have with time overflowing in year 2038. Beside
> getting in an unexpected state by not checking integer operations with
> time_t variables, some system calls have unexpected behavior, e.g. the
> system time can't be set back to the current time (negative value),
> timers with the ABSTIME flag can't be set (negative value) or they
> expire immediately (current time is always larger).
>
> It would be unrealistic to expect all applications to be able to handle
> all these problems. Year 2038 is still many years away, but this can be
> a problem even now. The clock can be set close to the overflow
> accidentally or maliciously, e.g. when the clock is synchronized over
> network by NTP or PTP.
>
> This patch sets a maximum value of the system time to prevent the system
> time from getting too close to the overflow. The time can't be set to a
> larger value. When the maximum is reached in normal time accumulation,
> the clock will be stepped back by one week.
>
> A new kernel sysctl time_max is added to select the maximum time. It can
> be set to 0 for no limit, 1 for one week before 32-bit time_t overflow,
> and 2 for one week before ktime_t overflow. The default value is 1 with
> 32-bit time_t and 2 with 64-bit time_t. This can be changed later to be
> always 2 when 64-bit versions of system calls using 32-bit time_t are
> available.
>
> Signed-off-by: Miroslav Lichvar <mlichvar(a)redhat.com>
I have just created a y2038(a)lists.linaro.org mailing list, added to Cc in
this reply.
The patch looks basically ok to me, though I have no opinion on whether
a sysctl is the best API for configuring this.
Arnd
> ---
> Documentation/sysctl/kernel.txt | 19 +++++++++++++
> include/linux/timekeeping.h | 5 ++++
> include/uapi/linux/sysctl.h | 1 +
> kernel/sysctl.c | 9 ++++++
> kernel/sysctl_binary.c | 1 +
> kernel/time/timekeeping.c | 62 +++++++++++++++++++++++++++++++++++++----
> 6 files changed, 91 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
> index 83ab256..08e4f28 100644
> --- a/Documentation/sysctl/kernel.txt
> +++ b/Documentation/sysctl/kernel.txt
> @@ -82,6 +82,7 @@ show up in /proc/sys/kernel:
> - sysctl_writes_strict
> - tainted
> - threads-max
> +- time_max
> - unknown_nmi_panic
> - watchdog_thresh
> - version
> @@ -847,6 +848,24 @@ can be ORed together:
>
> ==============================================================
>
> +time_max:
> +
> +Select the maximum allowed value of the system time. The system clock cannot be
> +set to a larger value and when it reaches the maximum on its own, it will be
> +stepped back by one week.
> +
> +0: No limit.
> +
> +1: One week before 32-bit time_t overflows, i.e. Jan 12 03:14:07 UTC 2038.
> + This is currently the default value with 32-bit time_t, but it will likely
> + change when 64-bit versions of system calls using time_t are available.
> +
> +2: One week before time in the internal kernel representation (ktime_t)
> + overflows, i.e. Apr 4 23:47:16 UTC 2262. This is the default value with
> + 64-bit time_t.
> +
> +==============================================================
> +
> unknown_nmi_panic:
>
> The value in this file affects behavior of handling NMI. When the
> diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
> index 99176af..51fc970 100644
> --- a/include/linux/timekeeping.h
> +++ b/include/linux/timekeeping.h
> @@ -5,6 +5,11 @@
>
> void timekeeping_init(void);
> extern int timekeeping_suspended;
> +extern int sysctl_time_max;
> +
> +struct ctl_table;
> +extern int sysctl_time_max_handler(struct ctl_table *table, int write,
> + void __user *buffer, size_t *length, loff_t *ppos);
>
> /*
> * Get and set timeofday
> diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h
> index 0956373..8fd2aab 100644
> --- a/include/uapi/linux/sysctl.h
> +++ b/include/uapi/linux/sysctl.h
> @@ -154,6 +154,7 @@ enum
> KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
> KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
> KERN_PANIC_ON_WARN=77, /* int: call panic() in WARN() functions */
> + KERN_TIMEMAX=78, /* int: select maximum allowed system time */
> };
>
>
> diff --git a/kernel/sysctl.c b/kernel/sysctl.c
> index ce410bb..6713a5b 100644
> --- a/kernel/sysctl.c
> +++ b/kernel/sysctl.c
> @@ -1120,6 +1120,15 @@ static struct ctl_table kern_table[] = {
> .extra1 = &zero,
> .extra2 = &one,
> },
> + {
> + .procname = "time_max",
> + .data = &sysctl_time_max,
> + .maxlen = sizeof(int),
> + .mode = 0644,
> + .proc_handler = sysctl_time_max_handler,
> + .extra1 = &zero,
> + .extra2 = &two,
> + },
> { }
> };
>
> diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
> index 7e7746a..66c0946 100644
> --- a/kernel/sysctl_binary.c
> +++ b/kernel/sysctl_binary.c
> @@ -138,6 +138,7 @@ static const struct bin_table bin_kern_table[] = {
> { CTL_INT, KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
> { CTL_INT, KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
> { CTL_INT, KERN_PANIC_ON_WARN, "panic_on_warn" },
> + { CTL_INT, KERN_TIMEMAX, "time_max" },
> {}
> };
>
> diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
> index 946acb7..112932f 100644
> --- a/kernel/time/timekeeping.c
> +++ b/kernel/time/timekeeping.c
> @@ -32,6 +32,9 @@
> #define TK_MIRROR (1 << 1)
> #define TK_CLOCK_WAS_SET (1 << 2)
>
> +#define SEC_PER_DAY (24 * 3600)
> +#define SEC_PER_WEEK (7 * SEC_PER_DAY)
> +
> /*
> * The most important data for readout fits into a single 64 byte
> * cache line.
> @@ -884,6 +887,37 @@ EXPORT_SYMBOL(getnstime_raw_and_real);
>
> #endif /* CONFIG_NTP_PPS */
>
> +/* Maximum allowed system time as a sysctl setting and in seconds */
> +int sysctl_time_max __read_mostly;
> +static u64 time_max_sec __read_mostly;
> +
> +static void update_time_max_sec(int tm)
> +{
> + if (tm > 1) {
> + /* One week before ktime_t overflow */
> + time_max_sec = KTIME_SEC_MAX - SEC_PER_WEEK;
> + } else if (tm == 1) {
> + /* One week before 32-bit time_t overflow */
> + time_max_sec = 0x7fffffff - SEC_PER_WEEK;
> + } else {
> + /* No limit */
> + time_max_sec = -1;
> + }
> +}
> +
> +int sysctl_time_max_handler(struct ctl_table *table, int write,
> + void __user *buffer, size_t *length, loff_t *ppos)
> +{
> + int rc;
> +
> + rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
> + if (rc)
> + return rc;
> +
> + update_time_max_sec(sysctl_time_max);
> + return 0;
> +}
> +
> /**
> * do_gettimeofday - Returns the time of day in a timeval
> * @tv: pointer to the timeval to be set
> @@ -912,7 +946,7 @@ int do_settimeofday64(const struct timespec64 *ts)
> struct timespec64 ts_delta, xt;
> unsigned long flags;
>
> - if (!timespec64_valid_strict(ts))
> + if (!timespec64_valid_strict(ts) || ts->tv_sec >= time_max_sec)
> return -EINVAL;
>
> raw_spin_lock_irqsave(&timekeeper_lock, flags);
> @@ -965,7 +999,7 @@ int timekeeping_inject_offset(struct timespec *ts)
>
> /* Make sure the proposed value is valid */
> tmp = timespec64_add(tk_xtime(tk), ts64);
> - if (!timespec64_valid_strict(&tmp)) {
> + if (!timespec64_valid_strict(&tmp) || tmp.tv_sec >= time_max_sec) {
> ret = -EINVAL;
> goto error;
> }
> @@ -1238,6 +1272,10 @@ void __init timekeeping_init(void)
> write_seqcount_begin(&tk_core.seq);
> ntp_init();
>
> + /* For now, prevent 32-bit time_t overflow by default */
> + sysctl_time_max = sizeof(time_t) > 4 ? 2 : 1;
> + update_time_max_sec(sysctl_time_max);
> +
> clock = clocksource_default_clock();
> if (clock->enable)
> clock->enable(clock);
> @@ -1687,23 +1725,35 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
>
> while (tk->tkr_mono.xtime_nsec >= nsecps) {
> int leap;
> + s64 step;
>
> tk->tkr_mono.xtime_nsec -= nsecps;
> tk->xtime_sec++;
>
> /* Figure out if its a leap sec and apply if needed */
> leap = second_overflow(tk->xtime_sec);
> - if (unlikely(leap)) {
> + step = leap;
> +
> + /* If the system time reached the maximum, step it back */
> + if (unlikely(tk->xtime_sec >= time_max_sec)) {
> + step = time_max_sec - tk->xtime_sec - SEC_PER_WEEK;
> + printk(KERN_NOTICE
> + "Clock: maximum time reached, stepping back\n");
> + }
> +
> + if (unlikely(step)) {
> struct timespec64 ts;
>
> - tk->xtime_sec += leap;
> + tk->xtime_sec += step;
>
> - ts.tv_sec = leap;
> + ts.tv_sec = step;
> ts.tv_nsec = 0;
> tk_set_wall_to_mono(tk,
> timespec64_sub(tk->wall_to_monotonic, ts));
>
> - __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
> + if (leap)
> + __timekeeping_set_tai_offset(tk,
> + tk->tai_offset - leap);
>
> clock_set = TK_CLOCK_WAS_SET;
> }
>