|
|
@@ -1,198 +0,0 @@
|
|
|
-From ec2215726cffb976019d08ebf569edd2229e9dba Mon Sep 17 00:00:00 2001
|
|
|
-From: Matt Johnston <[email protected]>
|
|
|
-Date: Thu, 1 Dec 2022 11:34:43 +0800
|
|
|
-Subject: Fix y2038 issues with time_t conversion
|
|
|
-
|
|
|
-These changes were identified by building with and without
|
|
|
--D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64
|
|
|
-on 32-bit arm, logging warnings to files.
|
|
|
--Wconversion was added to CFLAGS in both builds.
|
|
|
-
|
|
|
-Then a "diff -I Wconversion log1 log2" shows new warnings that appear
|
|
|
-with the 64-bit time_t. There are a few false positives that have been
|
|
|
-fixed for quietness.
|
|
|
-
|
|
|
-struct logininfo and struct wtmp are still problematic, those will
|
|
|
-need to be handled by libc.
|
|
|
----
|
|
|
- common-session.c | 43 +++++++++++++++++++++++++++----------------
|
|
|
- dbutil.c | 2 +-
|
|
|
- loginrec.c | 2 ++
|
|
|
- loginrec.h | 4 ++--
|
|
|
- runopts.h | 4 ++--
|
|
|
- svr-auth.c | 2 +-
|
|
|
- 6 files changed, 35 insertions(+), 22 deletions(-)
|
|
|
-
|
|
|
---- a/common-session.c
|
|
|
-+++ b/common-session.c
|
|
|
-@@ -519,15 +519,24 @@ static void send_msg_keepalive() {
|
|
|
- ses.last_packet_time_idle = old_time_idle;
|
|
|
- }
|
|
|
-
|
|
|
-+/* Returns the difference in seconds, clamped to LONG_MAX */
|
|
|
-+static long elapsed(time_t now, time_t prev) {
|
|
|
-+ time_t del = now - prev;
|
|
|
-+ if (del > LONG_MAX) {
|
|
|
-+ return LONG_MAX;
|
|
|
-+ }
|
|
|
-+ return (long)del;
|
|
|
-+}
|
|
|
-+
|
|
|
- /* Check all timeouts which are required. Currently these are the time for
|
|
|
- * user authentication, and the automatic rekeying. */
|
|
|
- static void checktimeouts() {
|
|
|
-
|
|
|
- time_t now;
|
|
|
- now = monotonic_now();
|
|
|
--
|
|
|
-+
|
|
|
- if (IS_DROPBEAR_SERVER && ses.connect_time != 0
|
|
|
-- && now - ses.connect_time >= AUTH_TIMEOUT) {
|
|
|
-+ && elapsed(now, ses.connect_time) >= AUTH_TIMEOUT) {
|
|
|
- dropbear_close("Timeout before auth");
|
|
|
- }
|
|
|
-
|
|
|
-@@ -537,45 +546,47 @@ static void checktimeouts() {
|
|
|
- }
|
|
|
-
|
|
|
- if (!ses.kexstate.sentkexinit
|
|
|
-- && (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
|
|
|
-+ && (elapsed(now, ses.kexstate.lastkextime) >= KEX_REKEY_TIMEOUT
|
|
|
- || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
|
|
|
- TRACE(("rekeying after timeout or max data reached"))
|
|
|
- send_msg_kexinit();
|
|
|
- }
|
|
|
--
|
|
|
-+
|
|
|
- if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
|
|
|
- /* Avoid sending keepalives prior to auth - those are
|
|
|
- not valid pre-auth packet types */
|
|
|
-
|
|
|
- /* Send keepalives if we've been idle */
|
|
|
-- if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
|
|
|
-+ if (elapsed(now, ses.last_packet_time_any_sent) >= opts.keepalive_secs) {
|
|
|
- send_msg_keepalive();
|
|
|
- }
|
|
|
-
|
|
|
- /* Also send an explicit keepalive message to trigger a response
|
|
|
- if the remote end hasn't sent us anything */
|
|
|
-- if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
|
|
|
-- && now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
|
|
|
-+ if (elapsed(now, ses.last_packet_time_keepalive_recv) >= opts.keepalive_secs
|
|
|
-+ && elapsed(now, ses.last_packet_time_keepalive_sent) >= opts.keepalive_secs) {
|
|
|
- send_msg_keepalive();
|
|
|
- }
|
|
|
-
|
|
|
-- if (now - ses.last_packet_time_keepalive_recv
|
|
|
-+ if (elapsed(now, ses.last_packet_time_keepalive_recv)
|
|
|
- >= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
|
|
|
- dropbear_exit("Keepalive timeout");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-- if (opts.idle_timeout_secs > 0
|
|
|
-- && now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
|
|
|
-+ if (opts.idle_timeout_secs > 0
|
|
|
-+ && elapsed(now, ses.last_packet_time_idle) >= opts.idle_timeout_secs) {
|
|
|
- dropbear_close("Idle timeout");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
--static void update_timeout(long limit, long now, long last_event, long * timeout) {
|
|
|
-- TRACE2(("update_timeout limit %ld, now %ld, last %ld, timeout %ld",
|
|
|
-- limit, now, last_event, *timeout))
|
|
|
-+static void update_timeout(long limit, time_t now, time_t last_event, long * timeout) {
|
|
|
-+ TRACE2(("update_timeout limit %ld, now %llu, last %llu, timeout %ld",
|
|
|
-+ limit,
|
|
|
-+ (unsigned long long)now,
|
|
|
-+ (unsigned long long)last_event, *timeout))
|
|
|
- if (last_event > 0 && limit > 0) {
|
|
|
-- *timeout = MIN(*timeout, last_event+limit-now);
|
|
|
-+ *timeout = MIN(*timeout, elapsed(now, last_event) + limit);
|
|
|
- TRACE2(("new timeout %ld", *timeout))
|
|
|
- }
|
|
|
- }
|
|
|
-@@ -584,7 +595,7 @@ static long select_timeout() {
|
|
|
- /* determine the minimum timeout that might be required, so
|
|
|
- as to avoid waking when unneccessary */
|
|
|
- long timeout = KEX_REKEY_TIMEOUT;
|
|
|
-- long now = monotonic_now();
|
|
|
-+ time_t now = monotonic_now();
|
|
|
-
|
|
|
- if (!ses.kexstate.sentkexinit) {
|
|
|
- update_timeout(KEX_REKEY_TIMEOUT, now, ses.kexstate.lastkextime, &timeout);
|
|
|
-@@ -596,7 +607,7 @@ static long select_timeout() {
|
|
|
- }
|
|
|
-
|
|
|
- if (ses.authstate.authdone) {
|
|
|
-- update_timeout(opts.keepalive_secs, now,
|
|
|
-+ update_timeout(opts.keepalive_secs, now,
|
|
|
- MAX(ses.last_packet_time_keepalive_recv, ses.last_packet_time_keepalive_sent),
|
|
|
- &timeout);
|
|
|
- }
|
|
|
---- a/dbutil.c
|
|
|
-+++ b/dbutil.c
|
|
|
-@@ -724,7 +724,7 @@ void gettime_wrapper(struct timespec *no
|
|
|
- /* Fallback for everything else - this will sometimes go backwards */
|
|
|
- gettimeofday(&tv, NULL);
|
|
|
- now->tv_sec = tv.tv_sec;
|
|
|
-- now->tv_nsec = 1000*tv.tv_usec;
|
|
|
-+ now->tv_nsec = 1000*(long)tv.tv_usec;
|
|
|
- }
|
|
|
-
|
|
|
- /* second-resolution monotonic timestamp */
|
|
|
---- a/loginrec.c
|
|
|
-+++ b/loginrec.c
|
|
|
-@@ -459,6 +459,7 @@ line_abbrevname(char *dst, const char *s
|
|
|
- void
|
|
|
- set_utmp_time(struct logininfo *li, struct utmp *ut)
|
|
|
- {
|
|
|
-+ /* struct utmp in glibc isn't y2038 safe yet */
|
|
|
- # ifdef HAVE_STRUCT_UTMP_UT_TV
|
|
|
- ut->ut_tv.tv_sec = li->tv_sec;
|
|
|
- ut->ut_tv.tv_usec = li->tv_usec;
|
|
|
-@@ -1272,6 +1273,7 @@ lastlog_construct(struct logininfo *li,
|
|
|
- (void)line_stripname(last->ll_line, li->line, sizeof(last->ll_line));
|
|
|
- strlcpy(last->ll_host, li->hostname,
|
|
|
- MIN_SIZEOF(last->ll_host, li->hostname));
|
|
|
-+ /* struct lastlog in glibc isn't y2038 safe yet */
|
|
|
- last->ll_time = li->tv_sec;
|
|
|
- }
|
|
|
-
|
|
|
---- a/loginrec.h
|
|
|
-+++ b/loginrec.h
|
|
|
-@@ -139,8 +139,8 @@ struct logininfo {
|
|
|
- /* struct timeval (sys/time.h) isn't always available, if it isn't we'll
|
|
|
- * use time_t's value as tv_sec and set tv_usec to 0
|
|
|
- */
|
|
|
-- unsigned int tv_sec;
|
|
|
-- unsigned int tv_usec;
|
|
|
-+ time_t tv_sec;
|
|
|
-+ suseconds_t tv_usec;
|
|
|
- union login_netinfo hostaddr; /* caller's host address(es) */
|
|
|
- }; /* struct logininfo */
|
|
|
-
|
|
|
---- a/runopts.h
|
|
|
-+++ b/runopts.h
|
|
|
-@@ -39,8 +39,8 @@ typedef struct runopts {
|
|
|
- int listen_fwd_all;
|
|
|
- #endif
|
|
|
- unsigned int recv_window;
|
|
|
-- time_t keepalive_secs; /* Time between sending keepalives. 0 is off */
|
|
|
-- time_t idle_timeout_secs; /* Exit if no traffic is sent/received in this time */
|
|
|
-+ long keepalive_secs; /* Time between sending keepalives. 0 is off */
|
|
|
-+ long idle_timeout_secs; /* Exit if no traffic is sent/received in this time */
|
|
|
- int usingsyslog;
|
|
|
-
|
|
|
- #ifndef DISABLE_ZLIB
|
|
|
---- a/svr-auth.c
|
|
|
-+++ b/svr-auth.c
|
|
|
-@@ -389,7 +389,7 @@ void send_msg_userauth_failure(int parti
|
|
|
- Beware of integer overflow if increasing these values */
|
|
|
- const unsigned int mindelay = 250000000;
|
|
|
- const unsigned int vardelay = 100000000;
|
|
|
-- unsigned int rand_delay;
|
|
|
-+ suseconds_t rand_delay;
|
|
|
- struct timespec delay;
|
|
|
-
|
|
|
- gettime_wrapper(&delay);
|