diff options
-rw-r--r-- | common-kex.c | 2 | ||||
-rw-r--r-- | common-session.c | 3 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | dbutil.c | 43 | ||||
-rw-r--r-- | dbutil.h | 5 | ||||
-rw-r--r-- | packet.c | 2 | ||||
-rw-r--r-- | process-packet.c | 2 | ||||
-rw-r--r-- | session.h | 7 | ||||
-rw-r--r-- | svr-session.c | 2 |
9 files changed, 61 insertions, 9 deletions
diff --git a/common-kex.c b/common-kex.c index 10ea554..f5119d2 100644 --- a/common-kex.c +++ b/common-kex.c @@ -270,7 +270,7 @@ static void kexinitialise() { ses.kexstate.our_first_follows_matches = 0; - ses.kexstate.lastkextime = time(NULL); + ses.kexstate.lastkextime = monotonic_now(); } diff --git a/common-session.c b/common-session.c index 998bf0e..6bcb7fa 100644 --- a/common-session.c +++ b/common-session.c @@ -397,8 +397,7 @@ void send_msg_ignore() { 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 --git a/configure.ac b/configure.ac index 8095280..29c0d40 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,10 @@ AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline ) 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. @@ -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 @@ int constant_time_memcmp(const void* a, const void *b, size_t n) 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 + +} + @@ -106,4 +106,9 @@ int m_str_to_uint(const char* str, unsigned int *val); /* 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_ */ @@ -151,7 +151,7 @@ void write_packet() { } #endif - now = time(NULL); + now = monotonic_now(); ses.last_trx_packet_time = now; if (!all_ignore) { diff --git a/process-packet.c b/process-packet.c index 3659cc0..6cbcfc7 100644 --- a/process-packet.c +++ b/process-packet.c @@ -52,7 +52,7 @@ void process_packet() { 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) { @@ -106,7 +106,8 @@ struct sshsession { 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 @@ struct sshsession { 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 --git a/svr-session.c b/svr-session.c index e9fde24..2adcb01 100644 --- a/svr-session.c +++ b/svr-session.c @@ -95,7 +95,7 @@ void svr_session(int sock, int childpipe) { 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); |