aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/epee/src')
-rw-r--r--contrib/epee/src/CMakeLists.txt2
-rw-r--r--contrib/epee/src/hex.cpp10
-rw-r--r--contrib/epee/src/mlocker.cpp182
-rw-r--r--contrib/epee/src/mlog.cpp4
-rw-r--r--contrib/epee/src/wipeable_string.cpp112
5 files changed, 303 insertions, 7 deletions
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index c4750cea0..0b5e7ae6c 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -27,7 +27,7 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c
- connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp)
+ connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp)
if (USE_READLINE AND GNU_READLINE_FOUND)
add_library(epee_readline STATIC readline_buffer.cpp)
endif()
diff --git a/contrib/epee/src/hex.cpp b/contrib/epee/src/hex.cpp
index c143b2dc2..5c8acc8be 100644
--- a/contrib/epee/src/hex.cpp
+++ b/contrib/epee/src/hex.cpp
@@ -52,17 +52,21 @@ namespace epee
}
}
- std::string to_hex::string(const span<const std::uint8_t> src)
+ template<typename T>
+ T to_hex::convert(const span<const std::uint8_t> src)
{
if (std::numeric_limits<std::size_t>::max() / 2 < src.size())
throw std::range_error("hex_view::to_string exceeded maximum size");
- std::string out{};
+ T out{};
out.resize(src.size() * 2);
- buffer_unchecked(std::addressof(out[0]), src);
+ to_hex::buffer_unchecked((char*)out.data(), src); // can't see the non const version in wipeable_string??
return out;
}
+ std::string to_hex::string(const span<const std::uint8_t> src) { return convert<std::string>(src); }
+ epee::wipeable_string to_hex::wipeable_string(const span<const std::uint8_t> src) { return convert<epee::wipeable_string>(src); }
+
void to_hex::buffer(std::ostream& out, const span<const std::uint8_t> src)
{
write_hex(std::ostreambuf_iterator<char>{out}, src);
diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp
new file mode 100644
index 000000000..5573d591a
--- /dev/null
+++ b/contrib/epee/src/mlocker.cpp
@@ -0,0 +1,182 @@
+// Copyright (c) 2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if defined __GNUC__ && !defined _WIN32
+#define HAVE_MLOCK 1
+#endif
+
+#include <unistd.h>
+#if defined HAVE_MLOCK
+#include <sys/mman.h>
+#endif
+#include "misc_log_ex.h"
+#include "syncobj.h"
+#include "mlocker.h"
+
+static size_t query_page_size()
+{
+#if defined HAVE_MLOCK
+ long ret = sysconf(_SC_PAGESIZE);
+ if (ret <= 0)
+ {
+ MERROR("Failed to determine page size");
+ return 0;
+ }
+ MINFO("Page size: " << ret);
+ return ret;
+#else
+#warning Missing query_page_size implementation
+#endif
+ return 0;
+}
+
+static void do_lock(void *ptr, size_t len)
+{
+#if defined HAVE_MLOCK
+ int ret = mlock(ptr, len);
+ if (ret < 0)
+ MERROR("Error locking page at " << ptr << ": " << strerror(errno));
+#else
+#warning Missing do_lock implementation
+#endif
+}
+
+static void do_unlock(void *ptr, size_t len)
+{
+#if defined HAVE_MLOCK
+ int ret = munlock(ptr, len);
+ if (ret < 0)
+ MERROR("Error unlocking page at " << ptr << ": " << strerror(errno));
+#else
+#warning Missing implementation of page size detection
+#endif
+}
+
+namespace epee
+{
+ size_t mlocker::page_size = 0;
+ size_t mlocker::num_locked_objects = 0;
+
+ boost::mutex &mlocker::mutex()
+ {
+ static boost::mutex vmutex;
+ return vmutex;
+ }
+ std::map<size_t, unsigned int> &mlocker::map()
+ {
+ static std::map<size_t, unsigned int> vmap;
+ return vmap;
+ }
+
+ size_t mlocker::get_page_size()
+ {
+ CRITICAL_REGION_LOCAL(mutex());
+ if (page_size == 0)
+ page_size = query_page_size();
+ return page_size;
+ }
+
+ mlocker::mlocker(void *ptr, size_t len): ptr(ptr), len(len)
+ {
+ lock(ptr, len);
+ }
+
+ mlocker::~mlocker()
+ {
+ unlock(ptr, len);
+ }
+
+ void mlocker::lock(void *ptr, size_t len)
+ {
+ size_t page_size = get_page_size();
+ if (page_size == 0)
+ return;
+
+ CRITICAL_REGION_LOCAL(mutex());
+ const size_t first = ((uintptr_t)ptr) / page_size;
+ const size_t last = (((uintptr_t)ptr) + len - 1) / page_size;
+ for (size_t page = first; page <= last; ++page)
+ lock_page(page);
+ ++num_locked_objects;
+ }
+
+ void mlocker::unlock(void *ptr, size_t len)
+ {
+ size_t page_size = get_page_size();
+ if (page_size == 0)
+ return;
+ CRITICAL_REGION_LOCAL(mutex());
+ const size_t first = ((uintptr_t)ptr) / page_size;
+ const size_t last = (((uintptr_t)ptr) + len - 1) / page_size;
+ for (size_t page = first; page <= last; ++page)
+ unlock_page(page);
+ --num_locked_objects;
+ }
+
+ size_t mlocker::get_num_locked_pages()
+ {
+ CRITICAL_REGION_LOCAL(mutex());
+ return map().size();
+ }
+
+ size_t mlocker::get_num_locked_objects()
+ {
+ CRITICAL_REGION_LOCAL(mutex());
+ return num_locked_objects;
+ }
+
+ void mlocker::lock_page(size_t page)
+ {
+ std::pair<std::map<size_t, unsigned int>::iterator, bool> p = map().insert(std::make_pair(page, 1));
+ if (p.second)
+ {
+ do_lock((void*)(page * page_size), page_size);
+ }
+ else
+ {
+ ++p.first->second;
+ }
+ }
+
+ void mlocker::unlock_page(size_t page)
+ {
+ std::map<size_t, unsigned int>::iterator i = map().find(page);
+ if (i == map().end())
+ {
+ MERROR("Attempt to unlock unlocked page at " << (void*)(page * page_size));
+ }
+ else
+ {
+ if (!--i->second)
+ {
+ map().erase(i);
+ do_unlock((void*)(page * page_size), page_size);
+ }
+ }
+ }
+}
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index e8248c958..818fc0a69 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -142,7 +142,9 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
{
std::vector<boost::filesystem::path> found_files;
const boost::filesystem::directory_iterator end_itr;
- for (boost::filesystem::directory_iterator iter(boost::filesystem::path(filename_base).parent_path()); iter != end_itr; ++iter)
+ const boost::filesystem::path filename_base_path(filename_base);
+ const boost::filesystem::path parent_path = filename_base_path.has_parent_path() ? filename_base_path.parent_path() : ".";
+ for (boost::filesystem::directory_iterator iter(parent_path); iter != end_itr; ++iter)
{
const std::string filename = iter->path().string();
if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp
index 6ed4ee8a2..7c9722765 100644
--- a/contrib/epee/src/wipeable_string.cpp
+++ b/contrib/epee/src/wipeable_string.cpp
@@ -26,11 +26,22 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <boost/optional/optional.hpp>
#include <string.h>
#include "memwipe.h"
#include "misc_log_ex.h"
#include "wipeable_string.h"
+namespace
+{
+ int atolower(int c)
+ {
+ if (c >= 'A' && c <= 'Z')
+ c |= 32;
+ return c;
+ }
+}
+
namespace epee
{
@@ -69,6 +80,12 @@ wipeable_string::wipeable_string(const char *s)
memcpy(buffer.data(), s, size());
}
+wipeable_string::wipeable_string(const char *s, size_t len)
+{
+ grow(len);
+ memcpy(buffer.data(), s, len);
+}
+
wipeable_string::~wipeable_string()
{
wipe();
@@ -109,9 +126,100 @@ void wipeable_string::push_back(char c)
buffer.back() = c;
}
-void wipeable_string::pop_back()
+void wipeable_string::operator+=(char c)
+{
+ push_back(c);
+}
+
+void wipeable_string::append(const char *ptr, size_t len)
+{
+ const size_t orgsz = size();
+ CHECK_AND_ASSERT_THROW_MES(orgsz < std::numeric_limits<size_t>::max() - len, "Appended data too large");
+ grow(orgsz + len);
+ if (len > 0)
+ memcpy(data() + orgsz, ptr, len);
+}
+
+void wipeable_string::operator+=(const char *s)
+{
+ append(s, strlen(s));
+}
+
+void wipeable_string::operator+=(const epee::wipeable_string &s)
+{
+ append(s.data(), s.size());
+}
+
+void wipeable_string::operator+=(const std::string &s)
+{
+ append(s.c_str(), s.size());
+}
+
+void wipeable_string::trim()
+{
+ size_t prefix = 0;
+ while (prefix < size() && data()[prefix] == ' ')
+ ++prefix;
+ if (prefix > 0)
+ memmove(buffer.data(), buffer.data() + prefix, size() - prefix);
+
+ size_t suffix = 0;
+ while (suffix < size()-prefix && data()[size() - 1 - prefix - suffix] == ' ')
+ ++suffix;
+
+ resize(size() - prefix - suffix);
+}
+
+void wipeable_string::split(std::vector<wipeable_string> &fields) const
+{
+ fields.clear();
+ size_t len = size();
+ const char *ptr = data();
+ bool space = true;
+ while (len--)
+ {
+ const char c = *ptr++;
+ if (c != ' ')
+ {
+ if (space)
+ fields.push_back({});
+ fields.back().push_back(c);
+ }
+ space = c == ' ';
+ }
+}
+
+boost::optional<epee::wipeable_string> wipeable_string::parse_hexstr() const
+{
+ if (size() % 2 != 0)
+ return boost::none;
+ boost::optional<epee::wipeable_string> res = epee::wipeable_string("");
+ const size_t len = size();
+ const char *d = data();
+ res->grow(0, len / 2);
+ static constexpr const char hex[] = u8"0123456789abcdef";
+ for (size_t i = 0; i < len; i += 2)
+ {
+ char c = atolower(d[i]);
+ const char *ptr0 = strchr(hex, c);
+ if (!ptr0)
+ return boost::none;
+ c = atolower(d[i+1]);
+ const char *ptr1 = strchr(hex, c);
+ if (!ptr1)
+ return boost::none;
+ res->push_back(((ptr0-hex)<<4) | (ptr1-hex));
+ }
+ return res;
+}
+
+char wipeable_string::pop_back()
{
- resize(size() - 1);
+ const size_t sz = size();
+ CHECK_AND_ASSERT_THROW_MES(sz > 0, "Popping from an empty string");
+ const char c = buffer.back();
+ resize(sz - 1);
+ return c;
}
void wipeable_string::resize(size_t sz)