From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl0-f66.google.com ([209.85.160.66]:33744 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752054AbdKZHZW (ORCPT ); Sun, 26 Nov 2017 02:25:22 -0500 Received: by mail-pl0-f66.google.com with SMTP id a12so6639898pll.0 for ; Sat, 25 Nov 2017 23:25:21 -0800 (PST) From: Harsh Shandilya To: stable@vger.kernel.org Cc: Wang YanQing , Prarit Bhargava , Richard Cochran , Ingo Molnar , Thomas Gleixner , John Stultz , Harsh Shandilya Subject: [PATCH 1/1] time: Always make sure wall_to_monotonic isn't positive Date: Sun, 26 Nov 2017 12:55:11 +0530 Message-Id: <20171126072511.7553-1-msfjarvis@gmail.com> Sender: stable-owner@vger.kernel.org List-ID: From: Wang YanQing commit e1d7ba8735551ed79c7a0463a042353574b96da3 upstream. Two issues were found on an IMX6 development board without an enabled RTC device(resulting in the boot time and monotonic time being initialized to 0). Issue 1:exportfs -a generate: "exportfs: /opt/nfs/arm does not support NFS export" Issue 2:cat /proc/stat: "btime 4294967236" The same issues can be reproduced on x86 after running the following code: int main(void) { struct timeval val; int ret; val.tv_sec = 0; val.tv_usec = 0; ret = settimeofday(&val, NULL); return 0; } Two issues are different symptoms of same problem: The reason is a positive wall_to_monotonic pushes boot time back to the time before Epoch, and getboottime will return negative value. In symptom 1: negative boot time cause get_expiry() to overflow time_t when input expire time is 2147483647, then cache_flush() always clears entries just added in ip_map_parse. In symptom 2: show_stat() uses "unsigned long" to print negative btime value returned by getboottime. This patch fix the problem by prohibiting time from being set to a value which would cause a negative boot time. As a result one can't set the CLOCK_REALTIME time prior to (1970 + system uptime). Change-Id: I19acf5df5cc34dd388de0dc633723fe73adc077e Cc: Prarit Bhargava Cc: Richard Cochran Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Wang YanQing [jstultz: reworded commit message] [msfjarvis: Backport to 3.18 as we are missing the do_settimeofday64 function the upstream commit patches, so we apply the changes to do_settimeofday] Signed-off-by: John Stultz Signed-off-by: Harsh Shandilya --- kernel/time/timekeeping.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 07b1c31898bd..caece7c8e44c 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -713,6 +713,7 @@ int do_settimeofday(const struct timespec *tv) struct timekeeper *tk = &tk_core.timekeeper; struct timespec64 ts_delta, xt, tmp; unsigned long flags; + int ret = 0; if (!timespec_valid_strict(tv)) return -EINVAL; @@ -726,11 +727,16 @@ int do_settimeofday(const struct timespec *tv) ts_delta.tv_sec = tv->tv_sec - xt.tv_sec; ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; + if (timespec64_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { + ret = -EINVAL; + goto out; + } + tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta)); tmp = timespec_to_timespec64(*tv); tk_set_xtime(tk, &tmp); - +out: timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET); write_seqcount_end(&tk_core.seq); @@ -739,7 +745,7 @@ int do_settimeofday(const struct timespec *tv) /* signal hrtimers about time change */ clock_was_set(); - return 0; + return ret; } EXPORT_SYMBOL(do_settimeofday); @@ -768,7 +774,8 @@ 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_compare(&tk->wall_to_monotonic, &ts64) > 0 || + !timespec64_valid_strict(&tmp)) { ret = -EINVAL; goto error; } -- 2.15.0.631.g7ddcec0