summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Ignatov <egori@altlinux.org>2021-07-28 12:13:31 +0300
committerLuca Boccassi <luca.boccassi@gmail.com>2021-08-02 20:33:01 +0100
commitb10abe4bba61aebe4c667c412741193f11886298 (patch)
tree8414c21e5c499c2884b9567a1defb45e41ad3b2e
parentf121bd78185b00389c21ab3abdb145daf1cc9d5d (diff)
downloadsystemd-b10abe4bba61aebe4c667c412741193f11886298.tar.gz
time-set: adjust system clock if rtc is far in future
-rw-r--r--meson.build2
-rw-r--r--meson_options.txt2
-rw-r--r--src/core/main.c16
-rw-r--r--src/shared/clock-util.c18
-rw-r--r--src/shared/clock-util.h11
5 files changed, 41 insertions, 8 deletions
diff --git a/meson.build b/meson.build
index 27dcf956f3..e08a7662a7 100644
--- a/meson.build
+++ b/meson.build
@@ -722,6 +722,8 @@ if time_epoch == -1
endif
conf.set('TIME_EPOCH', time_epoch)
+conf.set('CLOCK_VALID_RANGE_USEC_MAX', get_option('clock-valid-range-usec-max'))
+
foreach tuple : [['system-alloc-uid-min', 'SYS_UID_MIN', 1], # Also see login.defs(5).
['system-uid-max', 'SYS_UID_MAX', 999],
['system-alloc-gid-min', 'SYS_GID_MIN', 1],
diff --git a/meson_options.txt b/meson_options.txt
index 0b01fb2cbf..110a471b6b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -208,6 +208,8 @@ option('status-unit-format-default', type : 'combo',
description : 'use unit name or description in messages by default')
option('time-epoch', type : 'integer', value : '-1',
description : 'time epoch for time clients')
+option('clock-valid-range-usec-max', type : 'integer', value : '473364000000000', # 15 years
+ description : 'maximum value in microseconds for the difference between RTC and epoch, exceeding which is considered an RTC error')
option('system-alloc-uid-min', type : 'integer', value : '-1',
description : 'minimum system UID used when allocating')
diff --git a/src/core/main.c b/src/core/main.c
index 8920d70d5d..473dc0920e 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -83,6 +83,7 @@
#include "switch-root.h"
#include "sysctl-util.h"
#include "terminal-util.h"
+#include "time-util.h"
#include "umask-util.h"
#include "user-util.h"
#include "util.h"
@@ -1598,11 +1599,18 @@ static void initialize_clock(void) {
*/
(void) clock_reset_timewarp();
- r = clock_apply_epoch();
- if (r < 0)
- log_error_errno(r, "Current system time is before build time, but cannot correct: %m");
- else if (r > 0)
+ ClockChangeDirection change_dir;
+ r = clock_apply_epoch(&change_dir);
+ if (r > 0 && change_dir == CLOCK_CHANGE_FORWARD)
log_info("System time before build time, advancing clock.");
+ else if (r > 0 && change_dir == CLOCK_CHANGE_BACKWARD)
+ log_info("System time is further ahead than %s after build time, resetting clock to build time.",
+ FORMAT_TIMESPAN(CLOCK_VALID_RANGE_USEC_MAX, USEC_PER_DAY));
+ else if (r < 0 && change_dir == CLOCK_CHANGE_FORWARD)
+ log_error_errno(r, "Current system time is before build time, but cannot correct: %m");
+ else if (r < 0 && change_dir == CLOCK_CHANGE_BACKWARD)
+ log_error_errno(r, "Current system time is further ahead %s after build time, but cannot correct: %m",
+ FORMAT_TIMESPAN(CLOCK_VALID_RANGE_USEC_MAX, USEC_PER_DAY));
}
static void apply_clock_update(void) {
diff --git a/src/shared/clock-util.c b/src/shared/clock-util.c
index b446daf581..7c1c48d069 100644
--- a/src/shared/clock-util.c
+++ b/src/shared/clock-util.c
@@ -139,10 +139,15 @@ int clock_reset_timewarp(void) {
#define EPOCH_FILE "/usr/lib/clock-epoch"
-int clock_apply_epoch(void) {
+int clock_apply_epoch(ClockChangeDirection *ret_attempted_change) {
struct stat st;
struct timespec ts;
- usec_t epoch_usec;
+ usec_t epoch_usec, now_usec;
+
+ /* NB: we update *ret_attempted_change in *all* cases, both
+ * on success and failure, to indicate what we intended to do! */
+
+ assert(ret_attempted_change);
if (stat(EPOCH_FILE, &st) < 0) {
if (errno != ENOENT)
@@ -152,8 +157,15 @@ int clock_apply_epoch(void) {
} else
epoch_usec = timespec_load(&st.st_mtim);
- if (now(CLOCK_REALTIME) >= epoch_usec)
+ now_usec = now(CLOCK_REALTIME);
+ if (now_usec < epoch_usec)
+ *ret_attempted_change = CLOCK_CHANGE_FORWARD;
+ else if (now_usec > usec_add(epoch_usec, CLOCK_VALID_RANGE_USEC_MAX))
+ *ret_attempted_change = CLOCK_CHANGE_BACKWARD;
+ else {
+ *ret_attempted_change = CLOCK_CHANGE_NOOP;
return 0;
+ }
if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, epoch_usec)) < 0)
return -errno;
diff --git a/src/shared/clock-util.h b/src/shared/clock-util.h
index 9e96d50d96..c8f6d1b1f1 100644
--- a/src/shared/clock-util.h
+++ b/src/shared/clock-util.h
@@ -1,11 +1,20 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
+#include <errno.h>
#include <time.h>
+typedef enum ClockChangeDirection {
+ CLOCK_CHANGE_NOOP,
+ CLOCK_CHANGE_FORWARD,
+ CLOCK_CHANGE_BACKWARD,
+ _CLOCK_CHANGE_MAX,
+ _CLOCK_CHANGE_INVALID = -EINVAL,
+} ClockChangeDirection;
+
int clock_is_localtime(const char* adjtime_path);
int clock_set_timezone(int *ret_minutesdelta);
int clock_reset_timewarp(void);
int clock_get_hwclock(struct tm *tm);
int clock_set_hwclock(const struct tm *tm);
-int clock_apply_epoch(void);
+int clock_apply_epoch(ClockChangeDirection *ret_attempted_change);