]> granicus.if.org Git - pdns/commitdiff
Handle exceptions raised by `closesocket()`
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 5 Dec 2016 15:42:55 +0000 (16:42 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 16 Feb 2017 15:51:53 +0000 (16:51 +0100)
This was not very well handled, and could cause the PowerDNS process
to terminate. This is especially nasty when `closesocket()` is called
from a destructor, as we could already be dealing with an exception.

(cherry picked from commit a7b68ae7e414ec9f3184df70ac8008f8a310ae60)

pdns/dnsproxy.cc
pdns/pdns_recursor.cc
pdns/resolver.cc
pdns/rfc2136handler.cc
pdns/sstuff.hh
pdns/tcpreceiver.cc
pdns/utility.hh

index 3f6342386287f9dcde98d23a55327dffb91ac794..dfcc09006aff24dcf8a99ded2e5bf8dcf2f3eca6 100644 (file)
@@ -304,6 +304,13 @@ void DNSProxy::mainloop(void)
 }
 
 DNSProxy::~DNSProxy() {
-  if (d_sock>-1) closesocket(d_sock);
+  if (d_sock>-1) {
+    try {
+      closesocket(d_sock);
+    }
+    catch(const PDNSException& e) {
+    }
+  }
+
   d_sock=-1;
 }
index 9b2acc8b8a2d3fbee48538d7e0ee967b8883a34a..a53ca2f6e2f5e55868374d51e994d56f42847121 100644 (file)
@@ -388,7 +388,13 @@ public:
     if(connect(*fd, (struct sockaddr*)(&toaddr), toaddr.getSocklen()) < 0) {
       int err = errno;
       //      returnSocket(*fd);
-      closesocket(*fd);
+      try {
+        closesocket(*fd);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing UDP socket after connect() failed: "<<e.reason<<endl;
+      }
+
       if(err==ENETUNREACH) // Seth "My Interfaces Are Like A Yo Yo" Arnold special
         return -2;
       return -1;
@@ -420,7 +426,12 @@ public:
     catch(FDMultiplexerException& e) {
       // we sometimes return a socket that has not yet been assigned to t_fdm
     }
-    closesocket(*i);
+    try {
+      closesocket(*i);
+    }
+    catch(const PDNSException& e) {
+      L<<Logger::Error<<"Error closing returned UDP socket: "<<e.reason<<endl;
+    }
 
     d_socks.erase(i++);
     --d_numsocks;
@@ -571,8 +582,14 @@ TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : d_remote(addr),
 
 TCPConnection::~TCPConnection()
 {
-  if(closesocket(d_fd) < 0)
-    unixDie("closing socket for TCPConnection");
+  try {
+    if(closesocket(d_fd) < 0)
+      L<<Logger::Error<<"Error closing socket for TCPConnection"<<endl;
+  }
+  catch(const PDNSException& e) {
+    L<<Logger::Error<<"Error closing TCPConnection socket: "<<e.reason<<endl;
+  }
+
   if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
     t_tcpClientCounts->erase(d_remote);
   --s_currentConnections;
@@ -1408,7 +1425,12 @@ void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
   if(newsock>=0) {
     if(MT->numProcesses() > g_maxMThreads) {
       g_stats.overCapacityDrops++;
-      closesocket(newsock);
+      try {
+        closesocket(newsock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing TCP socket after an over capacity drop: "<<e.reason<<endl;
+      }
       return;
     }
 
@@ -1419,12 +1441,22 @@ void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t& )
         L<<Logger::Error<<"["<<MT->getTid()<<"] dropping TCP query from "<<addr.toString()<<", address not matched by allow-from"<<endl;
 
       g_stats.unauthorizedTCP++;
-      closesocket(newsock);
+      try {
+        closesocket(newsock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing TCP socket after an ACL drop: "<<e.reason<<endl;
+      }
       return;
     }
     if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
       g_stats.tcpClientOverflow++;
-      closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
+      try {
+        closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing TCP socket after an overflow drop: "<<e.reason<<endl;
+      }
       return;
     }
 
index 6c00edd866dfb259bbc374fd7a38cb893662ea53..5a0148fdbb8be2b2aefc31bd5a75545c27b4cfce 100644 (file)
@@ -516,8 +516,14 @@ void AXFRRetriever::connect()
   int err;
 
   if((err=::connect(d_sock,(struct sockaddr*)&d_remote, d_remote.getSocklen()))<0 && errno!=EINPROGRESS) {
-    closesocket(d_sock);
-    d_sock=-1;
+    try {
+      closesocket(d_sock);
+    }
+    catch(const PDNSException& e) {
+      d_sock=-1;
+      throw ResolverException("Error closing AXFR socket after connect() failed: "+e.reason);
+    }
+
     throw ResolverException("connect: "+stringerror());
   }
 
@@ -527,7 +533,14 @@ void AXFRRetriever::connect()
   err=waitForRWData(d_sock, false, 10, 0); // wait for writeability
   
   if(!err) {
-    closesocket(d_sock); // timeout
+    try {
+      closesocket(d_sock); // timeout
+    }
+    catch(const PDNSException& e) {
+      d_sock=-1;
+      throw ResolverException("Error closing AXFR socket after timeout: "+e.reason);
+    }
+
     d_sock=-1;
     errno=ETIMEDOUT;
     
index 0a4ec7928e4fea59bc866a84bd1d95a7c9fcfd6c..f545935a7a85e722553c2a4e051f13a35f098e72 100644 (file)
@@ -603,7 +603,12 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn
 
     if( connect(sock, (struct sockaddr*)&remote, remote.getSocklen()) < 0 ) {
       L<<Logger::Error<<msgPrefix<<"Failed to connect to "<<remote.toStringWithPort()<<": "<<stringerror()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after connect() failed: "<<e.reason<<endl;
+      }
       continue;
     }
 
@@ -615,19 +620,34 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn
     buffer.append(forwardPacket.getString());
     if(write(sock, buffer.c_str(), buffer.length()) < 0) {
       L<<Logger::Error<<msgPrefix<<"Unable to forward update message to "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after write() failed: "<<e.reason<<endl;
+      }
       continue;
     }
 
     int res = waitForData(sock, 10, 0);
     if (!res) {
       L<<Logger::Error<<msgPrefix<<"Timeout waiting for reply from master at "<<remote.toStringWithPort()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after a timeout occured: "<<e.reason<<endl;
+      }
       continue;
     }
     if (res < 0) {
       L<<Logger::Error<<msgPrefix<<"Error waiting for answer from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after an error occured: "<<e.reason<<endl;
+      }
       continue;
     }
 
