diff options
author | Tor Brede Vekterli <vekterli@yahooinc.com> | 2023-01-11 13:17:17 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahooinc.com> | 2023-01-11 13:17:17 +0000 |
commit | 68d1631e982c05e2bf0dd7dcbc1de8d87f5da3d4 (patch) | |
tree | 05dbf471befa6a5ac1c63c53c35e27a72a1100ff /vespalib | |
parent | de82bfc3fe492c406a69799f11530fe3b9b97d57 (diff) |
Reduce number of `#ifdef`s
Diffstat (limited to 'vespalib')
-rw-r--r-- | vespalib/src/vespa/vespalib/util/memory_trap.cpp | 132 |
1 files changed, 65 insertions, 67 deletions
diff --git a/vespalib/src/vespa/vespalib/util/memory_trap.cpp b/vespalib/src/vespa/vespalib/util/memory_trap.cpp index 113af0de35a..f17a0221246 100644 --- a/vespalib/src/vespa/vespalib/util/memory_trap.cpp +++ b/vespalib/src/vespa/vespalib/util/memory_trap.cpp @@ -1,9 +1,5 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -#ifdef __linux__ -# define VESPA_HAS_MPROTECT -#endif - #include "memory_trap.h" #include <string_view> #include <cassert> @@ -12,7 +8,8 @@ #include <cstdlib> #include <cstring> #include <malloc.h> -#ifdef VESPA_HAS_MPROTECT +#ifdef __linux__ +# define VESPA_HAS_MPROTECT # include <unistd.h> # include <sys/mman.h> #endif @@ -26,36 +23,6 @@ namespace vespalib { namespace { -#ifdef VESPA_HAS_MPROTECT - -bool has_4k_pages() noexcept { - return (sysconf(_SC_PAGESIZE) == 4096); -} - -constexpr bool is_4k_aligned(size_t v) noexcept { - return (v % 4096) == 0; -} - -constexpr size_t align_up_4k(size_t v) noexcept { - return (v + 4095) & ~4095ULL; -} - -constexpr size_t align_down_4k(size_t v) noexcept { - return v & ~4095ULL; -} - -bool env_var_is_yes(const char* env_var) noexcept { - const char* ev = getenv(env_var); - return ((ev != nullptr) && ("yes"sv == ev)); -} - -bool mprotect_trapping_is_enabled() noexcept { - static const bool enabled = (has_4k_pages() && env_var_is_yes("VESPA_USE_MPROTECT_TRAP")); - return enabled; -} - -#endif - // Have some symbols that provide immediate context in a crash backtrace [[noreturn]] void abort_due_to_guard_bits_tampered_with() __attribute__((noinline)); [[noreturn]] void abort_due_to_guard_bits_tampered_with() { @@ -85,8 +52,62 @@ MemoryRangeTrapper::~MemoryRangeTrapper() { check_and_release(); } -void MemoryRangeTrapper::rw_protect_buffer_if_possible() { +void MemoryRangeTrapper::check_and_release() noexcept { + unprotect_buffer_to_read_only(); // Make sure sanity check can't race with writes + verify_buffer_is_all_zeros(); + unprotect_buffer_to_read_and_write(); + _trap_len = _buf_len = 0; +} + +void MemoryRangeTrapper::verify_buffer_is_all_zeros() { + for (size_t i = 0; i < _buf_len; ++i) { + if (_trap_buf[i] != 0) { + const bool in_protected_area = ((i >= _trap_offset) && (i < _trap_offset + _trap_len)); + LOG(error, "Memory corruption detected! Offset %zu into buffer %p: 0x%.2x != 0x00%s", + i, _trap_buf, static_cast<unsigned int>(_trap_buf[i]), + in_protected_area ? ". CORRUPTION IN R/W PROTECTED MEMORY!" : ""); + if (in_protected_area) { + abort_due_to_PROTECTED_guard_bits_tampered_with(); + } else { + abort_due_to_guard_bits_tampered_with(); + } + } + } +} + #ifdef VESPA_HAS_MPROTECT + +namespace { + +bool has_4k_pages() noexcept { + return (sysconf(_SC_PAGESIZE) == 4096); +} + +constexpr bool is_4k_aligned(size_t v) noexcept { + return (v % 4096) == 0; +} + +constexpr size_t align_up_4k(size_t v) noexcept { + return (v + 4095) & ~4095ULL; +} + +constexpr size_t align_down_4k(size_t v) noexcept { + return v & ~4095ULL; +} + +bool env_var_is_yes(const char *env_var) noexcept { + const char *ev = getenv(env_var); + return ((ev != nullptr) && ("yes"sv == ev)); +} + +bool mprotect_trapping_is_enabled() noexcept { + static const bool enabled = (has_4k_pages() && env_var_is_yes("VESPA_USE_MPROTECT_TRAP")); + return enabled; +} + +} // anon ns + +void MemoryRangeTrapper::rw_protect_buffer_if_possible() { static_assert(std::is_same_v<size_t, uintptr_t>); const auto aligned_start = align_up_4k(reinterpret_cast<uintptr_t>(_trap_buf)); const auto aligned_end = align_down_4k(reinterpret_cast<uintptr_t>(_trap_buf + _buf_len)); @@ -105,57 +126,34 @@ void MemoryRangeTrapper::rw_protect_buffer_if_possible() { _trap_offset = _trap_len = 0; } } -#endif } bool MemoryRangeTrapper::hw_trapping_enabled() noexcept { -#ifdef VESPA_HAS_MPROTECT return mprotect_trapping_is_enabled(); -#else - return false; -#endif -} - -void MemoryRangeTrapper::check_and_release() noexcept { - unprotect_buffer_to_read_only(); // Make sure sanity check can't race with writes - verify_buffer_is_all_zeros(); - unprotect_buffer_to_read_and_write(); - _trap_len = _buf_len = 0; } void MemoryRangeTrapper::unprotect_buffer_to_read_only() { -#ifdef VESPA_HAS_MPROTECT if (_trap_len > 0) { int ret = mprotect(_trap_buf + _trap_offset, _trap_len, PROT_READ); assert(ret == 0 && "failed to un-protect memory region to PROT_READ"); } -#endif } void MemoryRangeTrapper::unprotect_buffer_to_read_and_write() { -#ifdef VESPA_HAS_MPROTECT if (_trap_len > 0) { int ret = mprotect(_trap_buf + _trap_offset, _trap_len, PROT_READ | PROT_WRITE); assert(ret == 0 && "failed to un-protect memory region to PROT_READ | PROT_WRITE"); } -#endif } -void MemoryRangeTrapper::verify_buffer_is_all_zeros() { - for (size_t i = 0; i < _buf_len; ++i) { - if (_trap_buf[i] != 0) { - const bool in_protected_area = ((i >= _trap_offset) && (i < _trap_offset + _trap_len)); - LOG(error, "Memory corruption detected! Offset %zu into buffer %p: 0x%.2x != 0x00%s", - i, _trap_buf, static_cast<unsigned int>(_trap_buf[i]), - in_protected_area ? ". CORRUPTION IN R/W PROTECTED MEMORY!" : ""); - if (in_protected_area) { - abort_due_to_PROTECTED_guard_bits_tampered_with(); - } else { - abort_due_to_guard_bits_tampered_with(); - } - } - } -} +#else // VESPA_HAS_MPROTECT not defined, fall back to no-ops + +void MemoryRangeTrapper::rw_protect_buffer_if_possible() { /* no-op */ } +bool MemoryRangeTrapper::hw_trapping_enabled() noexcept { return false; } +void MemoryRangeTrapper::unprotect_buffer_to_read_only() { /* no-op */ } +void MemoryRangeTrapper::unprotect_buffer_to_read_and_write() { /* no-op */ } + +#endif HeapMemoryTrap::HeapMemoryTrap(size_t trap_4k_pages) : _trap_buf(static_cast<char*>(memalign(4096, trap_4k_pages * 4096))), |