From: Otto Moerbeek Date: Mon, 5 Jan 2026 13:52:02 +0000 (+0100) Subject: Limit packet and record cache entry size X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=770ec7b22c6b1eafc5390182e8d180b5cc474118;p=thirdparty%2Fpdns.git Limit packet and record cache entry size Signed-off-by: Otto Moerbeek --- diff --git a/pdns/recursordist/pdns_recursor.cc b/pdns/recursordist/pdns_recursor.cc index a8b47c07a2..34f2b7c17f 100644 --- a/pdns/recursordist/pdns_recursor.cc +++ b/pdns/recursordist/pdns_recursor.cc @@ -1764,7 +1764,7 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi #endif } - const bool intoPC = g_packetCache && !variableAnswer && !resolver.wasVariable(); + const bool intoPC = g_packetCache && !variableAnswer && !resolver.wasVariable() && (RecursorPacketCache::s_maxEntrySize == 0 || packet.size() <= RecursorPacketCache::s_maxEntrySize); if (intoPC) { minTTL = capPacketCacheTTL(*packetWriter.getHeader(), minTTL, seenAuthSOA); g_packetCache->insertResponsePacket(comboWriter->d_tag, comboWriter->d_qhash, std::move(comboWriter->d_query), comboWriter->d_mdp.d_qname, diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 8abf028781..7e3b12e622 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -3239,6 +3239,8 @@ int main(int argc, char** argv) pdns::RecResolve::setInstanceParameters(arg()["server-id"], ttl, interval, selfResolveCheck, []() { reloadZoneConfiguration(g_yamlSettings); }); } + MemRecursorCache::s_maxEntrySize = ::arg().asNum("max-recordcache-entry-size"); + RecursorPacketCache::s_maxEntrySize = ::arg().asNum("max-packetcache-entry-size"); g_recCache = std::make_unique(::arg().asNum("record-cache-shards")); g_negCache = std::make_unique(::arg().asNum("record-cache-shards") / 8); if (!::arg().mustDo("disable-packetcache")) { diff --git a/pdns/recursordist/rec-rust-lib/table.py b/pdns/recursordist/rec-rust-lib/table.py index 2a0e63cb2f..4f2beb2c94 100644 --- a/pdns/recursordist/rec-rust-lib/table.py +++ b/pdns/recursordist/rec-rust-lib/table.py @@ -1520,6 +1520,19 @@ See :ref:`handling-of-root-hints` for more information on this. ''', 'versionchanged': ('4.1.0', 'The minimum value of this setting is 15. i.e. setting this to lower than 15 will make this value 15.') }, + { + 'name' : 'max_entry_size', + 'section' : 'recordcache', + 'oldname': 'max-recordcache-entry-size', + 'type' : LType.Uint64, + 'default' : '8192', + 'help' : 'maximum storage size of a recordset stored in record cache', + 'doc' : ''' +Maximum size of storage used by a single record cache entry. Entries larger than this number will not be stored. +Zero means no limit. +''', + 'versionadded': ['5.1.10', '5.2.8', '5.3.5', '5.4.0'], + }, { 'name' : 'max_concurrent_requests_per_tcp_connection', 'section' : 'incoming', @@ -1596,6 +1609,19 @@ Maximum number of Packet Cache entries. Sharded and shared by all threads since ''', 'runtime': 'set-max-packetcache-entries', }, + { + 'name' : 'max_entry_size', + 'section' : 'packetcache', + 'oldname' : 'max-packetcache-entry-size', + 'type' : LType.Uint64, + 'default' : '8192', + 'help' : 'maximum size of a packet stored in the the packet cache', + 'doc' : ''' +Maximum size of packets stored in the packet cache. Packets larger than this number will not be stored. +Zero means no limit. +''', + 'versionadded': ['5.1.10', '5.2.8', '5.3.5', '5.4.0'], + }, { 'name' : 'max_qperq', 'section' : 'outgoing', diff --git a/pdns/recursordist/recpacketcache.cc b/pdns/recursordist/recpacketcache.cc index ec99fe58f5..93a1a82a63 100644 --- a/pdns/recursordist/recpacketcache.cc +++ b/pdns/recursordist/recpacketcache.cc @@ -11,6 +11,7 @@ #include "rec-taskqueue.hh" unsigned int RecursorPacketCache::s_refresh_ttlperc{0}; +uint32_t RecursorPacketCache::s_maxEntrySize{8192}; void RecursorPacketCache::setShardSizes(size_t shardSize) { diff --git a/pdns/recursordist/recpacketcache.hh b/pdns/recursordist/recpacketcache.hh index e11906ec36..7922be6519 100644 --- a/pdns/recursordist/recpacketcache.hh +++ b/pdns/recursordist/recpacketcache.hh @@ -46,6 +46,7 @@ class RecursorPacketCache : public PacketCache { public: static unsigned int s_refresh_ttlperc; + static uint32_t s_maxEntrySize; struct PBData { diff --git a/pdns/recursordist/recursor_cache.cc b/pdns/recursordist/recursor_cache.cc index 55ff55ab01..94dc86de48 100644 --- a/pdns/recursordist/recursor_cache.cc +++ b/pdns/recursordist/recursor_cache.cc @@ -76,6 +76,7 @@ uint16_t MemRecursorCache::s_maxServedStaleExtensions; uint16_t MemRecursorCache::s_maxRRSetSize = 256; bool MemRecursorCache::s_limitQTypeAny = true; +uint32_t MemRecursorCache::s_maxEntrySize = 8192; const MemRecursorCache::AuthRecs MemRecursorCache::s_emptyAuthRecs = std::make_shared(); const MemRecursorCache::SigRecs MemRecursorCache::s_emptySigRecs = std::make_shared(); @@ -89,6 +90,7 @@ void MemRecursorCache::resetStaticsForTests() SyncRes::s_minimumTTL = 0; s_maxRRSetSize = 256; s_limitQTypeAny = true; + s_maxEntrySize = 8192; } MemRecursorCache::MemRecursorCache(size_t mapsCount) : @@ -762,6 +764,10 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qty } } + auto storeSize = cacheEntry.sizeEstimate(); + if (s_maxEntrySize > 0 && storeSize > s_maxEntrySize) { + return; + } if (!isNew) { moveCacheItemToBack(lockedShard->d_map, stored); } diff --git a/pdns/recursordist/recursor_cache.hh b/pdns/recursordist/recursor_cache.hh index bc70193ad8..d2d12b1743 100644 --- a/pdns/recursordist/recursor_cache.hh +++ b/pdns/recursordist/recursor_cache.hh @@ -56,6 +56,7 @@ public: // but mark it as too big. Subsequent gets will cause an ImmediateServFailException to be thrown. static uint16_t s_maxRRSetSize; static bool s_limitQTypeAny; + static uint32_t s_maxEntrySize; [[nodiscard]] size_t size() const; [[nodiscard]] size_t bytes(); diff --git a/pdns/recursordist/test-recursorcache_cc.cc b/pdns/recursordist/test-recursorcache_cc.cc index 42d9a274c3..3ed068b7b2 100644 --- a/pdns/recursordist/test-recursorcache_cc.cc +++ b/pdns/recursordist/test-recursorcache_cc.cc @@ -395,6 +395,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheSimpleDistantFuture) BOOST_AUTO_TEST_CASE(test_RecursorCacheBig) { MemRecursorCache::resetStaticsForTests(); + MemRecursorCache::s_maxEntrySize = 64 * 1024; MemRecursorCache MRC; std::vector records;