]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/timesync/timesyncd.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "capability-util.h"
7 #include "clock-util.h"
8 #include "daemon-util.h"
11 #include "main-func.h"
13 #include "network-util.h"
14 #include "process-util.h"
15 #include "signal-util.h"
16 #include "timesyncd-bus.h"
17 #include "timesyncd-conf.h"
18 #include "timesyncd-manager.h"
19 #include "user-util.h"
21 #define STATE_DIR "/var/lib/systemd/timesync"
22 #define CLOCK_FILE STATE_DIR "/clock"
24 static int load_clock_timestamp(uid_t uid
, gid_t gid
) {
25 _cleanup_close_
int fd
= -1;
26 usec_t min
= TIME_EPOCH
* USEC_PER_SEC
;
30 /* Let's try to make sure that the clock is always
31 * monotonically increasing, by saving the clock whenever we
32 * have a new NTP time, or when we shut down, and restoring it
33 * when we start again. This is particularly helpful on
34 * systems lacking a battery backed RTC. We also will adjust
35 * the time to at least the build time of systemd. */
37 fd
= open(CLOCK_FILE
, O_RDWR
|O_CLOEXEC
, 0644);
42 /* check if the recorded time is later than the compiled-in one */
45 stamp
= timespec_load(&st
.st_mtim
);
51 /* Try to fix the access mode, so that we can still
52 touch the file after dropping priviliges */
53 r
= fchmod_and_chown(fd
, 0644, uid
, gid
);
55 log_warning_errno(r
, "Failed to chmod or chown %s, ignoring: %m", CLOCK_FILE
);
59 r
= mkdir_safe_label(STATE_DIR
, 0755, uid
, gid
,
60 MKDIR_FOLLOW_SYMLINK
| MKDIR_WARN_MODE
);
62 log_debug_errno(r
, "Failed to create state directory, ignoring: %m");
66 /* create stamp file with the compiled-in date */
67 r
= touch_file(CLOCK_FILE
, false, min
, uid
, gid
, 0644);
69 log_debug_errno(r
, "Failed to create %s, ignoring: %m", CLOCK_FILE
);
73 ct
= now(CLOCK_REALTIME
);
76 char date
[FORMAT_TIMESTAMP_MAX
];
78 log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s",
79 format_timestamp(date
, sizeof(date
), min
));
81 if (clock_settime(CLOCK_REALTIME
, timespec_store(&ts
, min
)) < 0)
82 log_error_errno(errno
, "Failed to restore system clock, ignoring: %m");
88 static int run(int argc
, char *argv
[]) {
89 _cleanup_(notify_on_cleanup
) const char *notify_message
= NULL
;
90 _cleanup_(manager_freep
) Manager
*m
= NULL
;
91 const char *user
= "systemd-timesync";
92 uid_t uid
, uid_current
;
96 log_set_facility(LOG_CRON
);
102 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "This program does not take arguments.");
104 uid
= uid_current
= geteuid();
107 if (uid_current
== 0) {
108 r
= get_user_creds(&user
, &uid
, &gid
, NULL
, NULL
, 0);
110 return log_error_errno(r
, "Cannot resolve user name %s: %m", user
);
113 r
= load_clock_timestamp(uid
, gid
);
117 /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all
118 * privileges are already dropped. */
119 if (uid_current
== 0) {
120 r
= drop_privileges(uid
, gid
, (1ULL << CAP_SYS_TIME
));
122 return log_error_errno(r
, "Failed to drop privileges: %m");
125 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
129 return log_error_errno(r
, "Failed to allocate manager: %m");
131 r
= manager_connect_bus(m
);
133 return log_error_errno(r
, "Could not connect to bus: %m");
135 if (clock_is_localtime(NULL
) > 0) {
136 log_info("The system is configured to read the RTC time in the local time zone. "
137 "This mode cannot be fully supported. All system time to RTC updates are disabled.");
138 m
->rtc_local_time
= true;
141 r
= manager_parse_config_file(m
);
143 log_warning_errno(r
, "Failed to parse configuration file: %m");
145 r
= manager_parse_fallback_string(m
, NTP_SERVERS
);
147 return log_error_errno(r
, "Failed to parse fallback server strings: %m");
149 log_debug("systemd-timesyncd running as pid " PID_FMT
, getpid_cached());
151 notify_message
= notify_start("READY=1\n"
152 "STATUS=Daemon is running",
155 if (network_is_online()) {
156 r
= manager_connect(m
);
161 r
= sd_event_loop(m
->event
);
163 return log_error_errno(r
, "Failed to run event loop: %m");
165 /* if we got an authoritative time, store it in the file system */
167 r
= touch(CLOCK_FILE
);
169 log_debug_errno(r
, "Failed to touch %s, ignoring: %m", CLOCK_FILE
);
175 DEFINE_MAIN_FUNCTION(run
);