changeset 928:7cd89d4e0335

Add new monotonic_now() wrapper so that timeouts are unaffected by system clock changes
author Matt Johnston <matt@ucc.asn.au>
date Thu, 13 Mar 2014 23:50:09 +0800
parents 122fb3532038
children 9d40ed1da686
files common-kex.c common-session.c configure.ac dbutil.c dbutil.h packet.c process-packet.c session.h svr-session.c
diffstat 9 files changed, 61 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/common-kex.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/common-kex.c	Thu Mar 13 23:50:09 2014 +0800
@@ -270,7 +270,7 @@
 
 	ses.kexstate.our_first_follows_matches = 0;
 
-	ses.kexstate.lastkextime = time(NULL);
+	ses.kexstate.lastkextime = monotonic_now();
 
 }
 
--- a/common-session.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/common-session.c	Thu Mar 13 23:50:09 2014 +0800
@@ -397,8 +397,7 @@
 static void checktimeouts() {
 
 	time_t now;
-
-	now = time(NULL);
+	now = monotonic_now();
 	
 	if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
 			dropbear_close("Timeout before auth");
--- a/configure.ac	Thu Mar 13 23:08:47 2014 +0800
+++ b/configure.ac	Thu Mar 13 23:50:09 2014 +0800
@@ -361,6 +361,10 @@
 AC_CHECK_FUNCS(setutxent utmpxname)
 AC_CHECK_FUNCS(logout updwtmp logwtmp)
 
+# OS X monotonic time
+AC_CHECK_HEADERS([mach/mach_time.h])
+AC_CHECK_FUNCS(mach_absolute_time)
+
 AC_ARG_ENABLE(bundled-libtom,
 [  --enable-bundled-libtom       Force using bundled libtomcrypt/libtommath even if a system version exists.
   --disable-bundled-libtom      Force using system libtomcrypt/libtommath, fail if it does not exist.
--- a/dbutil.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/dbutil.c	Thu Mar 13 23:50:09 2014 +0800
@@ -48,6 +48,19 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
+#include "config.h"
+
+#ifdef __linux__
+#define _GNU_SOURCE
+/* To call clock_gettime() directly */
+#include <sys/syscall.h>
+#endif /* __linux */
+
+#ifdef HAVE_MACH_MACH_TIME_H
+#include <mach/mach_time.h>
+#include <mach/mach.h>
+#endif
+
 #include "includes.h"
 #include "dbutil.h"
 #include "buffer.h"
@@ -932,3 +945,33 @@
 	return c;
 }
 
+time_t monotonic_now() {
+
+#if defined(__linux__) && defined(SYS_clock_gettime)
+	/* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32. Probably cheaper. */
+#ifndef CLOCK_MONOTONIC_COARSE
+#define CLOCK_MONOTONIC_COARSE 6
+#endif
+	static clockid_t clock_source = CLOCK_MONOTONIC_COARSE;
+	struct timespec ts;
+
+	if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) {
+		clock_source = CLOCK_MONOTONIC;
+		syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts);
+	}
+	return ts.tv_sec;
+#elif defined(HAVE_MACH_ABSOLUTE_TIME)
+	/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
+	mach_timebase_info_data_t timebase_info;
+	if (timebase_info.denom == 0) {
+		mach_timebase_info(&timebase_info);
+	}
+	return mach_absolute_time() * timebase_info.numer / timebase_info.denom
+		/ 1e9;
+#else 
+	/* Fallback for everything else - this will sometimes go backwards */
+	return time(NULL);
+#endif
+
+}
+
--- a/dbutil.h	Thu Mar 13 23:08:47 2014 +0800
+++ b/dbutil.h	Thu Mar 13 23:50:09 2014 +0800
@@ -106,4 +106,9 @@
 /* Returns 0 if a and b have the same contents */
 int constant_time_memcmp(const void* a, const void *b, size_t n);
 
+/* Returns a time in seconds that doesn't go backwards - does not correspond to
+a real-world clock */
+time_t monotonic_now();
+
+
 #endif /* _DBUTIL_H_ */
--- a/packet.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/packet.c	Thu Mar 13 23:50:09 2014 +0800
@@ -151,7 +151,7 @@
 	}
 
 #endif
-	now = time(NULL);
+	now = monotonic_now();
 	ses.last_trx_packet_time = now;
 
 	if (!all_ignore) {
--- a/process-packet.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/process-packet.c	Thu Mar 13 23:50:09 2014 +0800
@@ -52,7 +52,7 @@
 
 	ses.lastpacket = type;
 
-	ses.last_packet_time = time(NULL);
+	ses.last_packet_time = monotonic_now();
 
 	/* These packets we can receive at any time */
 	switch(type) {
--- a/session.h	Thu Mar 13 23:08:47 2014 +0800
+++ b/session.h	Thu Mar 13 23:50:09 2014 +0800
@@ -106,7 +106,8 @@
 
 	time_t connect_time; /* time the connection was established
 							(cleared after auth once we're not
-							respecting AUTH_TIMEOUT any more) */
+							respecting AUTH_TIMEOUT any more).
+							A monotonic time, not realworld */
 
 	int sock_in;
 	int sock_out;
@@ -147,10 +148,10 @@
 						   race-free signal handling */
 						
 	time_t last_trx_packet_time; /* time of the last packet transmission, for
-							keepalive purposes */
+							keepalive purposes. Not real-world clock */
 
 	time_t last_packet_time; /* time of the last packet transmission or receive, for
-								idle timeout purposes */
+								idle timeout purposes. Not real-world clock */
 
 
 	/* KEX/encryption related */
--- a/svr-session.c	Thu Mar 13 23:08:47 2014 +0800
+++ b/svr-session.c	Thu Mar 13 23:50:09 2014 +0800
@@ -95,7 +95,7 @@
 	chaninitialise(svr_chantypes);
 	svr_chansessinitialise();
 
-	ses.connect_time = time(NULL);
+	ses.connect_time = monotonic_now();
 
 	/* for logging the remote address */
 	get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0);