From 20ae89b4b14398e42cd0c76708d26230385a65d4 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 15 May 2026 15:49:10 +0200 Subject: [PATCH 1/5] dnsdist: Fix a data race on concurrent CDB KVS lookups Contrary to the assumption that was made by the existing author (me!), `tinycdb` structures are not safe to use concurrently from more than one thread, even for reading, as they hold data related to the current search (current position, mostly). This will have a performance impact for heavy users of the CDB KVS store, so perhaps a follow-up PR might be needed to have a per-thread CDB instance instead. Signed-off-by: Remi Gacogne --- pdns/dnsdistdist/dnsdist-kvs.cc | 6 +++--- pdns/dnsdistdist/dnsdist-kvs.hh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-kvs.cc b/pdns/dnsdistdist/dnsdist-kvs.cc index 4c0ba177d8c7..e9dbf92b08a8 100644 --- a/pdns/dnsdistdist/dnsdist-kvs.cc +++ b/pdns/dnsdistdist/dnsdist-kvs.cc @@ -205,7 +205,7 @@ bool CDBKVStore::reload(const struct stat& st) { auto newCDB = std::make_unique(d_fname); { - *(d_cdb.write_lock()) = std::move(newCDB); + *(d_cdb.lock()) = std::move(newCDB); } d_mtime = st.st_mtime; return true; @@ -263,7 +263,7 @@ bool CDBKVStore::getValue(const std::string& key, std::string& value) } { - auto cdb = d_cdb.read_lock(); + auto cdb = d_cdb.lock(); if (*cdb && (*cdb)->findOne(key, value)) { return true; } @@ -286,7 +286,7 @@ bool CDBKVStore::keyExists(const std::string& key) } { - auto cdb = d_cdb.read_lock(); + auto cdb = d_cdb.lock(); if (!*cdb) { return false; } diff --git a/pdns/dnsdistdist/dnsdist-kvs.hh b/pdns/dnsdistdist/dnsdist-kvs.hh index 6392401f5d5b..29986afaa1f7 100644 --- a/pdns/dnsdistdist/dnsdist-kvs.hh +++ b/pdns/dnsdistdist/dnsdist-kvs.hh @@ -222,7 +222,7 @@ private: void refreshDBIfNeeded(time_t now); bool reload(const struct stat& st); - SharedLockGuarded> d_cdb{nullptr}; + LockGuarded> d_cdb{nullptr}; std::string d_fname; time_t d_mtime{0}; time_t d_nextCheck{0}; From 5d2f936aaddc2cb8b4b52e467d260a8d312ade92 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 15 May 2026 15:59:15 +0200 Subject: [PATCH 2/5] dnsdist: Prevent duplicated responses for "too large" XSK responses Signed-off-by: Remi Gacogne --- pdns/dnsdistdist/dnsdist-xsk.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-xsk.cc b/pdns/dnsdistdist/dnsdist-xsk.cc index d66b5dea221a..143f4575870e 100644 --- a/pdns/dnsdistdist/dnsdist-xsk.cc +++ b/pdns/dnsdistdist/dnsdist-xsk.cc @@ -70,6 +70,8 @@ void XskResponderThread(std::shared_ptr dss, std::shared_ptr packet.getCapacity()) { /* fallback to sending the packet via normal socket */ + VERBOSESLOG(infolog("XSK packet falling back because packet is too large"), + logger->info(Logr::Info, "XSK packet falling back because packet is too large")); ids->xskPacketHeader.clear(); } if (!processResponderPacket(dss, response, std::move(*ids))) { @@ -79,10 +81,6 @@ void XskResponderThread(std::shared_ptr dss, std::shared_ptr packet.getCapacity()) { - /* fallback to sending the packet via normal socket */ - sendUDPResponse(ids->cs->udpFD, response, ids->delayMsec, ids->hopLocal, ids->hopRemote); - VERBOSESLOG(infolog("XSK packet falling back because packet is too large"), - logger->info(Logr::Info, "XSK packet falling back because packet is too large")); xskInfo->markAsFree(packet); return; } From 5f8850780d4f5844e930fb59191737f0c15bb4b9 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 15 May 2026 15:59:40 +0200 Subject: [PATCH 3/5] dnsdist: Properly handle interrupted writes in the XSK worker Signed-off-by: Remi Gacogne --- pdns/dnsdistdist/xsk.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/xsk.cc b/pdns/dnsdistdist/xsk.cc index 3017f121b864..5f3946e0fbb2 100644 --- a/pdns/dnsdistdist/xsk.cc +++ b/pdns/dnsdistdist/xsk.cc @@ -878,8 +878,11 @@ void XskWorker::notify(int desc) { uint64_t value = 1; ssize_t res = 0; - while ((res = write(desc, &value, sizeof(value))) == EINTR) { + do { + res = write(desc, &value, sizeof(value)); } + while (res == -1 && errno == EINTR); + if (res != sizeof(value)) { throw runtime_error("Unable Wake Up XskSocket Failed"); } From ba3eb2b9499f3938505ff44c77627e41b53f1459 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 15 May 2026 16:00:04 +0200 Subject: [PATCH 4/5] dnsdist: Fix checksum computation when data len is not a multiple of 4 Signed-off-by: Remi Gacogne --- pdns/dnsdistdist/xsk.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdns/dnsdistdist/xsk.cc b/pdns/dnsdistdist/xsk.cc index 5f3946e0fbb2..23356356d34b 100644 --- a/pdns/dnsdistdist/xsk.cc +++ b/pdns/dnsdistdist/xsk.cc @@ -1013,7 +1013,7 @@ void XskPacket::rewrite() noexcept { size_t position{0}; /* Main loop: 32 bits at a time */ - for (position = 0; position < len; position += sizeof(uint32_t)) { + for (position = 0; position + sizeof(uint32_t) <= len; position += sizeof(uint32_t)) { uint32_t value{}; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) memcpy(&value, static_cast(ptr) + position, sizeof(value)); From 0eca84b028bc69a37467301f10d2385d0d2a07c0 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 15 May 2026 16:57:04 +0200 Subject: [PATCH 5/5] dnsdist: Fix formatting Signed-off-by: Remi Gacogne --- pdns/dnsdistdist/xsk.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pdns/dnsdistdist/xsk.cc b/pdns/dnsdistdist/xsk.cc index 23356356d34b..475b5c6a25df 100644 --- a/pdns/dnsdistdist/xsk.cc +++ b/pdns/dnsdistdist/xsk.cc @@ -880,8 +880,7 @@ void XskWorker::notify(int desc) ssize_t res = 0; do { res = write(desc, &value, sizeof(value)); - } - while (res == -1 && errno == EINTR); + } while (res == -1 && errno == EINTR); if (res != sizeof(value)) { throw runtime_error("Unable Wake Up XskSocket Failed");