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