Dropbear 2014.64

NiLuJe
Mon Jul 28 05:56:07 WST 2014


Hello, I was having a bit of a problem with the new monotonic_call() stuff
on some old systems (again, a Kindle 2 w/ a fairly old glibc & kernel duo),
so, inspired from what's done in OpenSSH, I tweaked it to do runtime checks
w/ clock_gettime (and not the syscall, which really didn't play nice for
some reason).

It might not be terribly pretty, but it fixed it for me ;).

[Sorry for the whitespace noise]

----

diff -r 9a48d8bcfeed configure.ac
--- a/configure.ac	Sun Jul 27 23:11:52 2014 +0800
+++ b/configure.ac	Sun Jul 27 23:38:47 2014 +0200
@@ -636,6 +636,9 @@
 
 AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME))
 
+AC_SEARCH_LIBS([clock_gettime], [rt],
+	[AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])])
+
 # Solaris needs ptmx
 if test -z "$no_ptmx_check" ; then
 	if test x"$cross_compiling" = x"no" ; then
diff -r 9a48d8bcfeed dbutil.c
--- a/dbutil.c	Sun Jul 27 23:11:52 2014 +0800
+++ b/dbutil.c	Sun Jul 27 23:38:47 2014 +0200
@@ -1,19 +1,19 @@
 /*
  * Dropbear - a SSH2 server
- * 
+ *
  * Copyright (c) 2002,2003 Matt Johnston
  * All rights reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -50,12 +50,6 @@
 
 #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>
@@ -69,9 +63,9 @@
 
 #define MAX_FMT 100
 
-static void generic_dropbear_exit(int exitcode, const char* format, 
+static void generic_dropbear_exit(int exitcode, const char* format,
 		va_list param) ATTRIB_NORETURN;
-static void generic_dropbear_log(int priority, const char* format, 
+static void generic_dropbear_log(int priority, const char* format,
 		va_list param);
 
 void (*_dropbear_exit)(int exitcode, const char* format, va_list param)
ATTRIB_NORETURN
@@ -111,7 +105,7 @@
 	va_end(param);
 }
 
-static void generic_dropbear_exit(int exitcode, const char* format, 
+static void generic_dropbear_exit(int exitcode, const char* format,
 		va_list param) {
 
 	char fmtbuf[300];
@@ -127,7 +121,7 @@
 	dropbear_exit("Failed assertion (%s:%d): `%s'", file, line, expr);
 }
 
-static void generic_dropbear_log(int UNUSED(priority), const char* format, 
+static void generic_dropbear_log(int UNUSED(priority), const char* format,
 		va_list param) {
 
 	char printbuf[1024];
@@ -236,7 +230,7 @@
 
 }
 
-/* Listen on address:port. 
+/* Listen on address:port.
  * Special cases are address of "" listening on everything,
  * and address of NULL listening on localhost only.
  * Returns the number of sockets bound on success, or -1 on failure. On
@@ -253,7 +247,7 @@
 	int sock;
 
 	TRACE(("enter dropbear_listen"))
-	
+
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
 	hints.ai_socktype = SOCK_STREAM;
@@ -316,7 +310,7 @@
 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
 		if (res->ai_family == AF_INET6) {
 			int on = 1;
-			if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, 
+			if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
 						&on, sizeof(on)) == -1) {
 				dropbear_log(LOG_WARNING, "Couldn't set IPV6_V6ONLY");
 			}
@@ -415,7 +409,7 @@
 			int len;
 			len = 100 + strlen(gai_strerror(err));
 			*errstring = (char*)m_malloc(len);
-			snprintf(*errstring, len, "Error resolving '%s' port '%s'. %s", 
+			snprintf(*errstring, len, "Error resolving '%s' port '%s'. %s",
 					remotehost, remoteport, gai_strerror(err));
 		}
 		TRACE(("Error resolving: %s", gai_strerror(err)))
@@ -614,39 +608,39 @@
 {
 	struct sockaddr_storage addr;
 	socklen_t addrlen;
-	
+
 	if (local_host || local_port) {
 		addrlen = sizeof(addr);
 		if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
 			dropbear_exit("Failed socket address: %s", strerror(errno));
 		}
-		getaddrstring(&addr, local_host, local_port, host_lookup);		
+		getaddrstring(&addr, local_host, local_port, host_lookup);
 	}
 	if (remote_host || remote_port) {
 		addrlen = sizeof(addr);
 		if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
 			dropbear_exit("Failed socket address: %s", strerror(errno));
 		}
-		getaddrstring(&addr, remote_host, remote_port, host_lookup);		
+		getaddrstring(&addr, remote_host, remote_port, host_lookup);
 	}
 }
 
 /* Return a string representation of the socket address passed. The return
  * value is allocated with malloc() */
