# HG changeset patch # User Matt Johnston # Date 1394725809 -28800 # Node ID 7cd89d4e033534d8899b9746f94b44ec4aaa53c3 # Parent 122fb35320385f7929f6a7d5c3a3a9a88d6209bb Add new monotonic_now() wrapper so that timeouts are unaffected by system clock changes diff -r 122fb3532038 -r 7cd89d4e0335 common-kex.c --- 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(); } diff -r 122fb3532038 -r 7cd89d4e0335 common-session.c --- 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"); diff -r 122fb3532038 -r 7cd89d4e0335 configure.ac --- 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. diff -r 122fb3532038 -r 7cd89d4e0335 dbutil.c --- 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 +#endif /* __linux */ + +#ifdef HAVE_MACH_MACH_TIME_H +#include +#include +#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 + +} + diff -r 122fb3532038 -r 7cd89d4e0335 dbutil.h --- 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_ */ diff -r 122fb3532038 -r 7cd89d4e0335 packet.c --- 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) { diff -r 122fb3532038 -r 7cd89d4e0335 process-packet.c --- 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) { diff -r 122fb3532038 -r 7cd89d4e0335 session.h --- 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 */ diff -r 122fb3532038 -r 7cd89d4e0335 svr-session.c --- 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);