From: Roy Marples Date: Mon, 22 Jun 2026 18:25:48 +0000 (+0100) Subject: IPv6: Fix numerous issues extending temporary address times X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a52bc9f685dca009188d1540089977c21865aeca;p=thirdparty%2Fdhcpcd.git IPv6: Fix numerous issues extending temporary address times Fix a potential integer underflow if pltime is less than aquisition time. Fix potential time truncation to uint32_t. Reported by NVIDIA Project Vanessa --- diff --git a/src/ipv6.c b/src/ipv6.c index ee25c40a..20caa5e6 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -1985,13 +1985,14 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags) TAILQ_FOREACH_REVERSE(ap, &state->addrs, ipv6_addrhead, next) { if (ap->flags & IPV6_AF_TEMPORARY && ap->prefix_pltime && IN6_ARE_ADDR_EQUAL(&ia->prefix, &ap->prefix)) { - unsigned int max, ext; + unsigned long long elapsed; + uint32_t limit, rmtime; if (flags == 0) { - if (ap->prefix_pltime - - (uint32_t)(ia->acquired.tv_sec - - ap->acquired.tv_sec) < - REGEN_ADVANCE) + elapsed = eloop_timespec_diff(&ia->acquired, + &ap->acquired, NULL); + if (ap->prefix_pltime <= elapsed || + ap->prefix_pltime - elapsed < REGEN_ADVANCE) continue; return ap; @@ -2001,6 +2002,9 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags) ap->flags |= IPV6_AF_NEW | IPV6_AF_AUTOCONF; ap->flags &= ~IPV6_AF_STALE; + elapsed = eloop_timespec_diff(&ia->acquired, + &ap->created, NULL); + /* RFC4941 Section 3.4 * Deprecated prefix, deprecate the temporary address */ if (ia->prefix_pltime == 0) { @@ -2014,26 +2018,28 @@ ipv6_settemptime(struct ipv6_addr *ia, int flags) /* RFC4941 Section 3.3.2 * Extend temporary times, but ensure that they * never last beyond the system limit. */ - ext = (unsigned int)ia->acquired.tv_sec + - ia->prefix_pltime; - max = (unsigned int)(ap->created.tv_sec + - TEMP_PREFERRED_LIFETIME - state->desync_factor); - if (ext < max) - ap->prefix_pltime = ia->prefix_pltime; - else - ap->prefix_pltime = (uint32_t)(max - - ia->acquired.tv_sec); + limit = TEMP_PREFERRED_LIFETIME - state->desync_factor; + if (elapsed >= limit) + ap->prefix_pltime = 0; + else { + rmtime = (uint32_t)(limit - elapsed); + if (ia->prefix_pltime < rmtime) + ap->prefix_pltime = ia->prefix_pltime; + else + ap->prefix_pltime = rmtime; + } valid: - ext = (unsigned int)ia->acquired.tv_sec + - ia->prefix_vltime; - max = (unsigned int)(ap->created.tv_sec + - TEMP_VALID_LIFETIME); - if (ext < max) - ap->prefix_vltime = ia->prefix_vltime; - else - ap->prefix_vltime = (uint32_t)(max - - ia->acquired.tv_sec); + limit = TEMP_VALID_LIFETIME; + if (elapsed >= limit) + ap->prefix_vltime = 0; + else { + rmtime = (uint32_t)(limit - elapsed); + if (ia->prefix_vltime < rmtime) + ap->prefix_vltime = ia->prefix_vltime; + else + ap->prefix_vltime = rmtime; + } /* Just extend the latest matching prefix */ ap->acquired = ia->acquired;