diff options
author | Matt Whitlock <dnsmasq@mattwhitlock.name> | 2021-09-27 20:44:25 -0400 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2021-09-29 09:46:13 +0100 |
commit | 0140454ba2cd51e7037ca30ca9eeec5991fce1df (patch) | |
tree | 22e0eaa7abb0022ec2a6d65273d272f66f2981dc | |
parent | 2c60441239e1c10c4987cb586653b1ea08f703c0 (diff) | |
download | dnsmasq-0140454ba2cd51e7037ca30ca9eeec5991fce1df.tar.gz |
dnsmasq_time: avoid signed integer overflow when HAVE_BROKEN_RTC
The dnsmasq_time() function, in the case of HAVE_BROKEN_RTC, was calling
times() to read the number of ticks "elapsed since an arbitrary point in
the past" and then dividing that by sysconf(_SC_CLK_TCK) to compute the
number of seconds elapsed since that arbitrary instant. This works fine
until the number of ticks exceeds 2^31, beyond which time the function
would begin erroneously returning negative times. On my system this
happens after approximately 248 days of uptime. A symptom is that
dnsmasq no longer populates the resolver cache with DHCP-derived names
at startup, as the inserted cache entries immediately expire due to
having negative expiration times that cause is_expired() to return true
when called with now==0.
This commit replaces the archaic implementation of dnsmasq_time() with a
call to the POSIX-standardized clock_gettime(CLOCK_MONOTONIC), thereby
eliminating the need to convert manually from ticks to seconds. The new
implementation will yield correct results until the system uptime
exceeds approximately 68 years.
Signed-off-by: Matt Whitlock <dnsmasq@mattwhitlock.name>
-rw-r--r-- | src/util.c | 9 |
1 files changed, 4 insertions, 5 deletions
@@ -430,13 +430,12 @@ int hostname_issubdomain(char *a, char *b) time_t dnsmasq_time(void) { #ifdef HAVE_BROKEN_RTC - struct tms dummy; - static long tps = 0; + struct timespec ts; - if (tps == 0) - tps = sysconf(_SC_CLK_TCK); + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) + die(_("cannot read monotonic clock: %s"), NULL, EC_MISC); - return (time_t)(times(&dummy)/tps); + return ts.tv_sec; #else return time(NULL); #endif |