1 /*
2 chronyd/chronyc - Programs for keeping computer clocks accurate.
3
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997-2003
6 * Copyright (C) John G. Hasler 2009
7 * Copyright (C) Miroslav Lichvar 2012-2020
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 *
22 **********************************************************************
23
24 =======================================================================
25
26 The main program
27 */
28
29 #include "config.h"
30
31 #include "sysincl.h"
32
33 #include "main.h"
34 #include "sched.h"
35 #include "local.h"
36 #include "sys.h"
37 #include "ntp_io.h"
38 #include "ntp_signd.h"
39 #include "ntp_sources.h"
40 #include "ntp_core.h"
41 #include "nts_ke_server.h"
42 #include "nts_ntp_server.h"
43 #include "socket.h"
44 #include "sources.h"
45 #include "sourcestats.h"
46 #include "reference.h"
47 #include "logging.h"
48 #include "conf.h"
49 #include "cmdmon.h"
50 #include "keys.h"
51 #include "manual.h"
52 #include "rtc.h"
53 #include "refclock.h"
54 #include "clientlog.h"
55 #include "nameserv.h"
56 #include "privops.h"
57 #include "smooth.h"
58 #include "tempcomp.h"
59 #include "util.h"
60
61 /* ================================================== */
62
63 /* Set when the initialisation chain has been completed. Prevents finalisation
64 * chain being run if a fatal error happened early. */
65
66 static int initialised = 0;
67
68 static int exit_status = 0;
69
70 static int reload = 0;
71
72 static REF_Mode ref_mode = REF_ModeNormal;
73
74 /* ================================================== */
75
76 static void
do_platform_checks(void)77 do_platform_checks(void)
78 {
79 struct timespec ts;
80
81 /* Require at least 32-bit integers, two's complement representation and
82 the usual implementation of conversion of unsigned integers */
83 assert(sizeof (int) >= 4);
84 assert(-1 == ~0);
85 assert((int32_t)4294967295U == (int32_t)-1);
86
87 /* Require time_t and tv_nsec in timespec to be signed */
88 ts.tv_sec = -1;
89 ts.tv_nsec = -1;
90 assert(ts.tv_sec < 0 && ts.tv_nsec < 0);
91 }
92
93 /* ================================================== */
94
95 static void
delete_pidfile(void)96 delete_pidfile(void)
97 {
98 const char *pidfile = CNF_GetPidFile();
99
100 if (!pidfile)
101 return;
102
103 if (!UTI_RemoveFile(NULL, pidfile, NULL))
104 ;
105 }
106
107 /* ================================================== */
108
109 void
MAI_CleanupAndExit(void)110 MAI_CleanupAndExit(void)
111 {
112 if (!initialised) exit(exit_status);
113
114 LCL_CancelOffsetCorrection();
115 SRC_DumpSources();
116
117 /* Don't update clock when removing sources */
118 REF_SetMode(REF_ModeIgnore);
119
120 SMT_Finalise();
121 TMC_Finalise();
122 MNL_Finalise();
123 CLG_Finalise();
124 NKS_Finalise();
125 NNS_Finalise();
126 NSD_Finalise();
127 NSR_Finalise();
128 SST_Finalise();
129 NCR_Finalise();
130 NIO_Finalise();
131 CAM_Finalise();
132
133 KEY_Finalise();
134 RCL_Finalise();
135 SRC_Finalise();
136 REF_Finalise();
137 RTC_Finalise();
138 SYS_Finalise();
139
140 SCK_Finalise();
141 SCH_Finalise();
142 LCL_Finalise();
143 PRV_Finalise();
144
145 delete_pidfile();
146
147 CNF_Finalise();
148 HSH_Finalise();
149 LOG_Finalise();
150
151 UTI_ResetGetRandomFunctions();
152
153 exit(exit_status);
154 }
155
156 /* ================================================== */
157
158 static void
signal_cleanup(int x)159 signal_cleanup(int x)
160 {
161 SCH_QuitProgram();
162 }
163
164 /* ================================================== */
165
166 static void
quit_timeout(void * arg)167 quit_timeout(void *arg)
168 {
169 /* Return with non-zero status if the clock is not synchronised */
170 exit_status = REF_GetOurStratum() >= NTP_MAX_STRATUM;
171 SCH_QuitProgram();
172 }
173
174 /* ================================================== */
175
176 static void
ntp_source_resolving_end(void)177 ntp_source_resolving_end(void)
178 {
179 NSR_SetSourceResolvingEndHandler(NULL);
180
181 if (reload) {
182 /* Note, we want reload to come well after the initialisation from
183 the real time clock - this gives us a fighting chance that the
184 system-clock scale for the reloaded samples still has a
185 semblence of validity about it. */
186 SRC_ReloadSources();
187 }
188
189 SRC_RemoveDumpFiles();
190 RTC_StartMeasurements();
191 RCL_StartRefclocks();
192 NSR_StartSources();
193 NSR_AutoStartSources();
194
195 /* Special modes can end only when sources update their reachability.
196 Give up immediately if there are no active sources. */
197 if (ref_mode != REF_ModeNormal && !SRC_ActiveSources()) {
198 REF_SetUnsynchronised();
199 }
200 }
201
202 /* ================================================== */
203
204 static void
post_init_ntp_hook(void * anything)205 post_init_ntp_hook(void *anything)
206 {
207 if (ref_mode == REF_ModeInitStepSlew) {
208 /* Remove the initstepslew sources and set normal mode */
209 NSR_RemoveAllSources();
210 ref_mode = REF_ModeNormal;
211 REF_SetMode(ref_mode);
212 }
213
214 /* Close the pipe to the foreground process so it can exit */
215 LOG_CloseParentFd();
216
217 CNF_AddSources();
218 CNF_AddBroadcasts();
219
220 NSR_SetSourceResolvingEndHandler(ntp_source_resolving_end);
221 NSR_ResolveSources();
222 }
223
224 /* ================================================== */
225
226 static void
reference_mode_end(int result)227 reference_mode_end(int result)
228 {
229 switch (ref_mode) {
230 case REF_ModeNormal:
231 case REF_ModeUpdateOnce:
232 case REF_ModePrintOnce:
233 exit_status = !result;
234 SCH_QuitProgram();
235 break;
236 case REF_ModeInitStepSlew:
237 /* Switch to the normal mode, the delay is used to prevent polling
238 interval shorter than the burst interval if some configured servers
239 were used also for initstepslew */
240 SCH_AddTimeoutByDelay(2.0, post_init_ntp_hook, NULL);
241 break;
242 default:
243 assert(0);
244 }
245 }
246
247 /* ================================================== */
248
249 static void
post_init_rtc_hook(void * anything)250 post_init_rtc_hook(void *anything)
251 {
252 if (CNF_GetInitSources() > 0) {
253 CNF_AddInitSources();
254 NSR_StartSources();
255 assert(REF_GetMode() != REF_ModeNormal);
256 /* Wait for mode end notification */
257 } else {
258 (post_init_ntp_hook)(NULL);
259 }
260 }
261
262 /* ================================================== */
263
264 static void
check_pidfile(void)265 check_pidfile(void)
266 {
267 const char *pidfile = CNF_GetPidFile();
268 FILE *in;
269 int pid, count;
270
271 if (!pidfile)
272 return;
273
274 in = UTI_OpenFile(NULL, pidfile, NULL, 'r', 0);
275 if (!in)
276 return;
277
278 count = fscanf(in, "%d", &pid);
279 fclose(in);
280
281 if (count != 1)
282 return;
283
284 if (getsid(pid) < 0)
285 return;
286
287 LOG_FATAL("Another chronyd may already be running (pid=%d), check %s",
288 pid, pidfile);
289 }
290
291 /* ================================================== */
292
293 static void
write_pidfile(void)294 write_pidfile(void)
295 {
296 const char *pidfile = CNF_GetPidFile();
297 FILE *out;
298
299 if (!pidfile)
300 return;
301
302 out = UTI_OpenFile(NULL, pidfile, NULL, 'W', 0644);
303 fprintf(out, "%d\n", (int)getpid());
304 fclose(out);
305 }
306
307 /* ================================================== */
308
309 #define DEV_NULL "/dev/null"
310
311 static void
go_daemon(void)312 go_daemon(void)
313 {
314 int pid, fd, pipefd[2];
315
316 /* Create pipe which will the daemon use to notify the grandparent
317 when it's initialised or send an error message */
318 if (pipe(pipefd)) {
319 LOG_FATAL("pipe() failed : %s", strerror(errno));
320 }
321
322 /* Does this preserve existing signal handlers? */
323 pid = fork();
324
325 if (pid < 0) {
326 LOG_FATAL("fork() failed : %s", strerror(errno));
327 } else if (pid > 0) {
328 /* In the 'grandparent' */
329 char message[1024];
330 int r;
331
332 close(pipefd[1]);
333 r = read(pipefd[0], message, sizeof (message));
334 if (r) {
335 if (r > 0) {
336 /* Print the error message from the child */
337 message[sizeof (message) - 1] = '\0';
338 fprintf(stderr, "%s\n", message);
339 }
340 exit(1);
341 } else
342 exit(0);
343 } else {
344 close(pipefd[0]);
345
346 setsid();
347
348 /* Do 2nd fork, as-per recommended practice for launching daemons. */
349 pid = fork();
350
351 if (pid < 0) {
352 LOG_FATAL("fork() failed : %s", strerror(errno));
353 } else if (pid > 0) {
354 exit(0); /* In the 'parent' */
355 } else {
356 /* In the child we want to leave running as the daemon */
357
358 /* Change current directory to / */
359 if (chdir("/") < 0) {
360 LOG_FATAL("chdir() failed : %s", strerror(errno));
361 }
362
363 /* Don't keep stdin/out/err from before. But don't close
364 the parent pipe yet. */
365 for (fd=0; fd<1024; fd++) {
366 if (fd != pipefd[1])
367 close(fd);
368 }
369
370 LOG_SetParentFd(pipefd[1]);
371
372 /* Open /dev/null as new stdin/out/err */
373 errno = 0;
374 if (open(DEV_NULL, O_RDONLY) != STDIN_FILENO ||
375 open(DEV_NULL, O_WRONLY) != STDOUT_FILENO ||
376 open(DEV_NULL, O_RDWR) != STDERR_FILENO)
377 LOG_FATAL("Could not open %s : %s", DEV_NULL, strerror(errno));
378 }
379 }
380 }
381
382 /* ================================================== */
383
384 static void
print_help(const char * progname)385 print_help(const char *progname)
386 {
387 printf("Usage: %s [OPTION]... [DIRECTIVE]...\n\n"
388 "Options:\n"
389 " -4\t\tUse IPv4 addresses only\n"
390 " -6\t\tUse IPv6 addresses only\n"
391 " -f FILE\tSpecify configuration file (%s)\n"
392 " -n\t\tDon't run as daemon\n"
393 " -d\t\tDon't run as daemon and log to stderr\n"
394 #if DEBUG > 0
395 " -d -d\t\tEnable debug messages\n"
396 #endif
397 " -l FILE\tLog to file\n"
398 " -L LEVEL\tSet logging threshold (0)\n"
399 " -p\t\tPrint configuration and exit\n"
400 " -q\t\tSet clock and exit\n"
401 " -Q\t\tLog offset and exit\n"
402 " -r\t\tReload dump files\n"
403 " -R\t\tAdapt configuration for restart\n"
404 " -s\t\tSet clock from RTC\n"
405 " -t SECONDS\tExit after elapsed time\n"
406 " -u USER\tSpecify user (%s)\n"
407 " -U\t\tDon't check for root\n"
408 " -F LEVEL\tSet system call filter level (0)\n"
409 " -P PRIORITY\tSet process priority (0)\n"
410 " -m\t\tLock memory\n"
411 " -x\t\tDon't control clock\n"
412 " -v, --version\tPrint version and exit\n"
413 " -h, --help\tPrint usage and exit\n",
414 progname, DEFAULT_CONF_FILE, DEFAULT_USER);
415 }
416
417 /* ================================================== */
418
419 static void
print_version(void)420 print_version(void)
421 {
422 printf("chronyd (chrony) version %s (%s)\n", CHRONY_VERSION, CHRONYD_FEATURES);
423 }
424
425 /* ================================================== */
426
427 static int
parse_int_arg(const char * arg)428 parse_int_arg(const char *arg)
429 {
430 int i;
431
432 if (sscanf(arg, "%d", &i) != 1)
433 LOG_FATAL("Invalid argument %s", arg);
434 return i;
435 }
436
437 /* ================================================== */
438
main(int argc,char ** argv)439 int main
440 (int argc, char **argv)
441 {
442 const char *conf_file = DEFAULT_CONF_FILE;
443 const char *progname = argv[0];
444 char *user = NULL, *log_file = NULL;
445 struct passwd *pw;
446 int opt, debug = 0, nofork = 0, address_family = IPADDR_UNSPEC;
447 int do_init_rtc = 0, restarted = 0, client_only = 0, timeout = -1;
448 int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
449 int clock_control = 1, system_log = 1, log_severity = LOGS_INFO;
450 int user_check = 1, config_args = 0, print_config = 0;
451
452 do_platform_checks();
453
454 LOG_Initialise();
455
456 /* Parse long command-line options */
457 for (optind = 1; optind < argc; optind++) {
458 if (!strcmp("--help", argv[optind])) {
459 print_help(progname);
460 return 0;
461 } else if (!strcmp("--version", argv[optind])) {
462 print_version();
463 return 0;
464 }
465 }
466
467 optind = 1;
468
469 /* Parse short command-line options */
470 while ((opt = getopt(argc, argv, "46df:F:hl:L:mnpP:qQrRst:u:Uvx")) != -1) {
471 switch (opt) {
472 case '4':
473 case '6':
474 address_family = opt == '4' ? IPADDR_INET4 : IPADDR_INET6;
475 break;
476 case 'd':
477 debug++;
478 nofork = 1;
479 system_log = 0;
480 break;
481 case 'f':
482 conf_file = optarg;
483 break;
484 case 'F':
485 scfilter_level = parse_int_arg(optarg);
486 break;
487 case 'l':
488 log_file = optarg;
489 break;
490 case 'L':
491 log_severity = parse_int_arg(optarg);
492 break;
493 case 'm':
494 lock_memory = 1;
495 break;
496 case 'n':
497 nofork = 1;
498 break;
499 case 'p':
500 print_config = 1;
501 user_check = 0;
502 nofork = 1;
503 system_log = 0;
504 log_severity = LOGS_WARN;
505 break;
506 case 'P':
507 sched_priority = parse_int_arg(optarg);
508 break;
509 case 'q':
510 ref_mode = REF_ModeUpdateOnce;
511 nofork = 1;
512 client_only = 0;
513 system_log = 0;
514 break;
515 case 'Q':
516 ref_mode = REF_ModePrintOnce;
517 nofork = 1;
518 client_only = 1;
519 user_check = 0;
520 clock_control = 0;
521 system_log = 0;
522 break;
523 case 'r':
524 reload = 1;
525 break;
526 case 'R':
527 restarted = 1;
528 break;
529 case 's':
530 do_init_rtc = 1;
531 break;
532 case 't':
533 timeout = parse_int_arg(optarg);
534 break;
535 case 'u':
536 user = optarg;
537 break;
538 case 'U':
539 user_check = 0;
540 break;
541 case 'v':
542 print_version();
543 return 0;
544 case 'x':
545 clock_control = 0;
546 break;
547 default:
548 print_help(progname);
549 return opt != 'h';
550 }
551 }
552
553 if (user_check && getuid() != 0)
554 LOG_FATAL("Not superuser");
555
556 /* Turn into a daemon */
557 if (!nofork) {
558 go_daemon();
559 }
560
561 if (log_file) {
562 LOG_OpenFileLog(log_file);
563 } else if (system_log) {
564 LOG_OpenSystemLog();
565 }
566
567 LOG_SetMinSeverity(debug >= 2 ? LOGS_DEBUG : log_severity);
568
569 LOG(LOGS_INFO, "chronyd version %s starting (%s)", CHRONY_VERSION, CHRONYD_FEATURES);
570
571 DNS_SetAddressFamily(address_family);
572
573 CNF_Initialise(restarted, client_only);
574 if (print_config)
575 CNF_EnablePrint();
576
577 /* Parse the config file or the remaining command line arguments */
578 config_args = argc - optind;
579 if (!config_args) {
580 CNF_ReadFile(conf_file);
581 } else {
582 for (; optind < argc; optind++)
583 CNF_ParseLine(NULL, config_args + optind - argc + 1, argv[optind]);
584 }
585
586 if (print_config)
587 return 0;
588
589 /* Check whether another chronyd may already be running */
590 check_pidfile();
591
592 if (!user)
593 user = CNF_GetUser();
594
595 pw = getpwnam(user);
596 if (!pw)
597 LOG_FATAL("Could not get user/group ID of %s", user);
598
599 /* Create directories for sockets, log files, and dump files */
600 CNF_CreateDirs(pw->pw_uid, pw->pw_gid);
601
602 /* Write our pidfile to prevent other instances from running */
603 write_pidfile();
604
605 PRV_Initialise();
606 LCL_Initialise();
607 SCH_Initialise();
608 SCK_Initialise(address_family);
609
610 /* Start helper processes if needed */
611 NKS_PreInitialise(pw->pw_uid, pw->pw_gid, scfilter_level);
612
613 SYS_Initialise(clock_control);
614 RTC_Initialise(do_init_rtc);
615 SRC_Initialise();
616 RCL_Initialise();
617 KEY_Initialise();
618
619 /* Open privileged ports before dropping root */
620 CAM_Initialise();
621 NIO_Initialise();
622 NCR_Initialise();
623 CNF_SetupAccessRestrictions();
624
625 /* Command-line switch must have priority */
626 if (!sched_priority) {
627 sched_priority = CNF_GetSchedPriority();
628 }
629 if (sched_priority) {
630 SYS_SetScheduler(sched_priority);
631 }
632
633 if (lock_memory || CNF_GetLockMemory()) {
634 SYS_LockMemory();
635 }
636
637 /* Drop root privileges if the specified user has a non-zero UID */
638 if (!geteuid() && (pw->pw_uid || pw->pw_gid))
639 SYS_DropRoot(pw->pw_uid, pw->pw_gid, SYS_MAIN_PROCESS);
640
641 if (!geteuid())
642 LOG(LOGS_WARN, "Running with root privileges");
643
644 REF_Initialise();
645 SST_Initialise();
646 NSR_Initialise();
647 NSD_Initialise();
648 NNS_Initialise();
649 NKS_Initialise();
650 CLG_Initialise();
651 MNL_Initialise();
652 TMC_Initialise();
653 SMT_Initialise();
654
655 /* From now on, it is safe to do finalisation on exit */
656 initialised = 1;
657
658 UTI_SetQuitSignalsHandler(signal_cleanup, 1);
659
660 CAM_OpenUnixSocket();
661
662 if (scfilter_level)
663 SYS_EnableSystemCallFilter(scfilter_level, SYS_MAIN_PROCESS);
664
665 if (ref_mode == REF_ModeNormal && CNF_GetInitSources() > 0) {
666 ref_mode = REF_ModeInitStepSlew;
667 }
668
669 REF_SetModeEndHandler(reference_mode_end);
670 REF_SetMode(ref_mode);
671
672 if (timeout >= 0)
673 SCH_AddTimeoutByDelay(timeout, quit_timeout, NULL);
674
675 if (do_init_rtc) {
676 RTC_TimeInit(post_init_rtc_hook, NULL);
677 } else {
678 post_init_rtc_hook(NULL);
679 }
680
681 /* The program normally runs under control of the main loop in
682 the scheduler. */
683 SCH_MainLoop();
684
685 LOG(LOGS_INFO, "chronyd exiting");
686
687 MAI_CleanupAndExit();
688
689 return 0;
690 }
691
692 /* ================================================== */
693