From b29a61b140510aa3c40d203e894fb0171dc0b7ab Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Thu, 16 Mar 2023 16:08:56 +0100 Subject: [PATCH] Sanitize d_orig_ttl 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 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pdns/recursordist/recursor_cache.cc b/pdns/recursordist/recursor_cache.cc index 4c95c052c5..c32364c40d 100644 --- a/pdns/recursordist/recursor_cache.cc +++ b/pdns/recursordist/recursor_cache.cc @@ -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(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()); } -- 2.47.2