]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Sanitize d_orig_ttl
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 16 Mar 2023 15:08:56 +0000 (16:08 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 16 May 2023 10:51:00 +0000 (12:51 +0200)
The computed orig_ttl can be wrong if d_now.tv_sec is more recent
than the d_now.tv_sec the ttd was computed from. This can happen
if we went out to get e.g. keys and that took time. d_orig_ttl wraps
around in that case if the TTL value was smaller than that delay.
Work around that and make sure d_orig_ttl is within the legal range.

pdns/recursordist/recursor_cache.cc

index 4c95c052c55c00fe14425dafb93e7409ecd29e57..c32364c40d75471411544a351065f1c524dd28d7 100644 (file)
@@ -607,7 +607,19 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
     /* Yes, we have altered the d_ttl value by adding time(nullptr) to it
        prior to calling this function, so the TTL actually holds a TTD. */
     ce.d_ttd = min(maxTTD, static_cast<time_t>(i.d_ttl)); // XXX this does weird things if TTLs differ in the set
+
     ce.d_orig_ttl = ce.d_ttd - now;
+
+    // d_orig_ttl should be between s_minimumTTL and s_maxcachettl, as d_ttd was sanitized wrt those
+    // bounds. But our reference point (d_now aka now) might be "too new" at this point, if we went
+    // outside to e.g. get DNSKEYS and that took a while. In that case, if the original TTL was
+    // smaller than the delay, d_orig_ttl will wrap and become very large.  Detect that case and
+    // make sure d_orig_ttl is fixed. Likewise if there was a delay but that was smaller than the
+    // original TTL, d_orig_ttl can become smaller than s_minimumTTL. Detect those cases and use a
+    // small but legal d_orig_ttl in those cases.
+    if (ce.d_orig_ttl < SyncRes::s_minimumTTL || ce.d_orig_ttl > SyncRes::s_maxcachettl) {
+      ce.d_orig_ttl = SyncRes::s_minimumTTL;
+    }
     ce.d_records.push_back(i.getContent());
   }