From 9c331bf201909fb5a85725202eee872d4323e12d Mon Sep 17 00:00:00 2001 From: Will Drewry Date: Wed, 17 Sep 2014 15:33:22 -0500 Subject: continued merge issues: platform, debug, configs - moved debug () to verb_debug () - moved to platform->* calls for system calls - moved upstart file for cros to a cros-specific name --- init/tlsdated-cros.conf | 22 ++++++ init/tlsdated.conf | 22 ------ src/dbus.c | 27 +++++--- src/dbus.h | 6 -- src/events/kickoff_time_sync.c | 10 +-- src/events/route_up.c | 6 +- src/events/run_tlsdate.c | 2 +- src/events/save.c | 2 +- src/events/sigchld.c | 2 +- src/events/sigterm.c | 2 +- src/events/time_set.c | 2 +- src/events/tlsdate_status.c | 2 +- src/platform-cros.c | 16 ++--- src/rtc.h | 9 +++ src/seccomp.c | 1 - src/tlsdate-helper.c | 2 +- src/tlsdate-monitor.c | 2 +- src/tlsdate-setter.c | 42 +----------- src/tlsdate.h | 5 +- src/tlsdated-unittest.c | 67 ++---------------- src/tlsdated.c | 39 ++++------- src/util.c | 150 +++++++++++++++++++++++------------------ src/util.h | 35 ++++------ tests/run-idle/runs | 2 +- tests/run-routeup/runs | 2 +- 25 files changed, 195 insertions(+), 282 deletions(-) create mode 100644 init/tlsdated-cros.conf delete mode 100644 init/tlsdated.conf create mode 100644 src/rtc.h diff --git a/init/tlsdated-cros.conf b/init/tlsdated-cros.conf new file mode 100644 index 0000000..f5b46a4 --- /dev/null +++ b/init/tlsdated-cros.conf @@ -0,0 +1,22 @@ +# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +description "Run the tlsdate daemon to set the system time" +author "chromium-os-dev@chromium.org" + +start on started system-services +stop on stopping system-services +respawn + +script + GOOGLE_CERTS=/usr/share/chromeos-ca-certificates + mkdir -m 755 -p /var/cache/tlsdated + # Make sure the timestamp file has the proper permissions. + chmod 0644 /var/cache/tlsdated/timestamp || true + # When it runs tlsdate, tlsdated stitches together an argument vector for it + # as follows: it begins with everything supplied to it after the --, then + # appends -H $host -p $port, and maybe -x $proxy if it has a proxy to use. + exec tlsdated -v -- /usr/bin/tlsdate -v -C "$GOOGLE_CERTS" -l \ + 2>&1 | logger -t tlsdate +end script diff --git a/init/tlsdated.conf b/init/tlsdated.conf deleted file mode 100644 index f5b46a4..0000000 --- a/init/tlsdated.conf +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -description "Run the tlsdate daemon to set the system time" -author "chromium-os-dev@chromium.org" - -start on started system-services -stop on stopping system-services -respawn - -script - GOOGLE_CERTS=/usr/share/chromeos-ca-certificates - mkdir -m 755 -p /var/cache/tlsdated - # Make sure the timestamp file has the proper permissions. - chmod 0644 /var/cache/tlsdated/timestamp || true - # When it runs tlsdate, tlsdated stitches together an argument vector for it - # as follows: it begins with everything supplied to it after the --, then - # appends -H $host -p $port, and maybe -x $proxy if it has a proxy to use. - exec tlsdated -v -- /usr/bin/tlsdate -v -C "$GOOGLE_CERTS" -l \ - 2>&1 | logger -t tlsdate -end script diff --git a/src/dbus.c b/src/dbus.c index 81bda4b..b83e9ef 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -231,15 +231,21 @@ toggle_timeout (DBusTimeout *t, void *user_data) } } -#ifdef TLSDATED_MAIN void dbus_announce (struct state *global_state) { struct dbus_state *state = global_state->dbus; - DBusConnection *conn = state->conn; + DBusConnection *conn; DBusMessage *msg; uint32_t ignored; const char *sync_type = sync_type_str (global_state->last_sync_type); + +#ifndef TLSDATED_MAIN + /* Return early if we're not linked to tlsdated. */ + return; +#endif + + conn = state->conn; msg = dbus_message_new_signal (kServicePath, kServiceInterface, kTimeUpdated); if (!msg) { @@ -259,7 +265,6 @@ dbus_announce (struct state *global_state) return; } } -#endif static DBusHandlerResult @@ -374,7 +379,7 @@ handle_set_time (DBusConnection *connection, DBusMessageIter iter; DBusError error; dbus_int64_t requested_time = 0; - debug ("[event:%s]: fired", __func__); + verb_debug ("[event:%s]: fired", __func__); dbus_error_init (&error); /* Expects DBUS_TYPE_INT64: */ @@ -410,7 +415,7 @@ handle_can_set_time (DBusConnection *connection, DBusMessage *message, struct state *state) { - debug ("[event:%s]: fired", __func__); + verb_debug ("[event:%s]: fired", __func__); return send_can_reply (connection, message, can_set_time (state)); } @@ -427,7 +432,7 @@ handle_last_sync_info (DBusConnection *connection, const char *sync = sync_type_str (state->last_sync_type); int64_t t = state->last_time; - debug ("[dbus]: handler fired"); + verb_debug ("[dbus]: handler fired"); reply = dbus_message_new_method_return (message); if (!reply) { @@ -488,7 +493,7 @@ service_dispatch (DBusConnection *conn, DBusMessage *msg, void *data) const char *interface; const char *method; - debug ("[dbus] service dispatcher called"); + verb_debug ("[dbus] service dispatcher called"); if (dbus_message_get_type (msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -496,13 +501,13 @@ service_dispatch (DBusConnection *conn, DBusMessage *msg, void *data) method = dbus_message_get_member (msg); if (!interface || !method) { - debug ("[dbus] service request fired with bogus data"); + verb_debug ("[dbus] service request fired with bogus data"); /* Consume it */ return DBUS_HANDLER_RESULT_HANDLED; } if (strcmp (interface, kServiceInterface)) { - debug ("[dbus] invalid interface supplied"); + verb_debug ("[dbus] invalid interface supplied"); return DBUS_HANDLER_RESULT_HANDLED; } if (!strcmp (method, kServiceSetTime)) @@ -511,7 +516,7 @@ service_dispatch (DBusConnection *conn, DBusMessage *msg, void *data) return handle_can_set_time (conn, msg, state); else if (!strcmp (method, kServiceLastSyncInfo)) return handle_last_sync_info (conn, msg, state); - debug ("[dbus] invalid method supplied"); + verb_debug ("[dbus] invalid method supplied"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -564,7 +569,7 @@ init_dbus (struct state *tlsdate_state) goto err; } - debug ("[dbus] initialized"); + verb_debug ("[dbus] initialized"); return 0; err: tlsdate_state->dbus = NULL; diff --git a/src/dbus.h b/src/dbus.h index b166a7d..296ba86 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -31,13 +31,7 @@ struct dbus_event_data struct event *event; }; -#ifdef TLSDATED_MAIN void dbus_announce (struct state *); -#else -static inline void dbus_announce (struct state *global_state) -{ -} -#endif #else /* !HAVE_DBUS */ struct state; diff --git a/src/events/kickoff_time_sync.c b/src/events/kickoff_time_sync.c index 33c15ed..2ed2b0b 100644 --- a/src/events/kickoff_time_sync.c +++ b/src/events/kickoff_time_sync.c @@ -70,7 +70,7 @@ void action_invalidate_time (evutil_socket_t fd, short what, void *arg) { struct state *state = arg; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); /* If time is already invalid and being acquired, do nothing. */ if (state->last_sync_type == SYNC_TYPE_RTC && event_pending (state->events[E_TLSDATE], EV_TIMEOUT, NULL)) @@ -118,7 +118,7 @@ setup_event_timer_sync (struct state *state) void action_kickoff_time_sync (evutil_socket_t fd, short what, void *arg) { struct state *state = arg; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); time_t delta = state->clock_delta; int jitter = 0; if (check_continuity (&delta) > 0) @@ -134,7 +134,7 @@ void action_kickoff_time_sync (evutil_socket_t fd, short what, void *arg) } if (state->last_sync_type == SYNC_TYPE_NET) { - debug ("[event:%s] time in sync. skipping", __func__); + verb_debug ("[event:%s] time in sync. skipping", __func__); return; } /* Keep parity with run_tlsdate: for every wake, allow it to retry again. */ @@ -142,7 +142,7 @@ void action_kickoff_time_sync (evutil_socket_t fd, short what, void *arg) { state->tries -= 1; /* Don't bother re-triggering tlsdate */ - debug ("[event:%s] called while tries are in progress", __func__); + verb_debug ("[event:%s] called while tries are in progress", __func__); return; } /* Don't over-schedule if the first attempt hasn't fired. If a wake event @@ -152,7 +152,7 @@ void action_kickoff_time_sync (evutil_socket_t fd, short what, void *arg) */ if (event_pending (state->events[E_TLSDATE], EV_TIMEOUT, NULL)) { - debug ("[event:%s] called while tlsdate is pending", __func__); + verb_debug ("[event:%s] called while tlsdate is pending", __func__); return; } if (!state->events[E_RESOLVER]) diff --git a/src/events/route_up.c b/src/events/route_up.c index 280467d..23330bd 100644 --- a/src/events/route_up.c +++ b/src/events/route_up.c @@ -23,7 +23,7 @@ void action_stdin_wakeup (evutil_socket_t fd, short what, void *arg) { struct state *state = arg; char buf[1]; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); if (what != EV_READ) return; if (IGNORE_EINTR (read (fd, buf, sizeof (buf))) != sizeof (buf)) @@ -40,13 +40,13 @@ void action_stdin_wakeup (evutil_socket_t fd, short what, void *arg) void action_netlink_ready (evutil_socket_t fd, short what, void *arg) { struct routeup routeup_cfg; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); routeup_cfg.netlinkfd = fd; if (what & EV_READ) { if (routeup_process (&routeup_cfg) == 0) { - debug ("[event:%s] routes changed", __func__); + verb_debug ("[event:%s] routes changed", __func__); /* Fire off a proxy resolution attempt and a new sync request */ action_kickoff_time_sync (-1, EV_TIMEOUT, arg); } diff --git a/src/events/run_tlsdate.c b/src/events/run_tlsdate.c index c36da16..86f1236 100644 --- a/src/events/run_tlsdate.c +++ b/src/events/run_tlsdate.c @@ -18,7 +18,7 @@ void action_run_tlsdate (evutil_socket_t fd, short what, void *arg) { struct state *state = arg; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); if (state->last_sync_type == SYNC_TYPE_NET) { info ("[event:%s] called, but network time isn't needed"); diff --git a/src/events/save.c b/src/events/save.c index 637952a..8fa733e 100644 --- a/src/events/save.c +++ b/src/events/save.c @@ -23,7 +23,7 @@ void action_sync_and_save (evutil_socket_t fd, short what, void *arg) struct state *state = arg; time_t t = state->last_time; ssize_t bytes; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); /* For all non-net sources, don't write to disk by * flagging the time negative. We don't use negative * times and this won't effect shutdown (0) writes. diff --git a/src/events/sigchld.c b/src/events/sigchld.c index e164f2e..b4078b5 100644 --- a/src/events/sigchld.c +++ b/src/events/sigchld.c @@ -114,7 +114,7 @@ void action_sigchld (evutil_socket_t fd, short what, void *arg) { struct state *state = arg; - debug ("[event:%s] a child process has SIGCHLD'd!", __func__); + verb_debug ("[event:%s] a child process has SIGCHLD'd!", __func__); /* Process SIGCHLDs in two steps: death and stopped until all * pending children are sorted. */ diff --git a/src/events/sigterm.c b/src/events/sigterm.c index 0143d6f..ff09ab8 100644 --- a/src/events/sigterm.c +++ b/src/events/sigterm.c @@ -22,7 +22,7 @@ void action_sigterm (evutil_socket_t fd, short what, void *arg) struct timeval tv; info ("[event:%s] starting graceful shutdown . . .", __func__); state->exitting = 1; - if (gettimeofday (&tv, NULL)) + if (platform->time_get (&tv)) { pfatal ("[event:%s] couldn't gettimeofday to exit gracefully", __func__); } diff --git a/src/events/time_set.c b/src/events/time_set.c index 36f518f..edc30c9 100644 --- a/src/events/time_set.c +++ b/src/events/time_set.c @@ -86,7 +86,7 @@ action_time_set (evutil_socket_t fd, short what, void *arg) struct state *state = arg; int status = -1; ssize_t bytes = 0; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); bytes = IGNORE_EINTR (read (fd, &status, sizeof (status))); if (bytes == -1 && errno == EAGAIN) return; /* Catch next wake up */ diff --git a/src/events/tlsdate_status.c b/src/events/tlsdate_status.c index caa71fd..3e7601c 100644 --- a/src/events/tlsdate_status.c +++ b/src/events/tlsdate_status.c @@ -61,7 +61,7 @@ action_tlsdate_status (evutil_socket_t fd, short what, void *arg) struct state *state = arg; time_t t = 0; int ret = read_tlsdate_response (fd, &t); - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); if (ret < 0) { trigger_event (state, E_TLSDATE_TIMEOUT, 0); diff --git a/src/platform-cros.c b/src/platform-cros.c index 56c7115..5a9d7ab 100644 --- a/src/platform-cros.c +++ b/src/platform-cros.c @@ -192,7 +192,7 @@ handle_service_change (DBusConnection *connection, const char *pval; const char *service; dbus_error_init (&error); - debug ("[event:cros:%s]: fired", __func__); + verb_debug ("[event:cros:%s]: fired", __func__); /* TODO(wad) Track the current DefaultService only fire when it changes */ service = dbus_message_get_path (message); if (!service) @@ -232,7 +232,7 @@ handle_manager_change (DBusConnection *connection, DBusError error; const char *pname; const char *pval; - debug ("[event:cros:%s]: fired", __func__); + verb_debug ("[event:cros:%s]: fired", __func__); dbus_error_init (&error); if (!dbus_message_iter_init (message, &iter)) return DBUS_HANDLER_RESULT_HANDLED; @@ -251,7 +251,7 @@ handle_manager_change (DBusConnection *connection, return DBUS_HANDLER_RESULT_HANDLED; dbus_message_iter_get_basic (&subiter, &pval); /* TODO(wad) Filter on the currently active service in pval. */ - debug ("[event:cros:%s] service change on path %s", + verb_debug ("[event:cros:%s] service change on path %s", __func__, pval); action_kickoff_time_sync (-1, EV_TIMEOUT, ctx->state); return DBUS_HANDLER_RESULT_HANDLED; @@ -266,7 +266,7 @@ handle_suspend_done (DBusConnection *connection, DBusMessageIter iter; DBusError error; const char *pname; - debug ("[event:cros:%s]: fired", __func__); + verb_debug ("[event:cros:%s]: fired", __func__); /* Coming back from resume, trigger a continuity and time * check just in case none of the other events happen. */ @@ -287,7 +287,7 @@ handle_proxy_change (DBusConnection *connection, char time_host[MAX_PROXY_URL]; int url_len = 0; struct source *src = ctx->state->opts.sources; - debug ("[event:cros:%s]: fired", __func__); + verb_debug ("[event:cros:%s]: fired", __func__); if (ctx->state->opts.cur_source && ctx->state->opts.cur_source->next) src = ctx->state->opts.cur_source->next; if (!ctx->state->resolving) @@ -337,7 +337,7 @@ handle_dbus_change (DBusConnection *connection, DBusMessageIter iter; DBusError error; const char *pname; - debug ("[event:cros:%s]: fired", __func__); + verb_debug ("[event:cros:%s]: fired", __func__); dbus_error_init (&error); if (!dbus_message_iter_init (message, &iter)) return DBUS_HANDLER_RESULT_HANDLED; @@ -359,7 +359,7 @@ action_resolve_proxy (evutil_socket_t fd, short what, void *arg) struct dbus_state *dbus_state = ctx->state->dbus; DBusConnection *conn = dbus_state->conn; struct source *src = ctx->state->opts.sources; - debug ("[event:%s] fired", __func__); + verb_debug ("[event:%s] fired", __func__); /* Emulate tlsdate-monitor.c:build_argv and choose the next source */ if (ctx->state->opts.cur_source && ctx->state->opts.cur_source->next) src = ctx->state->opts.cur_source->next; @@ -447,7 +447,7 @@ dbus_filter (DBusConnection *connection, DBusMessage *message, void *data) info ("[cros] unknown DBus METHOD_RETURN seen: %u", serial); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - debug ("[cros] unknown message received: " + verb_debug ("[cros] unknown message received: " "type=%s dest=%s interface=%s member=%s path=%s sig=%s error_name=%s", dbus_message_type_to_string (dbus_message_get_type (message)), dbus_message_get_destination (message), diff --git a/src/rtc.h b/src/rtc.h new file mode 100644 index 0000000..2017e96 --- /dev/null +++ b/src/rtc.h @@ -0,0 +1,9 @@ +#ifndef RTC_H +#define RTC_H + +struct rtc_handle +{ + int fd; +}; + +#endif /* RTC_H */ diff --git a/src/seccomp.c b/src/seccomp.c index bc25e4c..7a7b904 100644 --- a/src/seccomp.c +++ b/src/seccomp.c @@ -88,7 +88,6 @@ enable_setter_seccomp (void) SC_ALLOW (write), SC_ALLOW (pwritev), SC_ALLOW (ioctl), /* TODO(wad) filter for fd and RTC_SET_TIME */ - SC_ALLOW (restart_syscall), SC_ALLOW (exit_group), SC_ALLOW (exit), BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), diff --git a/src/tlsdate-helper.c b/src/tlsdate-helper.c index eea4b00..e193b22 100644 --- a/src/tlsdate-helper.c +++ b/src/tlsdate-helper.c @@ -1356,7 +1356,7 @@ main(int argc, char **argv) (void) munmap (time_map, sizeof (uint32_t)); _exit (0); } - if (ssl_child != waitpid (ssl_child, &status, 0)) + if (ssl_child != platform->process_wait (ssl_child, &status, 1)) die ("waitpid failed: %s\n", strerror (errno)); if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)) )) die ("child process failed in SSL handshake\n"); diff --git a/src/tlsdate-monitor.c b/src/tlsdate-monitor.c index 26b4394..032fbe1 100644 --- a/src/tlsdate-monitor.c +++ b/src/tlsdate-monitor.c @@ -81,7 +81,7 @@ tlsdate (struct state *state) perror ("fork() failed!"); return -1; default: - debug ("[tlsdate-monitor] spawned tlsdate: %d", pid); + verb_debug ("[tlsdate-monitor] spawned tlsdate: %d", pid); state->tlsdate_pid = pid; return 0; } diff --git a/src/tlsdate-setter.c b/src/tlsdate-setter.c index d14a2f2..179327e 100644 --- a/src/tlsdate-setter.c +++ b/src/tlsdate-setter.c @@ -9,14 +9,12 @@ #include #include -#include #include #include #include #include #include #include -#include #include #include @@ -32,43 +30,7 @@ int save_timestamp_to_fd (int fd, time_t t) { - struct iovec iov[1]; - ssize_t ret; - iov[0].iov_base = &t; - iov[0].iov_len = sizeof (t); - ret = IGNORE_EINTR (pwritev (fd, iov, 1, 0)); - /* TODO(wad) platform->file_write(path, &t, sizeof(t)) */ - if (ret != sizeof (t)) - return 1; - return 0; -} - -/* - * Set the hardware clock referred to by fd (which should be a descriptor to - * some device that implements the interface documented in rtc(4)) to the system - * time. See hwclock(8) for details of why this is important. If we fail, we - * just return - there's nothing the caller can really do about a failure of - * this function except try later. - */ -int -sync_hwclock (int fd, time_t sec) -{ - struct tm tm; - struct rtc_time rtctm; - /* TODO(wad) if (platform->time_get(&tv)) */ - gmtime_r (&sec, &tm); - /* these structs are identical, but separately defined */ - rtctm.tm_sec = tm.tm_sec; - rtctm.tm_min = tm.tm_min; - rtctm.tm_hour = tm.tm_hour; - rtctm.tm_mday = tm.tm_mday; - rtctm.tm_mon = tm.tm_mon; - rtctm.tm_year = tm.tm_year; - rtctm.tm_wday = tm.tm_wday; - rtctm.tm_yday = tm.tm_yday; - rtctm.tm_isdst = tm.tm_isdst; - /* TODO(wad) if (platform->rtc_write(rtc_handle, &tv)) */ - return ioctl (fd, RTC_SET_TIME, &rtctm); + return platform->file_write(fd, &t, sizeof (t)); } void @@ -190,7 +152,7 @@ time_setter_coprocess (int time_fd, int notify_fd, struct state *state) goto notify_and_die; } if (state->opts.should_sync_hwclock && - sync_hwclock (state->hwclock_fd, tv.tv_sec)) + platform->rtc_write(&state->hwclock, &tv)) { status = SETTER_NO_RTC; goto notify_and_die; diff --git a/src/tlsdate.h b/src/tlsdate.h index 6f9f799..228a342 100644 --- a/src/tlsdate.h +++ b/src/tlsdate.h @@ -22,6 +22,8 @@ #include #include +#include "src/rtc.h" + #define DEFAULT_HOST "www.ptb.de" #define DEFAULT_PORT "443" #define DEFAULT_PROXY "none" @@ -153,6 +155,7 @@ enum event_id_t }; struct event_base; + /* This struct is used for passing tlsdated runtime state between * events/ in its event loop. */ @@ -168,7 +171,7 @@ struct state time_t last_time; char timestamp_path[PATH_MAX]; - int hwclock_fd; + struct rtc_handle hwclock; char dynamic_proxy[MAX_PROXY_URL]; /* Event triggered events */ diff --git a/src/tlsdated-unittest.c b/src/tlsdated-unittest.c index 0e22ee3..3c2986a 100644 --- a/src/tlsdated-unittest.c +++ b/src/tlsdated-unittest.c @@ -184,7 +184,7 @@ runner (FIXTURE_DATA (tlsdate) *self, time_t *newtime) return 1; } -TEST_F (tlsdate, runner) +TEST_F (tlsdate, runner_multi) { struct source source = { @@ -325,69 +325,12 @@ FIXTURE_TEARDOWN(mock_platform) { /* TODO(wad) add a leap test. */ -/* - * The stuff below this line is ugly. For a lot of these mock functions, we want - * to smuggle some state (our success) back to the caller, but there's no angle - * for that, so we're basically stuck with some static variables to store - * expectations and successes/failures. This could also be done with nested - * functions, but only gcc supports them. - */ -static const time_t sync_hwclock_expected = 12345678; - -static int sync_hwclock_time_get(struct timeval *tv) { - tv->tv_sec = sync_hwclock_expected; - tv->tv_usec = 0; - return 0; -} - -static int sync_hwclock_rtc_write(void *handle, const struct timeval *tv) { - *(int *)handle = tv->tv_sec == sync_hwclock_expected; - return 0; -} - -/* TODO(wad) -TEST_F(mock_platform, sync_hwclock) { - int ok = 0; - void *fake_handle = (void *)&ok; +TEST_F(mock_platform, time_setter) { + /* self->platform.time_get = sync_hwclock_time_get; self->platform.rtc_write = sync_hwclock_rtc_write; - sync_hwclock(fake_handle); - ASSERT_EQ(ok, 1); -} -*/ - -static const time_t sync_and_save_expected = 12345678; - -static int sync_and_save_time_get(struct timeval *tv) { - tv->tv_sec = sync_and_save_expected; - tv->tv_usec = 0; - return 0; -} - -static int sync_and_save_rtc_write(void *handle, const struct timeval *tv) { - *(int *)handle += tv->tv_sec == sync_and_save_expected; - return 0; -} - -static int sync_and_save_file_write_ok = 0; - -static int sync_and_save_file_write(const char *path, void *buf, size_t sz) { - if (!strcmp(path, timestamp_path)) - sync_and_save_file_write_ok++; - return 0; -} - -/* TODO(wad) TODO ? -TEST_F(mock_platform, sync_and_save) { - int nosave_ok = 0; - self->platform.time_get = sync_and_save_time_get; - self->platform.rtc_write = sync_and_save_rtc_write; - self->platform.file_write = sync_and_save_file_write; - sync_and_save(&sync_and_save_file_write_ok, 1); - ASSERT_EQ(sync_and_save_file_write_ok, 2); - sync_and_save(&nosave_ok, 0); - ASSERT_EQ(nosave_ok, 1); + */ + ASSERT_EQ(0, 1); } -*/ TEST_HARNESS_MAIN diff --git a/src/tlsdated.c b/src/tlsdated.c index ad4f4ca..09a5489 100644 --- a/src/tlsdated.c +++ b/src/tlsdated.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -59,30 +58,20 @@ is_sane_time (time_t ts) int load_disk_timestamp (const char *path, time_t * t) { -/* TODO(wad) - time_t tmpt; - if (platform->file_read(path, &tmpt, sizeof(tmpt))) { - info("can't load time file"); - return -1; - } -*/ - struct iovec iov[1]; - int fd = open (path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); - time_t tmpt; - iov[0].iov_base = &tmpt; - iov[0].iov_len = sizeof (tmpt); + int fd = platform->file_open (path, 0 /* RDONLY */, 1 /* CLOEXEC */); + time_t tmpt = 0; if (fd < 0) { perror ("Can't open %s for reading", path); return -1; } - if (preadv (fd, iov, 1, 0) != sizeof (tmpt)) + if (platform->file_read(fd, &tmpt, sizeof(tmpt))) { perror ("Can't read seconds from %s", path); - close (fd); + platform->file_close (fd); return -1; } - close (fd); + platform->file_close (fd); if (!is_sane_time (tmpt)) { error ("Disk timestamp is not sane: %ld", tmpt); @@ -425,19 +414,19 @@ cleanup_main (struct state *state) } } /* The other half was closed above. */ - close (state->tlsdate_monitor_fd); + platform->file_close (state->tlsdate_monitor_fd); if (state->tlsdate_pid) { - kill (state->tlsdate_pid, SIGKILL); - waitpid (state->tlsdate_pid, NULL, WNOHANG); + platform->process_signal (state->tlsdate_pid, SIGKILL); + platform->process_wait (state->tlsdate_pid, NULL, 0 /* !forever */); } /* Best effort to tear it down if it is still alive. */ close(state->setter_notify_fd); close(state->setter_save_fd); if (state->setter_pid) { - kill (state->setter_pid, SIGKILL); - waitpid (state->setter_pid, NULL, WNOHANG); + platform->process_signal (state->setter_pid, SIGKILL); + platform->process_wait (state->setter_pid, NULL, 0 /* !forever */); } /* TODO(wad) Add dbus_cleanup() */ if (state->base) @@ -473,12 +462,11 @@ main (int argc, char *argv[], char *envp[]) add_source_to_conf (&state.opts, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_PROXY); state.base = base; state.envp = envp; - state.hwclock_fd = -1; state.backoff = state.opts.wait_between_tries; /* TODO(wad) move this into setup_time_setter */ - /* grab a handle to /dev/rtc for sync_hwclock() */ + /* grab a handle to /dev/rtc for time-setter. */ if (state.opts.should_sync_hwclock && - (state.hwclock_fd = open (DEFAULT_RTC_DEVICE, O_RDONLY)) < 0) + platform->rtc_open(&state.hwclock)) { pinfo ("can't open hwclock fd"); state.opts.should_sync_hwclock = 0; @@ -497,8 +485,7 @@ main (int argc, char *argv[], char *envp[]) goto out; } /* release the hwclock now that the time-setter is running. */ - close (state.hwclock_fd); - state.hwclock_fd = -1; + platform->rtc_close (&state.hwclock); /* drop privileges before touching any untrusted data */ drop_privs_to (state.opts.user, state.opts.group); /* register a signal handler to save time at shutdown */ diff --git a/src/util.c b/src/util.c index 9c06e73..f9fb8ca 100644 --- a/src/util.c +++ b/src/util.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -136,30 +137,34 @@ drop_privs_to (const char *user, const char *group) } #ifdef ENABLE_RTC -struct rtc_handle +int rtc_open(struct rtc_handle *h) { - int fd; -}; - -void *rtc_open() -{ - struct rtc_handle *h = malloc(sizeof *h); + if (!h) + return -1; + h->fd = -1; + /* TODO: Use platform->file_open but drop NOFOLLOW? */ h->fd = open(DEFAULT_RTC_DEVICE, O_RDONLY); if (h->fd < 0) - { + { pinfo("can't open rtc"); - free(h); - return NULL; + return -1; } - return h; + return 0; } -int rtc_write(void *handle, const struct timeval *tv) +/* + * Set the hardware clock referred to by fd (which should be a descriptor to + * some device that implements the interface documented in rtc(4)) to the system + * time. See hwclock(8) for details of why this is important. If we fail, we + * just return - there's nothing the caller can really do about a failure of + * this function except try later. + */ +int rtc_write(struct rtc_handle *handle, const struct timeval *tv) { struct tm tmr; struct tm *tm; struct rtc_time rtctm; - int fd = ((struct rtc_handle *)handle)->fd; + int fd = handle->fd; tm = gmtime_r (&tv->tv_sec, &tmr); @@ -184,11 +189,11 @@ int rtc_write(void *handle, const struct timeval *tv) return 0; } -int rtc_read(void *handle, struct timeval *tv) +int rtc_read(struct rtc_handle *handle, struct timeval *tv) { struct tm tm; struct rtc_time rtctm; - int fd = ((struct rtc_handle *)handle)->fd; + int fd = handle->fd; if (ioctl (fd, RTC_RD_TIME, &rtctm)) { @@ -212,75 +217,72 @@ int rtc_read(void *handle, struct timeval *tv) return 0; } -int rtc_close(void *handle) +int rtc_close(struct rtc_handle *handle) { struct rtc_handle *h = handle; - close(h->fd); - free(h); + platform->file_close(h->fd); + h->fd = -1; return 0; } #endif -int file_write(const char *path, void *buf, size_t sz) +int file_write(int fd, void *buf, size_t sz) { - char tmp[PATH_MAX]; - int oflags = O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC; - int perms = S_IRUSR | S_IWUSR; - int fd; - - if (snprintf(tmp, sizeof(tmp), path, kTempSuffix) >= sizeof(tmp)) - { - pinfo("path %s too long to use", path); - exit(1); - } - - if ((fd = open(tmp, oflags, perms)) < 0) - { - pinfo("open(%s) failed", tmp); - return 1; - } - - if (write(fd, buf, sz) != sz) - { - pinfo("write() failed"); - close(fd); - return 1; - } - - if (close(fd)) - { - pinfo("close() failed"); - return 1; - } - - if (rename(tmp, path)) - { - pinfo("rename() failed"); - return 1; + struct iovec iov[1]; + ssize_t ret; + iov[0].iov_base = buf; + iov[0].iov_len = sz; + ret = IGNORE_EINTR (pwritev (fd, iov, 1, 0)); + if (ret != sz) + { + return -1; } - return 0; } -int file_read(const char *path, void *buf, size_t sz) +int file_open(const char *path, int write, int cloexec) { - int fd = open(path, O_RDONLY | O_NOFOLLOW); + int fd; + int oflags = cloexec ? O_CLOEXEC : 0; + if (write) + { + int perms = S_IRUSR | S_IWUSR; + oflags |= O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC; + /* Rely on atomic write calls rather than rename() calls. */ + fd = open(path, oflags, perms); + } + else + { + oflags |= O_RDONLY | O_NOFOLLOW; + fd = open(path, oflags); + } if (fd < 0) - { + { pinfo("open(%s) failed", path); - return 1; - } - - if (read(fd, buf, sz) != sz) - { - pinfo("read() failed"); - close(fd); - return 1; + return -1; } + return fd; +} +int file_close(int fd) +{ return close(fd); } +int file_read(int fd, void *buf, size_t sz) +{ + struct iovec iov[1]; + iov[0].iov_base = buf; + iov[0].iov_len = sz; + if (preadv (fd, iov, 1, 0) != sz) + { + /* Returns -1 on read failure */ + return -1; + } + /* Returns 0 on a successful buffer fill. */ + return 0; +} + int time_get(struct timeval *tv) { return gettimeofday(tv, NULL); @@ -297,6 +299,17 @@ int pgrp_kill(void) return kill(-grp, SIGKILL); } +int process_signal(pid_t pid, int signal) +{ + return kill (pid, signal); +} + +pid_t process_wait(pid_t pid, int *status, int forever) +{ + int flag = forever ? 0 : WNOHANG; + return waitpid (pid, status, flag); +} + static struct platform default_platform = { #ifdef ENABLE_RTC .rtc_open = rtc_open, @@ -305,13 +318,18 @@ static struct platform default_platform = { .rtc_close = rtc_close, #endif + .file_open = file_open, + .file_close = file_close, .file_write = file_write, .file_read = file_read, .time_get = time_get, .pgrp_enter = pgrp_enter, - .pgrp_kill = pgrp_kill + .pgrp_kill = pgrp_kill, + + .process_signal = process_signal, + .process_wait = process_wait }; struct platform *platform = &default_platform; diff --git a/src/util.h b/src/util.h index 2d7efb6..b0600c3 100644 --- a/src/util.h +++ b/src/util.h @@ -13,6 +13,8 @@ #include #include +#include "src/rtc.h" + #ifdef TARGET_OS_HAIKU #include #endif @@ -33,17 +35,6 @@ void verb (const char *fmt, ...); void verb_debug (const char *fmt, ...); extern void logat (int isverbose, const char *fmt, ...); -#ifdef NDEBUG -# define _SUPPORT_DEBUG 0 -#else -# define _SUPPORT_DEBUG 1 -#endif - -#define debug(fmt, ...) do { \ - if (_SUPPORT_DEBUG) \ - logat(1, fmt, ## __VA_ARGS__); \ -} while (0) - #define info(fmt, ...) logat(1, fmt, ## __VA_ARGS__) #define pinfo(fmt, ...) logat(1, fmt ": %s", ## __VA_ARGS__, strerror(errno)) #define error(fmt, ...) logat(0, fmt, ## __VA_ARGS__) @@ -66,23 +57,25 @@ struct state; enum event_id_t; void trigger_event (struct state *state, enum event_id_t e, int sec); -/* like wait(), but with a timeout. Returns ordinary fork() error codes, or - * ETIMEDOUT. */ -pid_t wait_with_timeout(int *status, int timeout_secs); - struct platform { - void *(*rtc_open)(void); - int (*rtc_write)(void *handle, const struct timeval *tv); - int (*rtc_read)(void *handle, struct timeval *tv); - int (*rtc_close)(void *handle); + int (*rtc_open)(struct rtc_handle *); + int (*rtc_write)(struct rtc_handle *, const struct timeval *tv); + int (*rtc_read)(struct rtc_handle *, struct timeval *tv); + int (*rtc_close)(struct rtc_handle *); - int (*file_write)(const char *path, void *buf, size_t sz); - int (*file_read)(const char *path, void *buf, size_t sz); + int (*file_open)(const char *path, int write, int cloexec); + int (*file_close)(int fd); + /* Atomic file write and read */ + int (*file_write)(int fd, void *buf, size_t sz); + int (*file_read)(int fd, void *buf, size_t sz); int (*time_get)(struct timeval *tv); int (*pgrp_enter)(void); int (*pgrp_kill)(void); + + int (*process_signal)(pid_t pid, int sig); + int (*process_wait)(pid_t pid, int *status, int timeout); }; extern struct platform *platform; diff --git a/tests/run-idle/runs b/tests/run-idle/runs index 7f8f011..d00491f 100644 --- a/tests/run-idle/runs +++ b/tests/run-idle/runs @@ -1 +1 @@ -7 +1 diff --git a/tests/run-routeup/runs b/tests/run-routeup/runs index d00491f..0cfbf08 100644 --- a/tests/run-routeup/runs +++ b/tests/run-routeup/runs @@ -1 +1 @@ -1 +2 -- cgit v1.2.3