-void getaddrstring(struct sockaddr_storage* addr, 
+void getaddrstring(struct sockaddr_storage* addr,
 			char **ret_host, char **ret_port,
 			int host_lookup) {
 
 	char host[NI_MAXHOST+1], serv[NI_MAXSERV+1];
 	unsigned int len;
 	int ret;
-	
+
 	int flags = NI_NUMERICSERV | NI_NUMERICHOST;
 
 #ifndef DO_HOST_LOOKUP
 	host_lookup = 0;
 #endif
-	
+
 	if (host_lookup) {
 		flags = NI_NUMERICSERV;
 	}
@@ -667,7 +661,7 @@
 #endif
 #endif
 
-	ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1, 
+	ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1,
 			serv, sizeof(serv)-1, flags);
 
 	if (ret != 0) {
@@ -727,7 +721,7 @@
 	char * ret;
 	int len, pos;
 	int i;
-	
+
 	len = strlen(text);
 	ret = m_malloc(len+1);
 
@@ -742,7 +736,7 @@
 	ret[pos] = 0x0;
 	return ret;
 }
-			
+
 
 /* reads the contents of filename into the buffer buf, from the current
  * position, either to the end of the file, or the buffer being full.
@@ -759,7 +753,7 @@
 	if (fd < 0) {
 		goto out;
 	}
-	
+
 	do {
 		maxlen = buf->size - buf->pos;
 		len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
@@ -819,7 +813,7 @@
 		return DROPBEAR_SUCCESS;
 	}
 
-}	
+}
 #endif
 
 /* make sure that the socket closes */
@@ -839,7 +833,7 @@
 		dropbear_exit("Error closing fd %d, %s", fd, strerror(errno));
 	}
 }
-	
+
 void * m_malloc(size_t size) {
 
 	void* ret;
@@ -947,19 +941,34 @@
 
 time_t monotonic_now() {
 
-#if defined(__linux__) && defined(SYS_clock_gettime)
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
 	/* 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;
+	static int gettime_coarse_failed = 0;
+	static int gettime_failed = 0;
 
-	if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) {
-		clock_source = CLOCK_MONOTONIC;
-		syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts);
+	/* Try the cheaper CLOCK_MONOTONIC_COARSE first, keeping track of failure
to avoid spamming invalid calls... */
+	if (!gettime_coarse_failed) {
+		if (clock_gettime(clock_source, &ts) == 0)
+			return ts.tv_sec;
+		else {
+			gettime_coarse_failed = 1;
+			clock_source = CLOCK_MONOTONIC;
+		}
 	}
-	return ts.tv_sec;
+	/* Then try CLOCK_MONOTONIC, keeping track of it too... */
+	if (!gettime_failed) {
+		if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+			return ts.tv_sec;
+		else
+			gettime_failed = 1;
+	}
+	/* Fallback to time() (CLOCK_MONOTONIC being defined doesn't ensure it'll
actually be supported at runtime...) */
+	return time(NULL);
 #elif defined(HAVE_MACH_ABSOLUTE_TIME)
 	/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
 	static mach_timebase_info_data_t timebase_info;
@@ -968,7 +977,7 @@
 	}
 	return mach_absolute_time() * timebase_info.numer / timebase_info.denom
 		/ 1e9;
-#else 
+#else
 	/* Fallback for everything else - this will sometimes go backwards */
 	return time(NULL);
 #endif




More information about the Dropbear mailing list