]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
IPv6: Fix numerous issues extending temporary address times master
authorRoy Marples <roy@marples.name>
Mon, 22 Jun 2026 18:25:48 +0000 (19:25 +0100)
committerGitHub <noreply@github.com>
Mon, 22 Jun 2026 18:25:48 +0000 (19:25 +0100)
Fix a potential integer underflow if pltime is less than
aquisition time.
Fix potential time truncation to uint32_t.

Reported by NVIDIA Project Vanessa

src/ipv6.c

index ee25c40af4cb161fe5cfc8afc7d6056f351837b2..20caa5e67fcbc07617f5e82269d860afe18b3acb 100644 (file)
@@ -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;