]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Prevent an underflow of the TCP d_queued counter 12365/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 27 Dec 2022 16:01:55 +0000 (17:01 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 27 Dec 2022 16:03:44 +0000 (17:03 +0100)
By incrementing it _before_ writing to the pipe, and decrementing
it in case of an error, we prevent a very possible underflow from
occurring if the reader manages to decrement before we can return
from write and increment it.

pdns/dnsdistdist/dnsdist-tcp.hh

index 05b2db4e464c599c008629735b4c1324ae7301b5..43d615dea2c8e359879c89a17cfb6abf0ac0fd98 100644 (file)
@@ -182,17 +182,6 @@ class TCPClientCollection
 public:
   TCPClientCollection(size_t maxThreads, std::vector<ClientState*> tcpStates);
 
-  int getThread()
-  {
-    if (d_numthreads == 0) {
-      throw std::runtime_error("No TCP worker thread yet");
-    }
-
-    uint64_t pos = d_pos++;
-    ++d_queued;
-    return d_tcpclientthreads.at(pos % d_numthreads).d_newConnectionPipe.getHandle();
-  }
-
   bool passConnectionToThread(std::unique_ptr<ConnectionInfo>&& conn)
   {
     if (d_numthreads == 0) {
@@ -203,13 +192,17 @@ public:
     auto pipe = d_tcpclientthreads.at(pos % d_numthreads).d_newConnectionPipe.getHandle();
     auto tmp = conn.release();
 
+    /* we need to increment this counter _before_ writing to the pipe,
+       otherwise there is a very real possiblity that the other end
+       decrement the counter before we can increment it, leading to an underflow */
+    ++d_queued;
     if (write(pipe, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+      --d_queued;
       ++g_stats.tcpQueryPipeFull;
       delete tmp;
       tmp = nullptr;
       return false;
     }
-    ++d_queued;
     return true;
   }