Add new monotonic_now() wrapper so that timeouts are unaffected by

system clock changes
This commit is contained in:
Matt Johnston 2014-03-13 23:50:09 +08:00
parent 2b599df57a
commit e767bbb41f
9 changed files with 61 additions and 9 deletions

View File

@ -270,7 +270,7 @@ static void kexinitialise() {
ses.kexstate.our_first_follows_matches = 0;
ses.kexstate.lastkextime = time(NULL);
ses.kexstate.lastkextime = monotonic_now();
}

View File

@ -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");

View File

@ -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.

View File

@ -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
}

View File

@ -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_ */

View File

@ -151,7 +151,7 @@ void write_packet() {
}
#endif
now = time(NULL);
now = monotonic_now();
ses.last_trx_packet_time = now;
if (!all_ignore) {

View File

@ -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) {

View File

@ -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 */

View File

@ -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);