@@ -636,7 +656,12 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn
     recvRes = recv(sock, &lenBuf, sizeof(lenBuf), 0);
     if (recvRes < 0) {
       L<<Logger::Error<<msgPrefix<<"Could not receive data (length) from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after recv() failed: "<<e.reason<<endl;
+      }
       continue;
     }
     int packetLen = lenBuf[0]*256+lenBuf[1];
@@ -646,10 +671,20 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn
     recvRes = recv(sock, &buf, packetLen, 0);
     if (recvRes < 0) {
       L<<Logger::Error<<msgPrefix<<"Could not receive data (dnspacket) from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
-      closesocket(sock);
+      try {
+        closesocket(sock);
+      }
+      catch(const PDNSException& e) {
+        L<<Logger::Error<<"Error closing master forwarding socket after recv() failed: "<<e.reason<<endl;
+      }
       continue;
     }
-    closesocket(sock);
+    try {
+      closesocket(sock);
+    }
+    catch(const PDNSException& e) {
+      L<<Logger::Error<<"Error closing master forwarding socket: "<<e.reason<<endl;
+    }
 
     try {
       MOADNSParser mdp(false, buf, recvRes);
index c2ccc2d1812a70886122f9b53ed6e02c30189ca9..a730a8787ad266bdb9e7342c139d3112c56d8ed2 100644 (file)
@@ -78,7 +78,12 @@ public:
 
   ~Socket()
   {
-    closesocket(d_socket);
+    try {
+      closesocket(d_socket);
+    }
+    catch(const PDNSException& e) {
+    }
+
     delete[] d_buffer;
   }
 
index a85f3b65b7cd7b4a949a86d3adaba8eee8c04303..436cb631ce892ae171198f5473de8d7dde693f4c 100644 (file)
@@ -259,7 +259,12 @@ void *TCPNameserver::doConnection(void *data)
   if(getpeername(fd, (struct sockaddr *)&remote, &remotelen) < 0) {
     L<<Logger::Warning<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl;
     d_connectionroom_sem->post();
-    closesocket(fd);
+    try {
+      closesocket(fd);
+    }
+    catch(const PDNSException& e) {
+      L<<Logger::Error<<"Error closing TCP socket: "<<e.reason<<endl;
+    }
     return 0;
   }
 
@@ -386,7 +391,13 @@ void *TCPNameserver::doConnection(void *data)
     L << Logger::Error << "TCP Connection Thread caught unknown exception." << endl;
   }
   d_connectionroom_sem->post();
-  closesocket(fd);
+
+  try {
+    closesocket(fd);
+  }
+  catch(const PDNSException& e) {
+    L<<Logger::Error<<"Error closing TCP socket: "<<e.reason<<endl;
+  }
 
   return 0;
 }
index 8ea95fadc15ce3d6fcb9ee7a8f0caedf06f5d614..d197c7c743f67bcbb2cc672787d4b775281c6a7c 100644 (file)
@@ -92,9 +92,6 @@ public:
   typedef int sock_t;
   typedef ::socklen_t socklen_t;
 
-  //! Closes a socket.
-  static int closesocket( sock_t socket );
-
   //! Connect with timeout
   // Returns:
   //    > 0 on success