From: Otto Date: Mon, 29 Mar 2021 13:27:43 +0000 (+0200) Subject: Safe tmp file handling, basic sanity check on size of data. X-Git-Tag: dnsdist-1.6.0-rc1~46^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F10238%2Fhead;p=thirdparty%2Fpdns.git Safe tmp file handling, basic sanity check on size of data. --- diff --git a/pdns/nod.cc b/pdns/nod.cc index af86697ddc..cc2e9de73c 100644 --- a/pdns/nod.cc +++ b/pdns/nod.cc @@ -28,8 +28,7 @@ #include #include #include "threadname.hh" -#include -#include +#include #include "logger.hh" #include "misc.hh" @@ -40,10 +39,9 @@ namespace filesystem = boost::filesystem; std::mutex PersistentSBF::d_cachedir_mutex; -void PersistentSBF::remove_tmp_files() +void PersistentSBF::remove_tmp_files(const filesystem::path& p, std::lock_guard& lock) { - filesystem::path p(d_cachedir); - Regex file_regex(d_prefix + ".*\\." + bf_suffix + "\\.[[:xdigit:]]{8}$"); + Regex file_regex(d_prefix + ".*\\." + bf_suffix + "\\..{8}$"); for (filesystem::directory_iterator i(p); i != filesystem::directory_iterator(); ++i) { if (filesystem::is_regular_file(i->path()) && file_regex.match(i->path().filename().string())) { filesystem::remove(*i); @@ -65,7 +63,7 @@ bool PersistentSBF::init(bool ignore_pid) { filesystem::path p(d_cachedir); try { if (filesystem::exists(p) && filesystem::is_directory(p)) { - remove_tmp_files(); + remove_tmp_files(p, lock); filesystem::path newest_file; std::time_t newest_time=time(nullptr); Regex file_regex(d_prefix + ".*\\." + bf_suffix + "$"); @@ -138,7 +136,6 @@ bool PersistentSBF::snapshotCurrent(std::thread::id tid) std::stringstream ss; ss << d_prefix << "_" << tid; f /= ss.str() + "_" + std::to_string(getpid()) + "." + bf_suffix; - filesystem::path ftmp(filesystem::unique_path(f.string() + ".%%%%%%%%")); if (filesystem::exists(p) && filesystem::is_directory(p)) { try { std::ofstream ofile; @@ -149,15 +146,22 @@ bool PersistentSBF::snapshotCurrent(std::thread::id tid) d_sbf.dump(iss); } // Now write it out to the file - ofile.open(ftmp.string(), std::ios::out | std::ios::binary); - ofile << iss.str(); - - if (ofile.fail()) { - ofile.close(); + std::string ftmp = f.string() + ".XXXXXXXX"; + int fd = mkstemp(&ftmp.at(0)); + if (fd == -1) { + throw std::runtime_error("Cannot create temp file: " + stringerror()); + } + std::string str = iss.str(); + ssize_t len = write(fd, str.data(), str.length()); + if (len != static_cast(str.length())) { + close(fd); + filesystem::remove(ftmp.c_str()); + throw std::runtime_error("Failed to write to file:" + ftmp); + } + if (close(fd) != 0) { filesystem::remove(ftmp); - throw std::runtime_error("Failed to write to file:" + ftmp.string()); + throw std::runtime_error("Failed to write to file:" + ftmp); } - ofile.close(); try { filesystem::rename(ftmp, f); } diff --git a/pdns/nod.hh b/pdns/nod.hh index a801b1a0e5..0def55606b 100644 --- a/pdns/nod.hh +++ b/pdns/nod.hh @@ -23,6 +23,7 @@ #include #include #include +#include #include "dnsname.hh" #include "stable-bloom.hh" @@ -59,7 +60,7 @@ namespace nod { return d_sbf.testAndAdd(data); } private: - void remove_tmp_files(); + void remove_tmp_files(const boost::filesystem::path&, std::lock_guard&); bool d_init{false}; bf::stableBF d_sbf; // Stable Bloom Filter diff --git a/pdns/recursordist/stable-bloom.hh b/pdns/recursordist/stable-bloom.hh index 9fc343f88b..947e92ed0c 100644 --- a/pdns/recursordist/stable-bloom.hh +++ b/pdns/recursordist/stable-bloom.hh @@ -123,6 +123,9 @@ public: throw std::runtime_error("SBF: read failed (file too short?)"); } bitstr_len = ntohl(bitstr_len); + if (bitstr_len > 2 * 64 * 1024 * 1024U) { // twice the current size + throw std::runtime_error("SBF: read failed (bitstr_len too big)"); + } unique_ptr bitcstr = make_unique(bitstr_len); is.read(bitcstr.get(), bitstr_len); if (is.fail()) {