Adjust clock gradually when possible

Use adjtime instead of settimeofday when device time is within 30
seconds of the real time. The clock jumping backwards can make certain
logs difficult to understand, and adjtime preserves clock monotonicity.

BUG=chromium:907304
TEST=ensure clock doesn't move backwards after boot

Change-Id: I4efd081c456cecd228037aa9f8d0b927baaf2029
Reviewed-on: https://chromium-review.googlesource.com/1344802
Commit-Ready: Christopher Morin <cmtm@google.com>
Tested-by: Christopher Morin <cmtm@google.com>
Reviewed-by: Dan Erat <derat@chromium.org>
diff --git a/src/events/time_set.c b/src/events/time_set.c
index 9b3c7f3..de85007 100644
--- a/src/events/time_set.c
+++ b/src/events/time_set.c
@@ -61,7 +61,7 @@
       error ("[event:%s] time setter exited gracefully", __func__);
       break;
     case SETTER_SET_ERR:
-      error ("[event:%s] time setter could not settimeofday()", __func__);
+      error ("[event:%s] time setter could not set time", __func__);
       break;
     case SETTER_NO_RTC:
       error ("[event:%s] time setter could sync rtc", __func__);
@@ -72,6 +72,9 @@
     case SETTER_READ_ERR:
       error ("[event:%s] time setter could not read time", __func__);
       break;
+    case SETTER_GETTIME_ERR:
+      error ("[event:%s] time setter could not gettimeofday()", __func__);
+      break;
     default:
       error ("[event:%s] received bogus status from time setter: %d",
              __func__, status);
diff --git a/src/seccomp.c b/src/seccomp.c
index 41cd6f7..aff26e5 100644
--- a/src/seccomp.c
+++ b/src/seccomp.c
@@ -104,6 +104,8 @@
     SC_ALLOW (close),
     SC_ALLOW (munmap),
 
+    SC_ALLOW (adjtimex),
+    SC_ALLOW (gettimeofday),
     SC_ALLOW (settimeofday),
     SC_ALLOW (read),
     SC_ALLOW (write),
diff --git a/src/tlsdate-setter.c b/src/tlsdate-setter.c
index fccb987..f5729b4 100644
--- a/src/tlsdate-setter.c
+++ b/src/tlsdate-setter.c
@@ -181,7 +181,26 @@
           status = SETTER_BAD_TIME;
           if (!state->opts.dry_run)
             {
-              if (settimeofday (&tv, NULL) < 0)
+              struct timeval our_time = { 0, 0 };
+              if (gettimeofday (&our_time, NULL) < 0)
+                {
+                  status = SETTER_GETTIME_ERR;
+                  goto notify_and_die;
+                }
+              struct timeval delta = {tv.tv_sec - our_time.tv_sec, 0};
+
+              /* Adjust clock gradually if it's close enough to the right time.
+               */
+              if (-ADJTIME_THRESHOLD < delta.tv_sec &&
+                  delta.tv_sec < ADJTIME_THRESHOLD)
+                {
+                  if (adjtime (&delta, NULL) < 0)
+                    {
+                      status = SETTER_SET_ERR;
+                      goto notify_and_die;
+                    }
+                }
+              else if (settimeofday (&tv, NULL) < 0)
                 {
                   status = SETTER_SET_ERR;
                   goto notify_and_die;
diff --git a/src/tlsdate.h b/src/tlsdate.h
index 9a836c1..c118d89 100644
--- a/src/tlsdate.h
+++ b/src/tlsdate.h
@@ -39,6 +39,7 @@
 #define SUBPROCESS_TRIES 10
 #define SUBPROCESS_WAIT_BETWEEN_TRIES 10
 #define RESOLVER_TIMEOUT 30
+#define ADJTIME_THRESHOLD 30
 /* Invalidate the network sync once per day. */
 #define STEADY_STATE_INTERVAL (60*60*24)
 /* Check if the clock has jumped every four hours. */
@@ -77,6 +78,7 @@
 #define SETTER_SET_ERR 5
 #define SETTER_NO_SBOX 6
 #define SETTER_NO_RTC 7
+#define SETTER_GETTIME_ERR 8
 
 #define TEST_HOST 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', \
                   'c', 'o', 'm'