Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp249449ybi; Wed, 29 May 2019 20:37:53 -0700 (PDT) X-Google-Smtp-Source: APXvYqxHsoYtkVP+icrFEDRln0vX+qeeMhws+GXddQ2jDN9YZREMEbeFl6vA1EVcjJB2tjXRgxdX X-Received: by 2002:a17:902:8f85:: with SMTP id z5mr1647741plo.219.1559187473525; Wed, 29 May 2019 20:37:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559187473; cv=none; d=google.com; s=arc-20160816; b=oWtFDv15A776FChLootI6xsY/iIe61/fj2wiRL+uwtc9KTRlTqJaMt0yuQBpCjBexQ rBheoomGlAw01S612oPpdpmLyTewud8Ec7sLV+PXZ8dNvUv9PCsvX5+TF/TZEP+kgV9O /bU6PC4jBV9zhiSDNFAPkLmMEi+F2aIWYOwe8PyfCF6y+keaF7Q4NL5VRt8JGc25b8I2 Ga5B83KGSglEAMht8ltZdSswXmfLfkeTULx5VS8rezMPyAmN/3+NL07uz7PFNlWxc6+J vybC9qjP1cKKyLfwc2IYCSSXTrDUYIEI2t/oO/gXvi28vo+6T6/G8TjEI9amQdxC7/XB PMWg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=n/m2Ju8p1WYyQUv6M4yEngBqGlaL1CznbqxLO+c4H94=; b=Cu1NqcIR7RVvns8TnnbAWZDQsVj8vs5CMn9CdjSMCtKjcEoPizc+/WLHYV+KA2wQk3 zcsnTgF39CwPcjIMt9OP6uosRal8PXH0sY+3IUabiTAeuSdq+oacROnC4YVmLQPVkmUS 7QGeNqOf1L6LcWif1UzN9NOfEOnlSOW88niPmNOEfkt/2P3GY5ZCmTJ1iS2nfqoavPXB KZQsyfxi/6isaWft7UsQFbLnkovpGU+jYN4Gnn1/SAFUa2J3EKULASIOlNH/MNvyXQmq VjhWs//SAvcjo2uVxiO2S0qXxLI2qndqlfQC0Fhx2N5Lkt0EmSKYYD0aNIgyKI1w45di PB/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bV97JuEj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d4si2076019pla.358.2019.05.29.20.37.38; Wed, 29 May 2019 20:37:53 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bV97JuEj; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733015AbfE3DZQ (ORCPT + 99 others); Wed, 29 May 2019 23:25:16 -0400 Received: from mail.kernel.org ([198.145.29.99]:50966 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731527AbfE3DSX (ORCPT ); Wed, 29 May 2019 23:18:23 -0400 Received: from localhost (ip67-88-213-2.z213-88-67.customer.algx.net [67.88.213.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 256D624713; Thu, 30 May 2019 03:18:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559186303; bh=u0X3vofVZHNouzsi4oNBsFqNyrgfzDzmW2l8HFU641k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bV97JuEjlG7UqNPaWngsiv/jd7/4czklkpzIgzyyreh4ugZP9K7mbO+HwxQKaf//J BVYQHKUH7Lc8krjw7wrPIx4jaDy+wnSf0KJ6Z+ZSoAOn0HSfqW9HReLBDHS7ZHNRhN 2tjqTd4L7+ki+j34T39LoGAaDpKPVZ21pFYrTG1w= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Xiongfeng Wang , Hongbo Yao , Thomas Gleixner , John Stultz , Stephen Boyd , Miroslav Lichvar , Arnd Bergmann , Richard Cochran , Peter Zijlstra , Sasha Levin Subject: [PATCH 4.19 226/276] timekeeping: Force upper bound for setting CLOCK_REALTIME Date: Wed, 29 May 2019 20:06:24 -0700 Message-Id: <20190530030539.240750842@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190530030523.133519668@linuxfoundation.org> References: <20190530030523.133519668@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ Upstream commit 7a8e61f8478639072d402a26789055a4a4de8f77 ] Several people reported testing failures after setting CLOCK_REALTIME close to the limits of the kernel internal representation in nanoseconds, i.e. year 2262. The failures are exposed in subsequent operations, i.e. when arming timers or when the advancing CLOCK_MONOTONIC makes the calculation of CLOCK_REALTIME overflow into negative space. Now people start to paper over the underlying problem by clamping calculations to the valid range, but that's just wrong because such workarounds will prevent detection of real issues as well. It is reasonable to force an upper bound for the various methods of setting CLOCK_REALTIME. Year 2262 is the absolute upper bound. Assume a maximum uptime of 30 years which is plenty enough even for esoteric embedded systems. That results in an upper bound of year 2232 for setting the time. Once that limit is reached in reality this limit is only a small part of the problem space. But until then this stops people from trying to paper over the problem at the wrong places. Reported-by: Xiongfeng Wang Reported-by: Hongbo Yao Signed-off-by: Thomas Gleixner Cc: John Stultz Cc: Stephen Boyd Cc: Miroslav Lichvar Cc: Arnd Bergmann Cc: Richard Cochran Cc: Peter Zijlstra Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1903231125480.2157@nanos.tec.linutronix.de Signed-off-by: Sasha Levin --- include/linux/time64.h | 21 +++++++++++++++++++++ kernel/time/time.c | 2 +- kernel/time/timekeeping.c | 6 +++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/linux/time64.h b/include/linux/time64.h index 05634afba0db6..4a45aea0f96e9 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h @@ -41,6 +41,17 @@ struct itimerspec64 { #define KTIME_MAX ((s64)~((u64)1 << 63)) #define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +/* + * Limits for settimeofday(): + * + * To prevent setting the time close to the wraparound point time setting + * is limited so a reasonable uptime can be accomodated. Uptime of 30 years + * should be really sufficient, which means the cutoff is 2232. At that + * point the cutoff is just a small part of the larger problem. + */ +#define TIME_UPTIME_SEC_MAX (30LL * 365 * 24 *3600) +#define TIME_SETTOD_SEC_MAX (KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX) + static inline int timespec64_equal(const struct timespec64 *a, const struct timespec64 *b) { @@ -108,6 +119,16 @@ static inline bool timespec64_valid_strict(const struct timespec64 *ts) return true; } +static inline bool timespec64_valid_settod(const struct timespec64 *ts) +{ + if (!timespec64_valid(ts)) + return false; + /* Disallow values which cause overflow issues vs. CLOCK_REALTIME */ + if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX) + return false; + return true; +} + /** * timespec64_to_ns - Convert timespec64 to nanoseconds * @ts: pointer to the timespec64 variable to be converted diff --git a/kernel/time/time.c b/kernel/time/time.c index ccdb351277eec..be057d6579f13 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -172,7 +172,7 @@ int do_sys_settimeofday64(const struct timespec64 *tv, const struct timezone *tz static int firsttime = 1; int error = 0; - if (tv && !timespec64_valid(tv)) + if (tv && !timespec64_valid_settod(tv)) return -EINVAL; error = security_settime64(tv, tz); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 7846ce24ecc03..9a6bfcd22dc66 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1242,7 +1242,7 @@ int do_settimeofday64(const struct timespec64 *ts) unsigned long flags; int ret = 0; - if (!timespec64_valid_strict(ts)) + if (!timespec64_valid_settod(ts)) return -EINVAL; raw_spin_lock_irqsave(&timekeeper_lock, flags); @@ -1299,7 +1299,7 @@ static int timekeeping_inject_offset(const struct timespec64 *ts) /* Make sure the proposed value is valid */ tmp = timespec64_add(tk_xtime(tk), *ts); if (timespec64_compare(&tk->wall_to_monotonic, ts) > 0 || - !timespec64_valid_strict(&tmp)) { + !timespec64_valid_settod(&tmp)) { ret = -EINVAL; goto error; } @@ -1556,7 +1556,7 @@ void __init timekeeping_init(void) unsigned long flags; read_persistent_wall_and_boot_offset(&wall_time, &boot_offset); - if (timespec64_valid_strict(&wall_time) && + if (timespec64_valid_settod(&wall_time) && timespec64_to_ns(&wall_time) > 0) { persistent_clock_exists = true; } else if (timespec64_to_ns(&wall_time) != 0) { -- 2.20.1