]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
More fail-safe handling of NOD files
authorOtto <otto.moerbeek@open-xchange.com>
Mon, 29 Mar 2021 08:40:37 +0000 (10:40 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 29 Mar 2021 08:50:43 +0000 (10:50 +0200)
pdns/nod.cc
pdns/recursordist/stable-bloom.hh

index 0605c513589b1faec093bd45fb465679f36a41c0..cc0b2761e2458e2a2501bf0389bd41373147c747 100644 (file)
@@ -86,7 +86,9 @@ bool PersistentSBF::init(bool ignore_pid) {
             remove(newest_file);
           }
           catch (const std::runtime_error& e) {
-            g_log<<Logger::Warning<<"NODDB init: Cannot parse file: " << filename << endl;
+            infile.close();
+            remove(newest_file);
+            g_log<<Logger::Warning<<"NODDB init: Cannot parse file: " << filename << ": " << e.what() << "; removed" << endl;
           }
         }
       }
@@ -124,11 +126,13 @@ bool PersistentSBF::snapshotCurrent(std::thread::id tid)
     std::stringstream ss;
     ss << d_prefix << "_" << tid;
     f /= ss.str() + "_" + std::to_string(getpid()) + "." + bf_suffix;
+    path ftmp = f;
+    ftmp += ".tmp";
     if (exists(p) && is_directory(p)) {
       try {
         std::ofstream ofile;
         std::stringstream iss;
-        ofile.open(f.string(), std::ios::out | std::ios::binary);
+        ofile.open(ftmp.string(), std::ios::out | std::ios::binary);
         {
           // only lock while dumping to a stringstream
           std::lock_guard<std::mutex> lock(d_sbf_mutex);
@@ -137,8 +141,13 @@ bool PersistentSBF::snapshotCurrent(std::thread::id tid)
         // Now write it out to the file
         ofile << iss.str();
 
-        if (ofile.fail())
-          throw std::runtime_error("Failed to write to file:" + f.string());
+        if (ofile.fail()) {
+          ofile.close();
+          remove(ftmp);
+          throw std::runtime_error("Failed to write to file:" + ftmp.string());
+        }
+        ofile.close();
+        rename(ftmp, f);
         return true;
       }
       catch (const std::runtime_error& e) {
index e15723589acb0a17a2fa3fde048aabee36c43326..a6cc5720f6321927ffebd49f8e132cc8d7d97ce4 100644 (file)
@@ -106,13 +106,28 @@ public:
     uint8_t k, p;
     uint32_t num_cells, bitstr_len;
     is.read((char*)&k, sizeof(k));
+    if (is.fail()) {
+      throw std::runtime_error("SBF: read failed (file too short?)");
+    }
     is.read((char*)&num_cells, sizeof(num_cells));
+    if (is.fail()) {
+      throw std::runtime_error("SBF: read failed (file too short?)");
+    }
     num_cells = ntohl(num_cells);
     is.read((char*)&p, sizeof(p));
+    if (is.fail()) {
+      throw std::runtime_error("SBF: read failed (file too short?)");
+    }
     is.read((char*)&bitstr_len, sizeof(bitstr_len));
+    if (is.fail()) {
+      throw std::runtime_error("SBF: read failed (file too short?)");
+    }
     bitstr_len = ntohl(bitstr_len);
     char* bitcstr = new char[bitstr_len];
     is.read((char*)bitcstr, bitstr_len);
+    if (is.fail()) {
+      throw std::runtime_error("SBF: read failed (file too short?)");
+    }
     std::string bitstr(bitcstr, bitstr_len);
     delete[] bitcstr;
     stableBF tempbf(k, num_cells, p, bitstr);