From: Shawn Routhier Date: Tue, 14 Dec 2010 23:12:09 +0000 (+0000) Subject: Limit the timeout period allowed in the dispatch code to 2^^32-1 seconds. X-Git-Tag: v4_2_1b1~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=95f3fc45dbf713c28945094dcb385ff229c71cf9;p=thirdparty%2Fdhcp.git Limit the timeout period allowed in the dispatch code to 2^^32-1 seconds. Thanks to a report from Jiri Popelka at Red Hat. [ISC-Bugs #22033], [Red Hat Bug #628258] --- diff --git a/RELNOTES b/RELNOTES index ee795ad7f..e93ef210c 100644 --- a/RELNOTES +++ b/RELNOTES @@ -155,6 +155,10 @@ work on other platforms. Please report any problems and suggested fixes to beginning with "auth". The previous arrangement caused "auto-partner-down" to be processed incorrectly. [ISC-Bugs #21854] +- Limit the timeout period allowed in the dispatch code to 2^^32-1 seconds. + Thanks to a report from Jiri Popelka at Red Hat. + [ISC-Bugs #22033], [Red Hat Bug #628258] + Changes since 4.2.0rc1 - Documentation cleanup covering multiple tickets @@ -2713,7 +2717,6 @@ work on other platforms. Please report any problems and suggested fixes to - Fix a bug in the DHCP client initial startup backoff interval, which would cause two DHCPDISCOVERS to be sent back-to-back on startup. - Changes since 3.0 Beta 2 Patchlevel 15 - Some documentation tweaks. diff --git a/common/dispatch.c b/common/dispatch.c index 27b59a9fb..76080bd4c 100644 --- a/common/dispatch.c +++ b/common/dispatch.c @@ -174,6 +174,7 @@ isclib_timer_callback(isc_task_t *taskp, /* maximum value for usec */ #define USEC_MAX 1000000 +#define DHCP_SEC_MAX 0xFFFFFFFF void add_timeout (when, where, what, ref, unref) struct timeval *when; @@ -185,7 +186,8 @@ void add_timeout (when, where, what, ref, unref) struct timeout *t, *q; int usereset = 0; isc_result_t status; - int sec, usec; + int64_t sec; + int usec; isc_interval_t interval; isc_time_t expires; @@ -227,9 +229,48 @@ void add_timeout (when, where, what, ref, unref) q->what = what; } - /* We don't really need this, but keep it for now */ - q->when.tv_sec = when->tv_sec; - q->when.tv_usec = when->tv_usec; + /* + * The value passed in is a time from an epoch but we need a relative + * time so we need to do some math to try and recover the period. + * This is complicated by the fact that not all of the calls cared + * about the usec value, if it's zero we assume the caller didn't care. + * + * The ISC timer library doesn't seem to like negative values + * and can't accept any values above 4G-1 seconds so we limit + * the values to 0 <= value < 4G-1. We do it before + * checking the trace option so that both the trace code and + * the working code use the same values. + */ + + sec = when->tv_sec - cur_tv.tv_sec; + usec = when->tv_usec - cur_tv.tv_usec; + + if ((when->tv_usec != 0) && (usec < 0)) { + sec--; + usec += USEC_MAX; + } + + if (sec < 0) { + sec = 0; + usec = 0; + } else if (sec > DHCP_SEC_MAX) { + log_error("Timeout requested too large %lld " + "reducing to 2^^32-1", sec); + sec = DHCP_SEC_MAX; + usec = 0; + } else if (usec < 0) { + usec = 0; + } else if (usec >= USEC_MAX) { + usec = USEC_MAX - 1; + } + + /* + * This is necessary for the tracing code but we put it + * here in case we want to compare timing information + * for some reason, like debugging. + */ + q->when.tv_sec = cur_tv.tv_sec + (sec & DHCP_SEC_MAX); + q->when.tv_usec = usec; #if defined (TRACING) if (trace_playback()) { @@ -279,38 +320,7 @@ void add_timeout (when, where, what, ref, unref) q->next = timeouts; timeouts = q; - /* - * Set up the interval values - The previous timers allowed - * negative values to be set, the ISC timer library doesn't like - * that so we make any negative values 0 which sould amount to - * the same thing. - */ - - /* - * The value passed in is a time from an epoch but we need a relative - * time so we need to do some math to try and recover the period. - * This is complicated by the fact that not all of the calls cared - * about the usec value, if it's zero we assume the caller didn't care. - */ - - sec = when->tv_sec - cur_tv.tv_sec; - usec = when->tv_usec - cur_tv.tv_usec; - - if ((when->tv_usec != 0) && (usec < 0)) { - sec--; - usec += USEC_MAX; - } - - if (sec < 0) { - sec = 0; - usec = 0; - } else if (usec < 0) { - usec = 0; - } else if (usec >= USEC_MAX) { - usec = USEC_MAX - 1; - } - - isc_interval_set(&interval, sec, usec * 1000); + isc_interval_set(&interval, sec & DHCP_SEC_MAX, usec * 1000); status = isc_time_nowplusinterval(&expires, &interval); if (status != ISC_R_SUCCESS) { /*