aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/any.h26
-rw-r--r--src/util/batchpriority.cpp26
-rw-r--r--src/util/batchpriority.h15
-rw-r--r--src/util/bip32.cpp8
-rw-r--r--src/util/bip32.h4
-rw-r--r--src/util/bytevectorhash.cpp2
-rw-r--r--src/util/chaintype.cpp39
-rw-r--r--src/util/chaintype.h22
-rw-r--r--src/util/fs.h2
-rw-r--r--src/util/hasher.cpp2
-rw-r--r--src/util/insert.h24
-rw-r--r--src/util/result.h5
-rw-r--r--src/util/settings.cpp258
-rw-r--r--src/util/settings.h114
-rw-r--r--src/util/signalinterrupt.cpp74
-rw-r--r--src/util/signalinterrupt.h52
-rw-r--r--src/util/sock.cpp2
-rw-r--r--src/util/strencodings.h4
-rw-r--r--src/util/string.h4
-rw-r--r--src/util/syscall_sandbox.cpp927
-rw-r--r--src/util/syscall_sandbox.h54
-rw-r--r--src/util/system.cpp125
-rw-r--r--src/util/system.h72
-rw-r--r--src/util/threadinterrupt.h16
-rw-r--r--src/util/time.cpp13
-rw-r--r--src/util/time.h3
-rw-r--r--src/util/translation.h22
27 files changed, 316 insertions, 1599 deletions
diff --git a/src/util/any.h b/src/util/any.h
new file mode 100644
index 0000000000..4562c5bd8a
--- /dev/null
+++ b/src/util/any.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_ANY_H
+#define BITCOIN_UTIL_ANY_H
+
+#include <any>
+
+namespace util {
+
+/**
+ * Helper function to access the contained object of a std::any instance.
+ * Returns a pointer to the object if passed instance has a value and the type
+ * matches, nullptr otherwise.
+ */
+template<typename T>
+T* AnyPtr(const std::any& any) noexcept
+{
+ T* const* ptr = std::any_cast<T*>(&any);
+ return ptr ? *ptr : nullptr;
+}
+
+} // namespace util
+
+#endif // BITCOIN_UTIL_ANY_H
diff --git a/src/util/batchpriority.cpp b/src/util/batchpriority.cpp
new file mode 100644
index 0000000000..c73aef1eb4
--- /dev/null
+++ b/src/util/batchpriority.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <logging.h>
+#include <util/syserror.h>
+
+#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
+#include <pthread.h>
+#include <pthread_np.h>
+#endif
+
+#ifndef WIN32
+#include <sched.h>
+#endif
+
+void ScheduleBatchPriority()
+{
+#ifdef SCHED_BATCH
+ const static sched_param param{};
+ const int rc = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
+ if (rc != 0) {
+ LogPrintf("Failed to pthread_setschedparam: %s\n", SysErrorString(rc));
+ }
+#endif
+}
diff --git a/src/util/batchpriority.h b/src/util/batchpriority.h
new file mode 100644
index 0000000000..5ffc8dd684
--- /dev/null
+++ b/src/util/batchpriority.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_BATCHPRIORITY_H
+#define BITCOIN_UTIL_BATCHPRIORITY_H
+
+/**
+ * On platforms that support it, tell the kernel the calling thread is
+ * CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
+ *
+ */
+void ScheduleBatchPriority();
+
+#endif // BITCOIN_UTIL_BATCHPRIORITY_H
diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp
index c0ad9257ce..4ab14bd704 100644
--- a/src/util/bip32.cpp
+++ b/src/util/bip32.cpp
@@ -51,17 +51,17 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypa
return true;
}
-std::string FormatHDKeypath(const std::vector<uint32_t>& path)
+std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe)
{
std::string ret;
for (auto i : path) {
ret += strprintf("/%i", (i << 1) >> 1);
- if (i >> 31) ret += '\'';
+ if (i >> 31) ret += apostrophe ? '\'' : 'h';
}
return ret;
}
-std::string WriteHDKeypath(const std::vector<uint32_t>& keypath)
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe)
{
- return "m" + FormatHDKeypath(keypath);
+ return "m" + FormatHDKeypath(keypath, apostrophe);
}
diff --git a/src/util/bip32.h b/src/util/bip32.h
index b720cb5638..ea5f192c07 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -13,7 +13,7 @@
[[nodiscard]] bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
/** Write HD keypaths as strings */
-std::string WriteHDKeypath(const std::vector<uint32_t>& keypath);
-std::string FormatHDKeypath(const std::vector<uint32_t>& path);
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe = false);
+std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe = false);
#endif // BITCOIN_UTIL_BIP32_H
diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
index 29be138eeb..92f1dbd5d8 100644
--- a/src/util/bytevectorhash.cpp
+++ b/src/util/bytevectorhash.cpp
@@ -16,5 +16,5 @@ ByteVectorHash::ByteVectorHash() :
size_t ByteVectorHash::operator()(const std::vector<unsigned char>& input) const
{
- return CSipHasher(m_k0, m_k1).Write(input.data(), input.size()).Finalize();
+ return CSipHasher(m_k0, m_k1).Write(input).Finalize();
}
diff --git a/src/util/chaintype.cpp b/src/util/chaintype.cpp
new file mode 100644
index 0000000000..8a199e352a
--- /dev/null
+++ b/src/util/chaintype.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/chaintype.h>
+
+#include <cassert>
+#include <optional>
+#include <string>
+
+std::string ChainTypeToString(ChainType chain)
+{
+ switch (chain) {
+ case ChainType::MAIN:
+ return "main";
+ case ChainType::TESTNET:
+ return "test";
+ case ChainType::SIGNET:
+ return "signet";
+ case ChainType::REGTEST:
+ return "regtest";
+ }
+ assert(false);
+}
+
+std::optional<ChainType> ChainTypeFromString(std::string_view chain)
+{
+ if (chain == "main") {
+ return ChainType::MAIN;
+ } else if (chain == "test") {
+ return ChainType::TESTNET;
+ } else if (chain == "signet") {
+ return ChainType::SIGNET;
+ } else if (chain == "regtest") {
+ return ChainType::REGTEST;
+ } else {
+ return std::nullopt;
+ }
+}
diff --git a/src/util/chaintype.h b/src/util/chaintype.h
new file mode 100644
index 0000000000..c73985df57
--- /dev/null
+++ b/src/util/chaintype.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_CHAINTYPE_H
+#define BITCOIN_UTIL_CHAINTYPE_H
+
+#include <optional>
+#include <string>
+
+enum class ChainType {
+ MAIN,
+ TESTNET,
+ SIGNET,
+ REGTEST,
+};
+
+std::string ChainTypeToString(ChainType chain);
+
+std::optional<ChainType> ChainTypeFromString(std::string_view chain);
+
+#endif // BITCOIN_UTIL_CHAINTYPE_H
diff --git a/src/util/fs.h b/src/util/fs.h
index 886a30394e..8f79f6cba6 100644
--- a/src/util/fs.h
+++ b/src/util/fs.h
@@ -8,7 +8,7 @@
#include <tinyformat.h>
#include <cstdio>
-#include <filesystem>
+#include <filesystem> // IWYU pragma: export
#include <functional>
#include <iomanip>
#include <ios>
diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp
index 81e9b990e1..f571725786 100644
--- a/src/util/hasher.cpp
+++ b/src/util/hasher.cpp
@@ -18,5 +18,5 @@ SaltedSipHasher::SaltedSipHasher() : m_k0(GetRand<uint64_t>()), m_k1(GetRand<uin
size_t SaltedSipHasher::operator()(const Span<const unsigned char>& script) const
{
- return CSipHasher(m_k0, m_k1).Write(script.data(), script.size()).Finalize();
+ return CSipHasher(m_k0, m_k1).Write(script).Finalize();
}
diff --git a/src/util/insert.h b/src/util/insert.h
new file mode 100644
index 0000000000..5332eca60a
--- /dev/null
+++ b/src/util/insert.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_INSERT_H
+#define BITCOIN_UTIL_INSERT_H
+
+#include <set>
+
+namespace util {
+
+//! Simplification of std insertion
+template <typename Tdst, typename Tsrc>
+inline void insert(Tdst& dst, const Tsrc& src) {
+ dst.insert(dst.begin(), src.begin(), src.end());
+}
+template <typename TsetT, typename Tsrc>
+inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
+ dst.insert(src.begin(), src.end());
+}
+
+} // namespace util
+
+#endif // BITCOIN_UTIL_INSERT_H
diff --git a/src/util/result.h b/src/util/result.h
index 972b1aada0..b99995c7e5 100644
--- a/src/util/result.h
+++ b/src/util/result.h
@@ -31,16 +31,19 @@ struct Error {
//! `std::optional<T>` can be updated to return `util::Result<T>` and return
//! error strings usually just replacing `return std::nullopt;` with `return
//! util::Error{error_string};`.
-template <class T>
+template <class M>
class Result
{
private:
+ using T = std::conditional_t<std::is_same_v<M, void>, std::monostate, M>;
+
std::variant<bilingual_str, T> m_variant;
template <typename FT>
friend bilingual_str ErrorString(const Result<FT>& result);
public:
+ Result() : m_variant{std::in_place_index_t<1>{}, std::monostate{}} {} // constructor for void
Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
diff --git a/src/util/settings.cpp b/src/util/settings.cpp
deleted file mode 100644
index bb257c0584..0000000000
--- a/src/util/settings.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (c) 2019-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <util/fs.h>
-#include <util/settings.h>
-
-#include <tinyformat.h>
-#include <univalue.h>
-
-#include <fstream>
-#include <map>
-#include <string>
-#include <vector>
-
-namespace util {
-namespace {
-
-enum class Source {
- FORCED,
- COMMAND_LINE,
- RW_SETTINGS,
- CONFIG_FILE_NETWORK_SECTION,
- CONFIG_FILE_DEFAULT_SECTION
-};
-
-//! Merge settings from multiple sources in precedence order:
-//! Forced config > command line > read-write settings file > config file network-specific section > config file default section
-//!
-//! This function is provided with a callback function fn that contains
-//! specific logic for how to merge the sources.
-template <typename Fn>
-static void MergeSettings(const Settings& settings, const std::string& section, const std::string& name, Fn&& fn)
-{
- // Merge in the forced settings
- if (auto* value = FindKey(settings.forced_settings, name)) {
- fn(SettingsSpan(*value), Source::FORCED);
- }
- // Merge in the command-line options
- if (auto* values = FindKey(settings.command_line_options, name)) {
- fn(SettingsSpan(*values), Source::COMMAND_LINE);
- }
- // Merge in the read-write settings
- if (const SettingsValue* value = FindKey(settings.rw_settings, name)) {
- fn(SettingsSpan(*value), Source::RW_SETTINGS);
- }
- // Merge in the network-specific section of the config file
- if (!section.empty()) {
- if (auto* map = FindKey(settings.ro_config, section)) {
- if (auto* values = FindKey(*map, name)) {
- fn(SettingsSpan(*values), Source::CONFIG_FILE_NETWORK_SECTION);
- }
- }
- }
- // Merge in the default section of the config file
- if (auto* map = FindKey(settings.ro_config, "")) {
- if (auto* values = FindKey(*map, name)) {
- fn(SettingsSpan(*values), Source::CONFIG_FILE_DEFAULT_SECTION);
- }
- }
-}
-} // namespace
-
-bool ReadSettings(const fs::path& path, std::map<std::string, SettingsValue>& values, std::vector<std::string>& errors)
-{
- values.clear();
- errors.clear();
-
- // Ok for file to not exist
- if (!fs::exists(path)) return true;
-
- std::ifstream file;
- file.open(path);
- if (!file.is_open()) {
- errors.emplace_back(strprintf("%s. Please check permissions.", fs::PathToString(path)));
- return false;
- }
-
- SettingsValue in;
- if (!in.read(std::string{std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()})) {
- errors.emplace_back(strprintf("Unable to parse settings file %s", fs::PathToString(path)));
- return false;
- }
-
- if (file.fail()) {
- errors.emplace_back(strprintf("Failed reading settings file %s", fs::PathToString(path)));
- return false;
- }
- file.close(); // Done with file descriptor. Release while copying data.
-
- if (!in.isObject()) {
- errors.emplace_back(strprintf("Found non-object value %s in settings file %s", in.write(), fs::PathToString(path)));
- return false;
- }
-
- const std::vector<std::string>& in_keys = in.getKeys();
- const std::vector<SettingsValue>& in_values = in.getValues();
- for (size_t i = 0; i < in_keys.size(); ++i) {
- auto inserted = values.emplace(in_keys[i], in_values[i]);
- if (!inserted.second) {
- errors.emplace_back(strprintf("Found duplicate key %s in settings file %s", in_keys[i], fs::PathToString(path)));
- values.clear();
- break;
- }
- }
- return errors.empty();
-}
-
-bool WriteSettings(const fs::path& path,
- const std::map<std::string, SettingsValue>& values,
- std::vector<std::string>& errors)
-{
- SettingsValue out(SettingsValue::VOBJ);
- for (const auto& value : values) {
- out.__pushKV(value.first, value.second);
- }
- std::ofstream file;
- file.open(path);
- if (file.fail()) {
- errors.emplace_back(strprintf("Error: Unable to open settings file %s for writing", fs::PathToString(path)));
- return false;
- }
- file << out.write(/* prettyIndent= */ 4, /* indentLevel= */ 1) << std::endl;
- file.close();
- return true;
-}
-
-SettingsValue GetSetting(const Settings& settings,
- const std::string& section,
- const std::string& name,
- bool ignore_default_section_config,
- bool ignore_nonpersistent,
- bool get_chain_name)
-{
- SettingsValue result;
- bool done = false; // Done merging any more settings sources.
- MergeSettings(settings, section, name, [&](SettingsSpan span, Source source) {
- // Weird behavior preserved for backwards compatibility: Apply negated
- // setting even if non-negated setting would be ignored. A negated
- // value in the default section is applied to network specific options,
- // even though normal non-negated values there would be ignored.
- const bool never_ignore_negated_setting = span.last_negated();
-
- // Weird behavior preserved for backwards compatibility: Take first
- // assigned value instead of last. In general, later settings take
- // precedence over early settings, but for backwards compatibility in
- // the config file the precedence is reversed for all settings except
- // chain name settings.
- const bool reverse_precedence =
- (source == Source::CONFIG_FILE_NETWORK_SECTION || source == Source::CONFIG_FILE_DEFAULT_SECTION) &&
- !get_chain_name;
-
- // Weird behavior preserved for backwards compatibility: Negated
- // -regtest and -testnet arguments which you would expect to override
- // values set in the configuration file are currently accepted but
- // silently ignored. It would be better to apply these just like other
- // negated values, or at least warn they are ignored.
- const bool skip_negated_command_line = get_chain_name;
-
- if (done) return;
-
- // Ignore settings in default config section if requested.
- if (ignore_default_section_config && source == Source::CONFIG_FILE_DEFAULT_SECTION &&
- !never_ignore_negated_setting) {
- return;
- }
-
- // Ignore nonpersistent settings if requested.
- if (ignore_nonpersistent && (source == Source::COMMAND_LINE || source == Source::FORCED)) return;
-
- // Skip negated command line settings.
- if (skip_negated_command_line && span.last_negated()) return;
-
- if (!span.empty()) {
- result = reverse_precedence ? span.begin()[0] : span.end()[-1];
- done = true;
- } else if (span.last_negated()) {
- result = false;
- done = true;
- }
- });
- return result;
-}
-
-std::vector<SettingsValue> GetSettingsList(const Settings& settings,
- const std::string& section,
- const std::string& name,
- bool ignore_default_section_config)
-{
- std::vector<SettingsValue> result;
- bool done = false; // Done merging any more settings sources.
- bool prev_negated_empty = false;
- MergeSettings(settings, section, name, [&](SettingsSpan span, Source source) {
- // Weird behavior preserved for backwards compatibility: Apply config
- // file settings even if negated on command line. Negating a setting on
- // command line will ignore earlier settings on the command line and
- // ignore settings in the config file, unless the negated command line
- // value is followed by non-negated value, in which case config file
- // settings will be brought back from the dead (but earlier command
- // line settings will still be ignored).
- const bool add_zombie_config_values =
- (source == Source::CONFIG_FILE_NETWORK_SECTION || source == Source::CONFIG_FILE_DEFAULT_SECTION) &&
- !prev_negated_empty;
-
- // Ignore settings in default config section if requested.
- if (ignore_default_section_config && source == Source::CONFIG_FILE_DEFAULT_SECTION) return;
-
- // Add new settings to the result if isn't already complete, or if the
- // values are zombies.
- if (!done || add_zombie_config_values) {
- for (const auto& value : span) {
- if (value.isArray()) {
- result.insert(result.end(), value.getValues().begin(), value.getValues().end());
- } else {
- result.push_back(value);
- }
- }
- }
-
- // If a setting was negated, or if a setting was forced, set
- // done to true to ignore any later lower priority settings.
- done |= span.negated() > 0 || source == Source::FORCED;
-
- // Update the negated and empty state used for the zombie values check.
- prev_negated_empty |= span.last_negated() && result.empty();
- });
- return result;
-}
-
-bool OnlyHasDefaultSectionSetting(const Settings& settings, const std::string& section, const std::string& name)
-{
- bool has_default_section_setting = false;
- bool has_other_setting = false;
- MergeSettings(settings, section, name, [&](SettingsSpan span, Source source) {
- if (span.empty()) return;
- else if (source == Source::CONFIG_FILE_DEFAULT_SECTION) has_default_section_setting = true;
- else has_other_setting = true;
- });
- // If a value is set in the default section and not explicitly overwritten by the
- // user on the command line or in a different section, then we want to enable
- // warnings about the value being ignored.
- return has_default_section_setting && !has_other_setting;
-}
-
-SettingsSpan::SettingsSpan(const std::vector<SettingsValue>& vec) noexcept : SettingsSpan(vec.data(), vec.size()) {}
-const SettingsValue* SettingsSpan::begin() const { return data + negated(); }
-const SettingsValue* SettingsSpan::end() const { return data + size; }
-bool SettingsSpan::empty() const { return size == 0 || last_negated(); }
-bool SettingsSpan::last_negated() const { return size > 0 && data[size - 1].isFalse(); }
-size_t SettingsSpan::negated() const
-{
- for (size_t i = size; i > 0; --i) {
- if (data[i - 1].isFalse()) return i; // Return number of negated values (position of last false value)
- }
- return 0;
-}
-
-} // namespace util
diff --git a/src/util/settings.h b/src/util/settings.h
deleted file mode 100644
index 27e87a4751..0000000000
--- a/src/util/settings.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2019-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_UTIL_SETTINGS_H
-#define BITCOIN_UTIL_SETTINGS_H
-
-#include <util/fs.h>
-
-#include <map>
-#include <string>
-#include <vector>
-
-class UniValue;
-
-namespace util {
-
-//! Settings value type (string/integer/boolean/null variant).
-//!
-//! @note UniValue is used here for convenience and because it can be easily
-//! serialized in a readable format. But any other variant type that can
-//! be assigned strings, int64_t, and bool values and has get_str(),
-//! getInt<int64_t>(), get_bool(), isNum(), isBool(), isFalse(), isTrue() and
-//! isNull() methods can be substituted if there's a need to move away
-//! from UniValue. (An implementation with boost::variant was posted at
-//! https://github.com/bitcoin/bitcoin/pull/15934/files#r337691812)
-using SettingsValue = UniValue;
-
-//! Stored settings. This struct combines settings from the command line, a
-//! read-only configuration file, and a read-write runtime settings file.
-struct Settings {
- //! Map of setting name to forced setting value.
- std::map<std::string, SettingsValue> forced_settings;
- //! Map of setting name to list of command line values.
- std::map<std::string, std::vector<SettingsValue>> command_line_options;
- //! Map of setting name to read-write file setting value.
- std::map<std::string, SettingsValue> rw_settings;
- //! Map of config section name and setting name to list of config file values.
- std::map<std::string, std::map<std::string, std::vector<SettingsValue>>> ro_config;
-};
-
-//! Read settings file.
-bool ReadSettings(const fs::path& path,
- std::map<std::string, SettingsValue>& values,
- std::vector<std::string>& errors);
-
-//! Write settings file.
-bool WriteSettings(const fs::path& path,
- const std::map<std::string, SettingsValue>& values,
- std::vector<std::string>& errors);
-
-//! Get settings value from combined sources: forced settings, command line
-//! arguments, runtime read-write settings, and the read-only config file.
-//!
-//! @param ignore_default_section_config - ignore values in the default section
-//! of the config file (part before any
-//! [section] keywords)
-//! @param ignore_nonpersistent - ignore non-persistent settings values (forced
-//! settings values and values specified on the
-//! command line). Only return settings in the
-//! read-only config and read-write settings
-//! files.
-//! @param get_chain_name - enable special backwards compatible behavior
-//! for GetChainName
-SettingsValue GetSetting(const Settings& settings,
- const std::string& section,
- const std::string& name,
- bool ignore_default_section_config,
- bool ignore_nonpersistent,
- bool get_chain_name);
-
-//! Get combined setting value similar to GetSetting(), except if setting was
-//! specified multiple times, return a list of all the values specified.
-std::vector<SettingsValue> GetSettingsList(const Settings& settings,
- const std::string& section,
- const std::string& name,
- bool ignore_default_section_config);
-
-//! Return true if a setting is set in the default config file section, and not
-//! overridden by a higher priority command-line or network section value.
-//!
-//! This is used to provide user warnings about values that might be getting
-//! ignored unintentionally.
-bool OnlyHasDefaultSectionSetting(const Settings& settings, const std::string& section, const std::string& name);
-
-//! Accessor for list of settings that skips negated values when iterated over.
-//! The last boolean `false` value in the list and all earlier values are
-//! considered negated.
-struct SettingsSpan {
- explicit SettingsSpan() = default;
- explicit SettingsSpan(const SettingsValue& value) noexcept : SettingsSpan(&value, 1) {}
- explicit SettingsSpan(const SettingsValue* data, size_t size) noexcept : data(data), size(size) {}
- explicit SettingsSpan(const std::vector<SettingsValue>& vec) noexcept;
- const SettingsValue* begin() const; //!< Pointer to first non-negated value.
- const SettingsValue* end() const; //!< Pointer to end of values.
- bool empty() const; //!< True if there are any non-negated values.
- bool last_negated() const; //!< True if the last value is negated.
- size_t negated() const; //!< Number of negated values.
-
- const SettingsValue* data = nullptr;
- size_t size = 0;
-};
-
-//! Map lookup helper.
-template <typename Map, typename Key>
-auto FindKey(Map&& map, Key&& key) -> decltype(&map.at(key))
-{
- auto it = map.find(key);
- return it == map.end() ? nullptr : &it->second;
-}
-
-} // namespace util
-
-#endif // BITCOIN_UTIL_SETTINGS_H
diff --git a/src/util/signalinterrupt.cpp b/src/util/signalinterrupt.cpp
new file mode 100644
index 0000000000..c551ba8044
--- /dev/null
+++ b/src/util/signalinterrupt.cpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/signalinterrupt.h>
+
+#ifdef WIN32
+#include <mutex>
+#else
+#include <util/tokenpipe.h>
+#endif
+
+#include <ios>
+#include <optional>
+
+namespace util {
+
+SignalInterrupt::SignalInterrupt() : m_flag{false}
+{
+#ifndef WIN32
+ std::optional<TokenPipe> pipe = TokenPipe::Make();
+ if (!pipe) throw std::ios_base::failure("Could not create TokenPipe");
+ m_pipe_r = pipe->TakeReadEnd();
+ m_pipe_w = pipe->TakeWriteEnd();
+#endif
+}
+
+SignalInterrupt::operator bool() const
+{
+ return m_flag;
+}
+
+void SignalInterrupt::reset()
+{
+ // Cancel existing interrupt by waiting for it, this will reset condition flags and remove
+ // the token from the pipe.
+ if (*this) wait();
+ m_flag = false;
+}
+
+void SignalInterrupt::operator()()
+{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(m_mutex);
+ m_flag = true;
+ m_cv.notify_one();
+#else
+ // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
+ // Make sure that the token is only written once even if multiple threads call this concurrently or in
+ // case of a reentrant signal.
+ if (!m_flag.exchange(true)) {
+ // Write an arbitrary byte to the write end of the pipe.
+ int res = m_pipe_w.TokenWrite('x');
+ if (res != 0) {
+ throw std::ios_base::failure("Could not write interrupt token");
+ }
+ }
+#endif
+}
+
+void SignalInterrupt::wait()
+{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(m_mutex);
+ m_cv.wait(lk, [this] { return m_flag.load(); });
+#else
+ int res = m_pipe_r.TokenRead();
+ if (res != 'x') {
+ throw std::ios_base::failure("Did not read expected interrupt token");
+ }
+#endif
+}
+
+} // namespace util
diff --git a/src/util/signalinterrupt.h b/src/util/signalinterrupt.h
new file mode 100644
index 0000000000..ca02feda91
--- /dev/null
+++ b/src/util/signalinterrupt.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_SIGNALINTERRUPT_H
+#define BITCOIN_UTIL_SIGNALINTERRUPT_H
+
+#ifdef WIN32
+#include <condition_variable>
+#include <mutex>
+#else
+#include <util/tokenpipe.h>
+#endif
+
+#include <atomic>
+#include <cstdlib>
+
+namespace util {
+/**
+ * Helper class that manages an interrupt flag, and allows a thread or
+ * signal to interrupt another thread.
+ *
+ * This class is safe to be used in a signal handler. If sending an interrupt
+ * from a signal handler is not necessary, the more lightweight \ref
+ * CThreadInterrupt class can be used instead.
+ */
+
+class SignalInterrupt
+{
+public:
+ SignalInterrupt();
+ explicit operator bool() const;
+ void operator()();
+ void reset();
+ void wait();
+
+private:
+ std::atomic<bool> m_flag;
+
+#ifndef WIN32
+ // On UNIX-like operating systems use the self-pipe trick.
+ TokenPipeEnd m_pipe_r;
+ TokenPipeEnd m_pipe_w;
+#else
+ // On windows use a condition variable, since we don't have any signals there
+ std::mutex m_mutex;
+ std::condition_variable m_cv;
+#endif
+};
+} // namespace util
+
+#endif // BITCOIN_UTIL_SIGNALINTERRUPT_H
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index f244f38f3f..fd64cae404 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -2,12 +2,12 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <common/system.h>
#include <compat/compat.h>
#include <logging.h>
#include <tinyformat.h>
#include <util/sock.h>
#include <util/syserror.h>
-#include <util/system.h>
#include <util/threadinterrupt.h>
#include <util/time.h>
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 05e7b957c4..d792562735 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -17,8 +17,8 @@
#include <cstdint>
#include <limits>
#include <optional>
-#include <string>
-#include <string_view>
+#include <string> // IWYU pragma: export
+#include <string_view> // IWYU pragma: export
#include <system_error>
#include <type_traits>
#include <vector>
diff --git a/src/util/string.h b/src/util/string.h
index fb93d2a80e..8b69d6ccae 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -12,8 +12,8 @@
#include <cstring>
#include <locale>
#include <sstream>
-#include <string>
-#include <string_view>
+#include <string> // IWYU pragma: export
+#include <string_view> // IWYU pragma: export
#include <vector>
void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute);
diff --git a/src/util/syscall_sandbox.cpp b/src/util/syscall_sandbox.cpp
deleted file mode 100644
index b1579bdb9c..0000000000
--- a/src/util/syscall_sandbox.cpp
+++ /dev/null
@@ -1,927 +0,0 @@
-// Copyright (c) 2020-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif // defined(HAVE_CONFIG_H)
-
-#include <util/syscall_sandbox.h>
-
-#if defined(USE_SYSCALL_SANDBOX)
-#include <array>
-#include <cassert>
-#include <cstdint>
-#include <exception>
-#include <map>
-#include <new>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <logging.h>
-#include <tinyformat.h>
-#include <util/threadnames.h>
-
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-#include <linux/unistd.h>
-#include <signal.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace {
-bool g_syscall_sandbox_enabled{false};
-bool g_syscall_sandbox_log_violation_before_terminating{false};
-
-#if !defined(__x86_64__)
-#error Syscall sandbox is an experimental feature currently available only under Linux x86-64.
-#endif // defined(__x86_64__)
-
-#ifndef SECCOMP_RET_KILL_PROCESS
-#define SECCOMP_RET_KILL_PROCESS 0x80000000U
-#endif
-
-// Define system call numbers for x86_64 that are referenced in the system call profile
-// but not provided by the kernel headers used in the GUIX build.
-// Usually, they can be found via "grep name /usr/include/x86_64-linux-gnu/asm/unistd_64.h"
-
-#ifndef __NR_clone3
-#define __NR_clone3 435
-#endif
-
-#ifndef __NR_statx
-#define __NR_statx 332
-#endif
-
-#ifndef __NR_getrandom
-#define __NR_getrandom 318
-#endif
-
-#ifndef __NR_membarrier
-#define __NR_membarrier 324
-#endif
-
-#ifndef __NR_copy_file_range
-#define __NR_copy_file_range 326
-#endif
-
-#ifndef __NR_rseq
-#define __NR_rseq 334
-#endif
-
-// This list of syscalls in LINUX_SYSCALLS is only used to map syscall numbers to syscall names in
-// order to be able to print user friendly error messages which include the syscall name in addition
-// to the syscall number.
-//
-// Example output in case of a syscall violation where the syscall is present in LINUX_SYSCALLS:
-//
-// ```
-// 2021-06-09T12:34:56Z ERROR: The syscall "execve" (syscall number 59) is not allowed by the syscall sandbox in thread "msghand". Please report.
-// ```
-//
-// Example output in case of a syscall violation where the syscall is not present in LINUX_SYSCALLS:
-//
-// ```
-// 2021-06-09T12:34:56Z ERROR: The syscall "*unknown*" (syscall number 314) is not allowed by the syscall sandbox in thread "msghand". Please report.
-// ``
-//
-// LINUX_SYSCALLS contains two types of syscalls:
-// 1.) Syscalls that are present under all architectures or relevant Linux kernel versions for which
-// we support the syscall sandbox feature (currently only Linux x86-64). Examples include read,
-// write, open, close, etc.
-// 2.) Syscalls that are present under a subset of architectures or relevant Linux kernel versions
-// for which we support the syscall sandbox feature. This type of syscalls should be added to
-// LINUX_SYSCALLS conditional on availability like in the following example:
-// ...
-// #if defined(__NR_arch_dependent_syscall)
-// {__NR_arch_dependent_syscall, "arch_dependent_syscall"},
-// #endif // defined(__NR_arch_dependent_syscall)
-// ...
-const std::map<uint32_t, std::string> LINUX_SYSCALLS{
- {__NR_accept, "accept"},
- {__NR_accept4, "accept4"},
- {__NR_access, "access"},
- {__NR_acct, "acct"},
- {__NR_add_key, "add_key"},
- {__NR_adjtimex, "adjtimex"},
- {__NR_afs_syscall, "afs_syscall"},
- {__NR_alarm, "alarm"},
- {__NR_arch_prctl, "arch_prctl"},
- {__NR_bind, "bind"},
- {__NR_bpf, "bpf"},
- {__NR_brk, "brk"},
- {__NR_capget, "capget"},
- {__NR_capset, "capset"},
- {__NR_chdir, "chdir"},
- {__NR_chmod, "chmod"},
- {__NR_chown, "chown"},
- {__NR_chroot, "chroot"},
- {__NR_clock_adjtime, "clock_adjtime"},
- {__NR_clock_getres, "clock_getres"},
- {__NR_clock_gettime, "clock_gettime"},
- {__NR_clock_nanosleep, "clock_nanosleep"},
- {__NR_clock_settime, "clock_settime"},
- {__NR_clone, "clone"},
- {__NR_clone3, "clone3"},
- {__NR_close, "close"},
- {__NR_connect, "connect"},
- {__NR_copy_file_range, "copy_file_range"},
- {__NR_creat, "creat"},
- {__NR_create_module, "create_module"},
- {__NR_delete_module, "delete_module"},
- {__NR_dup, "dup"},
- {__NR_dup2, "dup2"},
- {__NR_dup3, "dup3"},
- {__NR_epoll_create, "epoll_create"},
- {__NR_epoll_create1, "epoll_create1"},
- {__NR_epoll_ctl, "epoll_ctl"},
- {__NR_epoll_ctl_old, "epoll_ctl_old"},
- {__NR_epoll_pwait, "epoll_pwait"},
- {__NR_epoll_wait, "epoll_wait"},
- {__NR_epoll_wait_old, "epoll_wait_old"},
- {__NR_eventfd, "eventfd"},
- {__NR_eventfd2, "eventfd2"},
- {__NR_execve, "execve"},
- {__NR_execveat, "execveat"},
- {__NR_exit, "exit"},
- {__NR_exit_group, "exit_group"},
- {__NR_faccessat, "faccessat"},
- {__NR_fadvise64, "fadvise64"},
- {__NR_fallocate, "fallocate"},
- {__NR_fanotify_init, "fanotify_init"},
- {__NR_fanotify_mark, "fanotify_mark"},
- {__NR_fchdir, "fchdir"},
- {__NR_fchmod, "fchmod"},
- {__NR_fchmodat, "fchmodat"},
- {__NR_fchown, "fchown"},
- {__NR_fchownat, "fchownat"},
- {__NR_fcntl, "fcntl"},
- {__NR_fdatasync, "fdatasync"},
- {__NR_fgetxattr, "fgetxattr"},
- {__NR_finit_module, "finit_module"},
- {__NR_flistxattr, "flistxattr"},
- {__NR_flock, "flock"},
- {__NR_fork, "fork"},
- {__NR_fremovexattr, "fremovexattr"},
- {__NR_fsetxattr, "fsetxattr"},
- {__NR_fstat, "fstat"},
- {__NR_fstatfs, "fstatfs"},
- {__NR_fsync, "fsync"},
- {__NR_ftruncate, "ftruncate"},
- {__NR_futex, "futex"},
- {__NR_futimesat, "futimesat"},
- {__NR_get_kernel_syms, "get_kernel_syms"},
- {__NR_get_mempolicy, "get_mempolicy"},
- {__NR_get_robust_list, "get_robust_list"},
- {__NR_get_thread_area, "get_thread_area"},
- {__NR_getcpu, "getcpu"},
- {__NR_getcwd, "getcwd"},
- {__NR_getdents, "getdents"},
- {__NR_getdents64, "getdents64"},
- {__NR_getegid, "getegid"},
- {__NR_geteuid, "geteuid"},
- {__NR_getgid, "getgid"},
- {__NR_getgroups, "getgroups"},
- {__NR_getitimer, "getitimer"},
- {__NR_getpeername, "getpeername"},
- {__NR_getpgid, "getpgid"},
- {__NR_getpgrp, "getpgrp"},
- {__NR_getpid, "getpid"},
- {__NR_getpmsg, "getpmsg"},
- {__NR_getppid, "getppid"},
- {__NR_getpriority, "getpriority"},
- {__NR_getrandom, "getrandom"},
- {__NR_getresgid, "getresgid"},
- {__NR_getresuid, "getresuid"},
- {__NR_getrlimit, "getrlimit"},
- {__NR_getrusage, "getrusage"},
- {__NR_getsid, "getsid"},
- {__NR_getsockname, "getsockname"},
- {__NR_getsockopt, "getsockopt"},
- {__NR_gettid, "gettid"},
- {__NR_gettimeofday, "gettimeofday"},
- {__NR_getuid, "getuid"},
- {__NR_getxattr, "getxattr"},
- {__NR_init_module, "init_module"},
- {__NR_inotify_add_watch, "inotify_add_watch"},
- {__NR_inotify_init, "inotify_init"},
- {__NR_inotify_init1, "inotify_init1"},
- {__NR_inotify_rm_watch, "inotify_rm_watch"},
- {__NR_io_cancel, "io_cancel"},
- {__NR_io_destroy, "io_destroy"},
- {__NR_io_getevents, "io_getevents"},
- {__NR_io_setup, "io_setup"},
- {__NR_io_submit, "io_submit"},
- {__NR_ioctl, "ioctl"},
- {__NR_ioperm, "ioperm"},
- {__NR_iopl, "iopl"},
- {__NR_ioprio_get, "ioprio_get"},
- {__NR_ioprio_set, "ioprio_set"},
- {__NR_kcmp, "kcmp"},
- {__NR_kexec_file_load, "kexec_file_load"},
- {__NR_kexec_load, "kexec_load"},
- {__NR_keyctl, "keyctl"},
- {__NR_kill, "kill"},
- {__NR_lchown, "lchown"},
- {__NR_lgetxattr, "lgetxattr"},
- {__NR_link, "link"},
- {__NR_linkat, "linkat"},
- {__NR_listen, "listen"},
- {__NR_listxattr, "listxattr"},
- {__NR_llistxattr, "llistxattr"},
- {__NR_lookup_dcookie, "lookup_dcookie"},
- {__NR_lremovexattr, "lremovexattr"},
- {__NR_lseek, "lseek"},
- {__NR_lsetxattr, "lsetxattr"},
- {__NR_lstat, "lstat"},
- {__NR_madvise, "madvise"},
- {__NR_mbind, "mbind"},
- {__NR_membarrier, "membarrier"},
- {__NR_memfd_create, "memfd_create"},
- {__NR_migrate_pages, "migrate_pages"},
- {__NR_mincore, "mincore"},
- {__NR_mkdir, "mkdir"},
- {__NR_mkdirat, "mkdirat"},
- {__NR_mknod, "mknod"},
- {__NR_mknodat, "mknodat"},
- {__NR_mlock, "mlock"},
- {__NR_mlock2, "mlock2"},
- {__NR_mlockall, "mlockall"},
- {__NR_mmap, "mmap"},
- {__NR_modify_ldt, "modify_ldt"},
- {__NR_mount, "mount"},
- {__NR_move_pages, "move_pages"},
- {__NR_mprotect, "mprotect"},
- {__NR_mq_getsetattr, "mq_getsetattr"},
- {__NR_mq_notify, "mq_notify"},
- {__NR_mq_open, "mq_open"},
- {__NR_mq_timedreceive, "mq_timedreceive"},
- {__NR_mq_timedsend, "mq_timedsend"},
- {__NR_mq_unlink, "mq_unlink"},
- {__NR_mremap, "mremap"},
- {__NR_msgctl, "msgctl"},
- {__NR_msgget, "msgget"},
- {__NR_msgrcv, "msgrcv"},
- {__NR_msgsnd, "msgsnd"},
- {__NR_msync, "msync"},
- {__NR_munlock, "munlock"},
- {__NR_munlockall, "munlockall"},
- {__NR_munmap, "munmap"},
- {__NR_name_to_handle_at, "name_to_handle_at"},
- {__NR_nanosleep, "nanosleep"},
- {__NR_newfstatat, "newfstatat"},
- {__NR_nfsservctl, "nfsservctl"},
- {__NR_open, "open"},
- {__NR_open_by_handle_at, "open_by_handle_at"},
- {__NR_openat, "openat"},
- {__NR_pause, "pause"},
- {__NR_perf_event_open, "perf_event_open"},
- {__NR_personality, "personality"},
- {__NR_pipe, "pipe"},
- {__NR_pipe2, "pipe2"},
- {__NR_pivot_root, "pivot_root"},
-#ifdef __NR_pkey_alloc
- {__NR_pkey_alloc, "pkey_alloc"},
-#endif
-#ifdef __NR_pkey_free
- {__NR_pkey_free, "pkey_free"},
-#endif
-#ifdef __NR_pkey_mprotect
- {__NR_pkey_mprotect, "pkey_mprotect"},
-#endif
- {__NR_poll, "poll"},
- {__NR_ppoll, "ppoll"},
- {__NR_prctl, "prctl"},
- {__NR_pread64, "pread64"},
- {__NR_preadv, "preadv"},
-#ifdef __NR_preadv2
- {__NR_preadv2, "preadv2"},
-#endif
- {__NR_prlimit64, "prlimit64"},
- {__NR_process_vm_readv, "process_vm_readv"},
- {__NR_process_vm_writev, "process_vm_writev"},
- {__NR_pselect6, "pselect6"},
- {__NR_ptrace, "ptrace"},
- {__NR_putpmsg, "putpmsg"},
- {__NR_pwrite64, "pwrite64"},
- {__NR_pwritev, "pwritev"},
-#ifdef __NR_pwritev2
- {__NR_pwritev2, "pwritev2"},
-#endif
- {__NR__sysctl, "_sysctl"},
- {__NR_query_module, "query_module"},
- {__NR_quotactl, "quotactl"},
- {__NR_read, "read"},
- {__NR_readahead, "readahead"},
- {__NR_readlink, "readlink"},
- {__NR_readlinkat, "readlinkat"},
- {__NR_readv, "readv"},
- {__NR_reboot, "reboot"},
- {__NR_recvfrom, "recvfrom"},
- {__NR_recvmmsg, "recvmmsg"},
- {__NR_recvmsg, "recvmsg"},
- {__NR_remap_file_pages, "remap_file_pages"},
- {__NR_removexattr, "removexattr"},
- {__NR_rename, "rename"},
- {__NR_renameat, "renameat"},
- {__NR_renameat2, "renameat2"},
- {__NR_request_key, "request_key"},
- {__NR_restart_syscall, "restart_syscall"},
- {__NR_rmdir, "rmdir"},
- {__NR_rseq, "rseq"},
- {__NR_rt_sigaction, "rt_sigaction"},
- {__NR_rt_sigpending, "rt_sigpending"},
- {__NR_rt_sigprocmask, "rt_sigprocmask"},
- {__NR_rt_sigqueueinfo, "rt_sigqueueinfo"},
- {__NR_rt_sigreturn, "rt_sigreturn"},
- {__NR_rt_sigsuspend, "rt_sigsuspend"},
- {__NR_rt_sigtimedwait, "rt_sigtimedwait"},
- {__NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo"},
- {__NR_sched_get_priority_max, "sched_get_priority_max"},
- {__NR_sched_get_priority_min, "sched_get_priority_min"},
- {__NR_sched_getaffinity, "sched_getaffinity"},
- {__NR_sched_getattr, "sched_getattr"},
- {__NR_sched_getparam, "sched_getparam"},
- {__NR_sched_getscheduler, "sched_getscheduler"},
- {__NR_sched_rr_get_interval, "sched_rr_get_interval"},
- {__NR_sched_setaffinity, "sched_setaffinity"},
- {__NR_sched_setattr, "sched_setattr"},
- {__NR_sched_setparam, "sched_setparam"},
- {__NR_sched_setscheduler, "sched_setscheduler"},
- {__NR_sched_yield, "sched_yield"},
- {__NR_seccomp, "seccomp"},
- {__NR_security, "security"},
- {__NR_select, "select"},
- {__NR_semctl, "semctl"},
- {__NR_semget, "semget"},
- {__NR_semop, "semop"},
- {__NR_semtimedop, "semtimedop"},
- {__NR_sendfile, "sendfile"},
- {__NR_sendmmsg, "sendmmsg"},
- {__NR_sendmsg, "sendmsg"},
- {__NR_sendto, "sendto"},
- {__NR_set_mempolicy, "set_mempolicy"},
- {__NR_set_robust_list, "set_robust_list"},
- {__NR_set_thread_area, "set_thread_area"},
- {__NR_set_tid_address, "set_tid_address"},
- {__NR_setdomainname, "setdomainname"},
- {__NR_setfsgid, "setfsgid"},
- {__NR_setfsuid, "setfsuid"},
- {__NR_setgid, "setgid"},
- {__NR_setgroups, "setgroups"},
- {__NR_sethostname, "sethostname"},
- {__NR_setitimer, "setitimer"},
- {__NR_setns, "setns"},
- {__NR_setpgid, "setpgid"},
- {__NR_setpriority, "setpriority"},
- {__NR_setregid, "setregid"},
- {__NR_setresgid, "setresgid"},
- {__NR_setresuid, "setresuid"},
- {__NR_setreuid, "setreuid"},
- {__NR_setrlimit, "setrlimit"},
- {__NR_setsid, "setsid"},
- {__NR_setsockopt, "setsockopt"},
- {__NR_settimeofday, "settimeofday"},
- {__NR_setuid, "setuid"},
- {__NR_setxattr, "setxattr"},
- {__NR_shmat, "shmat"},
- {__NR_shmctl, "shmctl"},
- {__NR_shmdt, "shmdt"},
- {__NR_shmget, "shmget"},
- {__NR_shutdown, "shutdown"},
- {__NR_sigaltstack, "sigaltstack"},
- {__NR_signalfd, "signalfd"},
- {__NR_signalfd4, "signalfd4"},
- {__NR_socket, "socket"},
- {__NR_socketpair, "socketpair"},
- {__NR_splice, "splice"},
- {__NR_stat, "stat"},
- {__NR_statfs, "statfs"},
- {__NR_statx, "statx"},
- {__NR_swapoff, "swapoff"},
- {__NR_swapon, "swapon"},
- {__NR_symlink, "symlink"},
- {__NR_symlinkat, "symlinkat"},
- {__NR_sync, "sync"},
- {__NR_sync_file_range, "sync_file_range"},
- {__NR_syncfs, "syncfs"},
- {__NR_sysfs, "sysfs"},
- {__NR_sysinfo, "sysinfo"},
- {__NR_syslog, "syslog"},
- {__NR_tee, "tee"},
- {__NR_tgkill, "tgkill"},
- {__NR_time, "time"},
- {__NR_timer_create, "timer_create"},
- {__NR_timer_delete, "timer_delete"},
- {__NR_timer_getoverrun, "timer_getoverrun"},
- {__NR_timer_gettime, "timer_gettime"},
- {__NR_timer_settime, "timer_settime"},
- {__NR_timerfd_create, "timerfd_create"},
- {__NR_timerfd_gettime, "timerfd_gettime"},
- {__NR_timerfd_settime, "timerfd_settime"},
- {__NR_times, "times"},
- {__NR_tkill, "tkill"},
- {__NR_truncate, "truncate"},
- {__NR_tuxcall, "tuxcall"},
- {__NR_umask, "umask"},
- {__NR_umount2, "umount2"},
- {__NR_uname, "uname"},
- {__NR_unlink, "unlink"},
- {__NR_unlinkat, "unlinkat"},
- {__NR_unshare, "unshare"},
- {__NR_uselib, "uselib"},
- {__NR_userfaultfd, "userfaultfd"},
- {__NR_ustat, "ustat"},
- {__NR_utime, "utime"},
- {__NR_utimensat, "utimensat"},
- {__NR_utimes, "utimes"},
- {__NR_vfork, "vfork"},
- {__NR_vhangup, "vhangup"},
- {__NR_vmsplice, "vmsplice"},
- {__NR_vserver, "vserver"},
- {__NR_wait4, "wait4"},
- {__NR_waitid, "waitid"},
- {__NR_write, "write"},
- {__NR_writev, "writev"},
-};
-
-std::string GetLinuxSyscallName(uint32_t syscall_number)
-{
- const auto element = LINUX_SYSCALLS.find(syscall_number);
- if (element != LINUX_SYSCALLS.end()) {
- return element->second;
- }
- return "*unknown*";
-}
-
-// See Linux kernel developer Kees Cook's seccomp guide at <https://outflux.net/teach-seccomp/> for
-// an accessible introduction to using seccomp.
-//
-// This function largely follows <https://outflux.net/teach-seccomp/step-3/syscall-reporter.c> and
-// <https://outflux.net/teach-seccomp/step-3/seccomp-bpf.h>.
-//
-// Seccomp BPF resources:
-// * Seccomp BPF documentation: <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
-// * seccomp(2) manual page: <https://www.kernel.org/doc/man-pages/online/pages/man2/seccomp.2.html>
-// * Seccomp BPF demo code samples: <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/seccomp>
-void SyscallSandboxDebugSignalHandler(int, siginfo_t* signal_info, void* void_signal_context)
-{
- // The si_code field inside the siginfo_t argument that is passed to a SA_SIGINFO signal handler
- // is a value indicating why the signal was sent.
- //
- // The following value can be placed in si_code for a SIGSYS signal:
- // * SYS_SECCOMP (since Linux 3.5): Triggered by a seccomp(2) filter rule.
- constexpr int32_t SYS_SECCOMP_SI_CODE{1};
- assert(signal_info->si_code == SYS_SECCOMP_SI_CODE);
-
- // The ucontext_t structure contains signal context information that was saved on the user-space
- // stack by the kernel.
- const ucontext_t* signal_context = static_cast<ucontext_t*>(void_signal_context);
- assert(signal_context != nullptr);
-
- std::set_new_handler(std::terminate);
- // Portability note: REG_RAX is Linux x86_64 specific.
- const uint32_t syscall_number = static_cast<uint32_t>(signal_context->uc_mcontext.gregs[REG_RAX]);
- const std::string syscall_name = GetLinuxSyscallName(syscall_number);
- const std::string thread_name = !util::ThreadGetInternalName().empty() ? util::ThreadGetInternalName() : "*unnamed*";
- const std::string error_message = strprintf("ERROR: The syscall \"%s\" (syscall number %d) is not allowed by the syscall sandbox in thread \"%s\". Please report.", syscall_name, syscall_number, thread_name);
- tfm::format(std::cerr, "%s\n", error_message);
- LogPrintf("%s\n", error_message);
- std::terminate();
-}
-
-// This function largely follows install_syscall_reporter from Kees Cook's seccomp guide:
-// <https://outflux.net/teach-seccomp/step-3/syscall-reporter.c>
-bool SetupSyscallSandboxDebugHandler()
-{
- struct sigaction action = {};
- sigset_t mask;
- sigemptyset(&mask);
- sigaddset(&mask, SIGSYS);
- action.sa_sigaction = &SyscallSandboxDebugSignalHandler;
- action.sa_flags = SA_SIGINFO;
- if (sigaction(SIGSYS, &action, nullptr) < 0) {
- return false;
- }
- if (sigprocmask(SIG_UNBLOCK, &mask, nullptr)) {
- return false;
- }
- return true;
-}
-
-enum class SyscallSandboxAction {
- KILL_PROCESS,
- INVOKE_SIGNAL_HANDLER,
-};
-
-class SeccompPolicyBuilder
-{
- std::set<uint32_t> allowed_syscalls;
-
-public:
- SeccompPolicyBuilder()
- {
- // Allowed by default.
- AllowAddressSpaceAccess();
- AllowEpoll();
- AllowEventFd();
- AllowFutex();
- AllowGeneralIo();
- AllowGetRandom();
- AllowGetSimpleId();
- AllowGetTime();
- AllowGlobalProcessEnvironment();
- AllowGlobalSystemStatus();
- AllowKernelInternalApi();
- AllowNetworkSocketInformation();
- AllowOperationOnExistingFileDescriptor();
- AllowPipe();
- AllowPrctl();
- AllowProcessStartOrDeath();
- AllowScheduling();
- AllowSignalHandling();
- AllowSleep();
- AllowUmask();
- }
-
- void AllowAddressSpaceAccess()
- {
- allowed_syscalls.insert(__NR_brk); // change data segment size
- allowed_syscalls.insert(__NR_madvise); // give advice about use of memory
- allowed_syscalls.insert(__NR_membarrier); // issue memory barriers on a set of threads
- allowed_syscalls.insert(__NR_mincore); // check if virtual memory is in RAM
- allowed_syscalls.insert(__NR_mlock); // lock memory
- allowed_syscalls.insert(__NR_mmap); // map files or devices into memory
- allowed_syscalls.insert(__NR_mprotect); // set protection on a region of memory
- allowed_syscalls.insert(__NR_mremap); // remap a file in memory
- allowed_syscalls.insert(__NR_munlock); // unlock memory
- allowed_syscalls.insert(__NR_munmap); // unmap files or devices into memory
- }
-
- void AllowEpoll()
- {
- allowed_syscalls.insert(__NR_epoll_create1); // open an epoll file descriptor
- allowed_syscalls.insert(__NR_epoll_ctl); // control interface for an epoll file descriptor
- allowed_syscalls.insert(__NR_epoll_pwait); // wait for an I/O event on an epoll file descriptor
- allowed_syscalls.insert(__NR_epoll_wait); // wait for an I/O event on an epoll file descriptor
- }
-
- void AllowEventFd()
- {
- allowed_syscalls.insert(__NR_eventfd2); // create a file descriptor for event notification
- }
-
- void AllowFileSystem()
- {
- allowed_syscalls.insert(__NR_access); // check user's permissions for a file
- allowed_syscalls.insert(__NR_chdir); // change working directory
- allowed_syscalls.insert(__NR_chmod); // change permissions of a file
- allowed_syscalls.insert(__NR_copy_file_range); // copy a range of data from one file to another
- allowed_syscalls.insert(__NR_fallocate); // manipulate file space
- allowed_syscalls.insert(__NR_fchmod); // change permissions of a file
- allowed_syscalls.insert(__NR_fchown); // change ownership of a file
- allowed_syscalls.insert(__NR_fdatasync); // synchronize a file's in-core state with storage device
- allowed_syscalls.insert(__NR_flock); // apply or remove an advisory lock on an open file
- allowed_syscalls.insert(__NR_fstat); // get file status
- allowed_syscalls.insert(__NR_fstatfs); // get file system status
- allowed_syscalls.insert(__NR_fsync); // synchronize a file's in-core state with storage device
- allowed_syscalls.insert(__NR_ftruncate); // truncate a file to a specified length
- allowed_syscalls.insert(__NR_getcwd); // get current working directory
- allowed_syscalls.insert(__NR_getdents); // get directory entries
- allowed_syscalls.insert(__NR_getdents64); // get directory entries
- allowed_syscalls.insert(__NR_lstat); // get file status
- allowed_syscalls.insert(__NR_mkdir); // create a directory
- allowed_syscalls.insert(__NR_newfstatat); // get file status
- allowed_syscalls.insert(__NR_open); // open and possibly create a file
- allowed_syscalls.insert(__NR_openat); // open and possibly create a file
- allowed_syscalls.insert(__NR_readlink); // read value of a symbolic link
- allowed_syscalls.insert(__NR_rename); // change the name or location of a file
- allowed_syscalls.insert(__NR_rmdir); // delete a directory
- allowed_syscalls.insert(__NR_sendfile); // transfer data between file descriptors
- allowed_syscalls.insert(__NR_stat); // get file status
- allowed_syscalls.insert(__NR_statfs); // get filesystem statistics
- allowed_syscalls.insert(__NR_statx); // get file status (extended)
- allowed_syscalls.insert(__NR_unlink); // delete a name and possibly the file it refers to
- allowed_syscalls.insert(__NR_unlinkat); // delete relative to a directory file descriptor
- }
-
- void AllowFutex()
- {
- allowed_syscalls.insert(__NR_futex); // fast user-space locking
- allowed_syscalls.insert(__NR_set_robust_list); // set list of robust futexes
- }
-
- void AllowGeneralIo()
- {
- allowed_syscalls.insert(__NR_ioctl); // control device
- allowed_syscalls.insert(__NR_lseek); // reposition read/write file offset
- allowed_syscalls.insert(__NR_poll); // wait for some event on a file descriptor
- allowed_syscalls.insert(__NR_ppoll); // wait for some event on a file descriptor
- allowed_syscalls.insert(__NR_pread64); // read from a file descriptor at a given offset
- allowed_syscalls.insert(__NR_pwrite64); // write to a file descriptor at a given offset
- allowed_syscalls.insert(__NR_read); // read from a file descriptor
- allowed_syscalls.insert(__NR_readv); // read data into multiple buffers
- allowed_syscalls.insert(__NR_recvfrom); // receive a message from a socket
- allowed_syscalls.insert(__NR_recvmsg); // receive a message from a socket
- allowed_syscalls.insert(__NR_select); // synchronous I/O multiplexing
- allowed_syscalls.insert(__NR_sendmmsg); // send multiple messages on a socket
- allowed_syscalls.insert(__NR_sendmsg); // send a message on a socket
- allowed_syscalls.insert(__NR_sendto); // send a message on a socket
- allowed_syscalls.insert(__NR_write); // write to a file descriptor
- allowed_syscalls.insert(__NR_writev); // write data into multiple buffers
- }
-
- void AllowGetRandom()
- {
- allowed_syscalls.insert(__NR_getrandom); // obtain a series of random bytes
- }
-
- void AllowGetSimpleId()
- {
- allowed_syscalls.insert(__NR_getegid); // get group identity
- allowed_syscalls.insert(__NR_geteuid); // get user identity
- allowed_syscalls.insert(__NR_getgid); // get group identity
- allowed_syscalls.insert(__NR_getpgid); // get process group
- allowed_syscalls.insert(__NR_getpid); // get process identification
- allowed_syscalls.insert(__NR_getppid); // get process identification
- allowed_syscalls.insert(__NR_getresgid); // get real, effective and saved group IDs
- allowed_syscalls.insert(__NR_getresuid); // get real, effective and saved user IDs
- allowed_syscalls.insert(__NR_getsid); // get session ID
- allowed_syscalls.insert(__NR_gettid); // get thread identification
- allowed_syscalls.insert(__NR_getuid); // get user identity
- }
-
- void AllowGetTime()
- {
- allowed_syscalls.insert(__NR_clock_getres); // find the resolution (precision) of the specified clock
- allowed_syscalls.insert(__NR_clock_gettime); // retrieve the time of the specified clock
- allowed_syscalls.insert(__NR_gettimeofday); // get timeval
- }
-
- void AllowGlobalProcessEnvironment()
- {
- allowed_syscalls.insert(__NR_getrlimit); // get resource limits
- allowed_syscalls.insert(__NR_getrusage); // get resource usage
- allowed_syscalls.insert(__NR_prlimit64); // get/set resource limits
- }
-
- void AllowGlobalSystemStatus()
- {
- allowed_syscalls.insert(__NR_sysinfo); // return system information
- allowed_syscalls.insert(__NR_uname); // get name and information about current kernel
- }
-
- void AllowKernelInternalApi()
- {
- allowed_syscalls.insert(__NR_restart_syscall); // restart a system call after interruption by a stop signal
- }
-
- void AllowNetwork()
- {
- allowed_syscalls.insert(__NR_accept); // accept a connection on a socket
- allowed_syscalls.insert(__NR_accept4); // accept a connection on a socket
- allowed_syscalls.insert(__NR_bind); // bind a name to a socket
- allowed_syscalls.insert(__NR_connect); // initiate a connection on a socket
- allowed_syscalls.insert(__NR_listen); // listen for connections on a socket
- allowed_syscalls.insert(__NR_setsockopt); // set options on sockets
- allowed_syscalls.insert(__NR_socket); // create an endpoint for communication
- allowed_syscalls.insert(__NR_socketpair); // create a pair of connected sockets
- }
-
- void AllowNetworkSocketInformation()
- {
- allowed_syscalls.insert(__NR_getpeername); // get name of connected peer socket
- allowed_syscalls.insert(__NR_getsockname); // get socket name
- allowed_syscalls.insert(__NR_getsockopt); // get options on sockets
- }
-
- void AllowOperationOnExistingFileDescriptor()
- {
- allowed_syscalls.insert(__NR_close); // close a file descriptor
- allowed_syscalls.insert(__NR_dup); // duplicate a file descriptor
- allowed_syscalls.insert(__NR_dup2); // duplicate a file descriptor
- allowed_syscalls.insert(__NR_fcntl); // manipulate file descriptor
- allowed_syscalls.insert(__NR_shutdown); // shut down part of a full-duplex connection
- }
-
- void AllowPipe()
- {
- allowed_syscalls.insert(__NR_pipe); // create pipe
- allowed_syscalls.insert(__NR_pipe2); // create pipe
- }
-
- void AllowPrctl()
- {
- allowed_syscalls.insert(__NR_arch_prctl); // set architecture-specific thread state
- allowed_syscalls.insert(__NR_prctl); // operations on a process
- }
-
- void AllowProcessStartOrDeath()
- {
- allowed_syscalls.insert(__NR_clone); // create a child process
- allowed_syscalls.insert(__NR_clone3); // create a child process
- allowed_syscalls.insert(__NR_exit); // terminate the calling process
- allowed_syscalls.insert(__NR_exit_group); // exit all threads in a process
- allowed_syscalls.insert(__NR_fork); // create a child process
- allowed_syscalls.insert(__NR_tgkill); // send a signal to a thread
- allowed_syscalls.insert(__NR_wait4); // wait for process to change state, BSD style
- allowed_syscalls.insert(__NR_rseq); // register restartable sequence for thread
- }
-
- void AllowScheduling()
- {
- allowed_syscalls.insert(__NR_sched_getaffinity); // set a thread's CPU affinity mask
- allowed_syscalls.insert(__NR_sched_getparam); // get scheduling parameters
- allowed_syscalls.insert(__NR_sched_getscheduler); // get scheduling policy/parameters
- allowed_syscalls.insert(__NR_sched_setscheduler); // set scheduling policy/parameters
- allowed_syscalls.insert(__NR_sched_yield); // yield the processor
- }
-
- void AllowSignalHandling()
- {
- allowed_syscalls.insert(__NR_rt_sigaction); // examine and change a signal action
- allowed_syscalls.insert(__NR_rt_sigprocmask); // examine and change blocked signals
- allowed_syscalls.insert(__NR_rt_sigreturn); // return from signal handler and cleanup stack frame
- allowed_syscalls.insert(__NR_sigaltstack); // set and/or get signal stack context
- }
-
- void AllowSleep()
- {
- allowed_syscalls.insert(__NR_clock_nanosleep); // high-resolution sleep with specifiable clock
- allowed_syscalls.insert(__NR_nanosleep); // high-resolution sleep
- }
-
- void AllowUmask()
- {
- allowed_syscalls.insert(__NR_umask); // set file mode creation mask
- }
-
- // See Linux kernel developer Kees Cook's seccomp guide at <https://outflux.net/teach-seccomp/>
- // for an accessible introduction to using seccomp.
- //
- // This function largely follows <https://outflux.net/teach-seccomp/step-3/seccomp-bpf.h>.
- std::vector<sock_filter> BuildFilter(SyscallSandboxAction default_action)
- {
- std::vector<sock_filter> bpf_policy;
- // See VALIDATE_ARCHITECTURE in seccomp-bpf.h referenced above.
- bpf_policy.push_back(BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, arch)));
- // Portability note: AUDIT_ARCH_X86_64 is Linux x86_64 specific.
- bpf_policy.push_back(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, AUDIT_ARCH_X86_64, 1, 0));
- bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS));
- // See EXAMINE_SYSCALL in seccomp-bpf.h referenced above.
- bpf_policy.push_back(BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr)));
- for (const uint32_t allowed_syscall : allowed_syscalls) {
- // See ALLOW_SYSCALL in seccomp-bpf.h referenced above.
- bpf_policy.push_back(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, allowed_syscall, 0, 1));
- bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW));
- }
- switch (default_action) {
- case SyscallSandboxAction::KILL_PROCESS:
- // Disallow syscall and kill the process.
- //
- // See KILL_PROCESS in seccomp-bpf.h referenced above.
- //
- // Note that we're using SECCOMP_RET_KILL_PROCESS (kill the process) instead
- // of SECCOMP_RET_KILL_THREAD (kill the thread). The SECCOMP_RET_KILL_PROCESS
- // action was introduced in Linux 4.14.
- //
- // SECCOMP_RET_KILL_PROCESS: Results in the entire process exiting immediately without
- // executing the system call.
- //
- // SECCOMP_RET_KILL_PROCESS documentation:
- // <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
- bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_KILL_PROCESS));
- break;
- case SyscallSandboxAction::INVOKE_SIGNAL_HANDLER:
- // Disallow syscall and force a SIGSYS to trigger syscall debug reporter.
- //
- // SECCOMP_RET_TRAP: Results in the kernel sending a SIGSYS signal to the triggering
- // task without executing the system call.
- //
- // SECCOMP_RET_TRAP documentation:
- // <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
- bpf_policy.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP));
- break;
- }
- return bpf_policy;
- }
-};
-} // namespace
-
-bool SetupSyscallSandbox(bool log_syscall_violation_before_terminating)
-{
- assert(!g_syscall_sandbox_enabled && "SetupSyscallSandbox(...) should only be called once.");
- g_syscall_sandbox_enabled = true;
- g_syscall_sandbox_log_violation_before_terminating = log_syscall_violation_before_terminating;
- if (log_syscall_violation_before_terminating) {
- if (!SetupSyscallSandboxDebugHandler()) {
- return false;
- }
- }
- return true;
-}
-
-void TestDisallowedSandboxCall()
-{
- // The getgroups syscall is assumed NOT to be allowed by the syscall sandbox policy.
- std::array<gid_t, 1> groups;
- [[maybe_unused]] int32_t ignored = getgroups(groups.size(), groups.data());
-}
-#endif // defined(USE_SYSCALL_SANDBOX)
-
-void SetSyscallSandboxPolicy(SyscallSandboxPolicy syscall_policy)
-{
-#if defined(USE_SYSCALL_SANDBOX)
- if (!g_syscall_sandbox_enabled) {
- return;
- }
- SeccompPolicyBuilder seccomp_policy_builder;
- switch (syscall_policy) {
- case SyscallSandboxPolicy::INITIALIZATION: // Thread: main thread (state: init)
- // SyscallSandboxPolicy::INITIALIZATION is the first policy loaded.
- //
- // Subsequently loaded policies can reduce the abilities further, but
- // abilities can never be regained.
- //
- // SyscallSandboxPolicy::INITIALIZATION must thus be a superset of all
- // other policies.
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::INITIALIZATION_DNS_SEED: // Thread: dnsseed
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::INITIALIZATION_LOAD_BLOCKS: // Thread: loadblk
- seccomp_policy_builder.AllowFileSystem();
- break;
- case SyscallSandboxPolicy::INITIALIZATION_MAP_PORT: // Thread: mapport
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::MESSAGE_HANDLER: // Thread: msghand
- seccomp_policy_builder.AllowFileSystem();
- break;
- case SyscallSandboxPolicy::NET: // Thread: net
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::NET_ADD_CONNECTION: // Thread: addcon
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::NET_HTTP_SERVER: // Thread: http
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::NET_HTTP_SERVER_WORKER: // Thread: httpworker.<N>
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::NET_OPEN_CONNECTION: // Thread: opencon
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::SCHEDULER: // Thread: scheduler
- seccomp_policy_builder.AllowFileSystem();
- break;
- case SyscallSandboxPolicy::TOR_CONTROL: // Thread: torcontrol
- seccomp_policy_builder.AllowFileSystem();
- seccomp_policy_builder.AllowNetwork();
- break;
- case SyscallSandboxPolicy::TX_INDEX: // Thread: txindex
- seccomp_policy_builder.AllowFileSystem();
- break;
- case SyscallSandboxPolicy::VALIDATION_SCRIPT_CHECK: // Thread: scriptch.<N>
- break;
- case SyscallSandboxPolicy::SHUTOFF: // Thread: main thread (state: shutoff)
- seccomp_policy_builder.AllowFileSystem();
- break;
- }
-
- const SyscallSandboxAction default_action = g_syscall_sandbox_log_violation_before_terminating ? SyscallSandboxAction::INVOKE_SIGNAL_HANDLER : SyscallSandboxAction::KILL_PROCESS;
- std::vector<sock_filter> filter = seccomp_policy_builder.BuildFilter(default_action);
- const sock_fprog prog = {
- .len = static_cast<uint16_t>(filter.size()),
- .filter = filter.data(),
- };
- // Do not allow abilities to be regained after being dropped.
- //
- // PR_SET_NO_NEW_PRIVS documentation: <https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html>
- if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) {
- throw std::runtime_error("Syscall sandbox enforcement failed: prctl(PR_SET_NO_NEW_PRIVS)");
- }
- // Install seccomp-bpf syscall filter.
- //
- // PR_SET_SECCOMP documentation: <https://www.kernel.org/doc/html/latest/userspace-api/seccomp_filter.html>
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0) {
- throw std::runtime_error("Syscall sandbox enforcement failed: prctl(PR_SET_SECCOMP)");
- }
-
- const std::string thread_name = !util::ThreadGetInternalName().empty() ? util::ThreadGetInternalName() : "*unnamed*";
- LogPrint(BCLog::UTIL, "Syscall filter installed for thread \"%s\"\n", thread_name);
-#endif // defined(USE_SYSCALL_SANDBOX)
-}
diff --git a/src/util/syscall_sandbox.h b/src/util/syscall_sandbox.h
deleted file mode 100644
index 3e56ebe937..0000000000
--- a/src/util/syscall_sandbox.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2020-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_UTIL_SYSCALL_SANDBOX_H
-#define BITCOIN_UTIL_SYSCALL_SANDBOX_H
-
-enum class SyscallSandboxPolicy {
- // 1. Initialization
- INITIALIZATION,
- INITIALIZATION_DNS_SEED,
- INITIALIZATION_LOAD_BLOCKS,
- INITIALIZATION_MAP_PORT,
-
- // 2. Steady state (non-initialization, non-shutdown)
- MESSAGE_HANDLER,
- NET,
- NET_ADD_CONNECTION,
- NET_HTTP_SERVER,
- NET_HTTP_SERVER_WORKER,
- NET_OPEN_CONNECTION,
- SCHEDULER,
- TOR_CONTROL,
- TX_INDEX,
- VALIDATION_SCRIPT_CHECK,
-
- // 3. Shutdown
- SHUTOFF,
-};
-
-//! Force the current thread (and threads created from the current thread) into a restricted-service
-//! operating mode where only a subset of all syscalls are available.
-//!
-//! Subsequent calls to this function can reduce the abilities further, but abilities can never be
-//! regained.
-//!
-//! This function is a no-op unless SetupSyscallSandbox(...) has been called.
-//!
-//! SetupSyscallSandbox(...) is called during bitcoind initialization if Bitcoin Core was compiled
-//! with seccomp-bpf support (--with-seccomp) *and* the parameter -sandbox=<mode> was passed to
-//! bitcoind.
-//!
-//! This experimental feature is available under Linux x86_64 only.
-void SetSyscallSandboxPolicy(SyscallSandboxPolicy syscall_policy);
-
-#if defined(USE_SYSCALL_SANDBOX)
-//! Setup and enable the experimental syscall sandbox for the running process.
-[[nodiscard]] bool SetupSyscallSandbox(bool log_syscall_violation_before_terminating);
-
-//! Invoke a disallowed syscall. Use for testing purposes.
-void TestDisallowedSandboxCall();
-#endif // defined(USE_SYSCALL_SANDBOX)
-
-#endif // BITCOIN_UTIL_SYSCALL_SANDBOX_H
diff --git a/src/util/system.cpp b/src/util/system.cpp
deleted file mode 100644
index 598e6adb88..0000000000
--- a/src/util/system.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include <util/system.h>
-
-#include <logging.h>
-#include <util/string.h>
-#include <util/syserror.h>
-#include <util/time.h>
-
-#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
-#include <pthread.h>
-#include <pthread_np.h>
-#endif
-
-#ifndef WIN32
-#include <sched.h>
-#include <sys/stat.h>
-#else
-#include <codecvt>
-#endif
-
-#ifdef HAVE_MALLOPT_ARENA_MAX
-#include <malloc.h>
-#endif
-
-#include <cstdlib>
-#include <locale>
-#include <stdexcept>
-#include <string>
-#include <thread>
-
-// Application startup time (used for uptime calculation)
-const int64_t nStartupTime = GetTime();
-
-#ifndef WIN32
-std::string ShellEscape(const std::string& arg)
-{
- std::string escaped = arg;
- ReplaceAll(escaped, "'", "'\"'\"'");
- return "'" + escaped + "'";
-}
-#endif
-
-#if HAVE_SYSTEM
-void runCommand(const std::string& strCommand)
-{
- if (strCommand.empty()) return;
-#ifndef WIN32
- int nErr = ::system(strCommand.c_str());
-#else
- int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str());
-#endif
- if (nErr)
- LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
-}
-#endif
-
-void SetupEnvironment()
-{
-#ifdef HAVE_MALLOPT_ARENA_MAX
- // glibc-specific: On 32-bit systems set the number of arenas to 1.
- // By default, since glibc 2.10, the C library will create up to two heap
- // arenas per core. This is known to cause excessive virtual address space
- // usage in our usage. Work around it by setting the maximum number of
- // arenas to 1.
- if (sizeof(void*) == 4) {
- mallopt(M_ARENA_MAX, 1);
- }
-#endif
- // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale
- // may be invalid, in which case the "C.UTF-8" locale is used as fallback.
-#if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
- try {
- std::locale(""); // Raises a runtime error if current locale is invalid
- } catch (const std::runtime_error&) {
- setenv("LC_ALL", "C.UTF-8", 1);
- }
-#elif defined(WIN32)
- // Set the default input/output charset is utf-8
- SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
-#endif
-
-#ifndef WIN32
- constexpr mode_t private_umask = 0077;
- umask(private_umask);
-#endif
-}
-
-bool SetupNetworking()
-{
-#ifdef WIN32
- // Initialize Windows Sockets
- WSADATA wsadata;
- int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
- if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
- return false;
-#endif
- return true;
-}
-
-int GetNumCores()
-{
- return std::thread::hardware_concurrency();
-}
-
-// Obtain the application startup time (used for uptime calculation)
-int64_t GetStartupTime()
-{
- return nStartupTime;
-}
-
-void ScheduleBatchPriority()
-{
-#ifdef SCHED_BATCH
- const static sched_param param{};
- const int rc = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
- if (rc != 0) {
- LogPrintf("Failed to pthread_setschedparam: %s\n", SysErrorString(rc));
- }
-#endif
-}
diff --git a/src/util/system.h b/src/util/system.h
deleted file mode 100644
index e2fc3450f6..0000000000
--- a/src/util/system.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_UTIL_SYSTEM_H
-#define BITCOIN_UTIL_SYSTEM_H
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <compat/assumptions.h>
-#include <compat/compat.h>
-
-#include <any>
-#include <set>
-#include <stdint.h>
-#include <string>
-
-// Application startup time (used for uptime calculation)
-int64_t GetStartupTime();
-
-void SetupEnvironment();
-bool SetupNetworking();
-#ifndef WIN32
-std::string ShellEscape(const std::string& arg);
-#endif
-#if HAVE_SYSTEM
-void runCommand(const std::string& strCommand);
-#endif
-
-/**
- * Return the number of cores available on the current system.
- * @note This does count virtual cores, such as those provided by HyperThreading.
- */
-int GetNumCores();
-
-/**
- * On platforms that support it, tell the kernel the calling thread is
- * CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
- *
- */
-void ScheduleBatchPriority();
-
-namespace util {
-
-//! Simplification of std insertion
-template <typename Tdst, typename Tsrc>
-inline void insert(Tdst& dst, const Tsrc& src) {
- dst.insert(dst.begin(), src.begin(), src.end());
-}
-template <typename TsetT, typename Tsrc>
-inline void insert(std::set<TsetT>& dst, const Tsrc& src) {
- dst.insert(src.begin(), src.end());
-}
-
-/**
- * Helper function to access the contained object of a std::any instance.
- * Returns a pointer to the object if passed instance has a value and the type
- * matches, nullptr otherwise.
- */
-template<typename T>
-T* AnyPtr(const std::any& any) noexcept
-{
- T* const* ptr = std::any_cast<T*>(&any);
- return ptr ? *ptr : nullptr;
-}
-
-} // namespace util
-
-#endif // BITCOIN_UTIL_SYSTEM_H
diff --git a/src/util/threadinterrupt.h b/src/util/threadinterrupt.h
index ccc053f576..0b79b38276 100644
--- a/src/util/threadinterrupt.h
+++ b/src/util/threadinterrupt.h
@@ -12,11 +12,17 @@
#include <chrono>
#include <condition_variable>
-/*
- A helper class for interruptible sleeps. Calling operator() will interrupt
- any current sleep, and after that point operator bool() will return true
- until reset.
-*/
+/**
+ * A helper class for interruptible sleeps. Calling operator() will interrupt
+ * any current sleep, and after that point operator bool() will return true
+ * until reset.
+ *
+ * This class should not be used in a signal handler. It uses thread
+ * synchronization primitives that are not safe to use with signals. If sending
+ * an interrupt from a signal handler is necessary, the \ref SignalInterrupt
+ * class can be used instead.
+ */
+
class CThreadInterrupt
{
public:
diff --git a/src/util/time.cpp b/src/util/time.cpp
index fb9bc34931..5ca9d21f8d 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -78,14 +78,6 @@ NodeClock::time_point NodeClock::now() noexcept
return time_point{ret};
};
-template <typename T>
-static T GetSystemTime()
-{
- const auto now = std::chrono::duration_cast<T>(std::chrono::system_clock::now().time_since_epoch());
- assert(now.count() > 0);
- return now;
-}
-
void SetMockTime(int64_t nMockTimeIn)
{
Assert(nMockTimeIn >= 0);
@@ -102,11 +94,6 @@ std::chrono::seconds GetMockTime()
return std::chrono::seconds(nMockTime.load(std::memory_order_relaxed));
}
-int64_t GetTimeMillis()
-{
- return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
-}
-
int64_t GetTime() { return GetTime<std::chrono::seconds>().count(); }
std::string FormatISO8601DateTime(int64_t nTime) {
diff --git a/src/util/time.h b/src/util/time.h
index 8c6baeb12a..b6aab615ba 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -71,9 +71,6 @@ using MillisecondsDouble = std::chrono::duration<double, std::chrono::millisecon
*/
int64_t GetTime();
-/** Returns the system time (not mockable) */
-int64_t GetTimeMillis();
-
/**
* DEPRECATED
* Use SetMockTime with chrono type
diff --git a/src/util/translation.h b/src/util/translation.h
index d2b49d00b0..d33fd2d0a0 100644
--- a/src/util/translation.h
+++ b/src/util/translation.h
@@ -49,22 +49,18 @@ inline bilingual_str Untranslated(std::string original) { return {original, orig
// Provide an overload of tinyformat::format which can take bilingual_str arguments.
namespace tinyformat {
-inline std::string TranslateArg(const bilingual_str& arg, bool translated)
-{
- return translated ? arg.translated : arg.original;
-}
-
-template <typename T>
-inline T const& TranslateArg(const T& arg, bool translated)
-{
- return arg;
-}
-
template <typename... Args>
bilingual_str format(const bilingual_str& fmt, const Args&... args)
{
- return bilingual_str{format(fmt.original, TranslateArg(args, false)...),
- format(fmt.translated, TranslateArg(args, true)...)};
+ const auto translate_arg{[](const auto& arg, bool translated) -> const auto& {
+ if constexpr (std::is_same_v<decltype(arg), const bilingual_str&>) {
+ return translated ? arg.translated : arg.original;
+ } else {
+ return arg;
+ }
+ }};
+ return bilingual_str{tfm::format(fmt.original, translate_arg(args, false)...),
+ tfm::format(fmt.translated, translate_arg(args, true)...)};
}
} // namespace tinyformat