Use hardware-seeded, high quality rng for priority

This fixes a potential denial of service attack
This commit is contained in:
2024-05-14 09:49:19 -07:00
parent 59878cfe6c
commit 9834b2e811
6 changed files with 124 additions and 6831 deletions

View File

@@ -60,11 +60,10 @@ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
add_subdirectory(third_party)
add_executable(versioned_map_main VersionedMap.cpp RootSet.cpp
$<TARGET_OBJECTS:xxhash>)
add_executable(versioned_map_main VersionedMap.cpp RootSet.cpp)
target_include_directories(versioned_map_main
PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(versioned_map_main PRIVATE nanobench xxhash)
target_link_libraries(versioned_map_main PRIVATE nanobench)
target_compile_definitions(versioned_map_main PRIVATE ENABLE_MAIN)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(versioned_map_main
@@ -77,13 +76,12 @@ add_library(${PROJECT_NAME}-object OBJECT VersionedMap.cpp RootSet.cpp)
target_compile_options(${PROJECT_NAME}-object PRIVATE -fno-exceptions -fno-rtti)
target_include_directories(${PROJECT_NAME}-object
PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(${PROJECT_NAME}-object PRIVATE xxhash)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
COMMAND ld -r $<TARGET_OBJECTS:${PROJECT_NAME}-object>
$<TARGET_OBJECTS:xxhash> -o ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
DEPENDS $<TARGET_OBJECTS:${PROJECT_NAME}-object> $<TARGET_OBJECTS:xxhash>
COMMAND ld -r $<TARGET_OBJECTS:${PROJECT_NAME}-object> -o
${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
DEPENDS $<TARGET_OBJECTS:${PROJECT_NAME}-object>
COMMAND_EXPAND_LISTS)
add_library(${PROJECT_NAME} SHARED ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o)

View File

@@ -12,7 +12,6 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <xxhash.h>
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::MutationType>);
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::Key>);
@@ -64,6 +63,117 @@ void munmapSafe(void *ptr, size_t size) {
}
}
struct Random {
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
//
// Modified - mostly c -> c++
Random() = default;
Random(uint64_t initState, uint64_t initSeq) {
pcg32_srandom_r(initState, initSeq);
next();
}
/// Draws from a uniform distribution of uint32_t's
uint32_t next() {
auto result = next_;
next_ = pcg32_random_r();
return result;
}
/// Draws from a uniform distribution of [0, s). From
/// https://arxiv.org/pdf/1805.10941.pdf
uint32_t bounded(uint32_t s) {
assert(s != 0);
uint32_t x = next();
auto m = uint64_t(x) * uint64_t(s);
auto l = uint32_t(m);
if (l < s) {
uint32_t t = -s % s;
while (l < t) {
x = next();
m = uint64_t(x) * uint64_t(s);
l = uint32_t(m);
}
}
uint32_t result = m >> 32;
return result;
}
/// Fill `bytes` with `size` random hex bytes
void randomHex(uint8_t *bytes, int size);
private:
uint32_t pcg32_random_r() {
uint64_t oldState = state;
// Advance internal state
state = oldState * 6364136223846793005ULL + inc;
// Calculate output function (XSH RR), uses old state for max ILP
uint32_t xorShifted = ((oldState >> 18u) ^ oldState) >> 27u;
uint32_t rot = oldState >> 59u;
return (xorShifted >> rot) | (xorShifted << ((-rot) & 31));
}
// Seed the rng. Specified in two parts, state initializer and a
// sequence selection constant (a.k.a. stream id)
void pcg32_srandom_r(uint64_t initstate, uint64_t initSeq) {
state = 0U;
inc = (initSeq << 1u) | 1u;
pcg32_random_r();
state += initstate;
pcg32_random_r();
}
uint32_t next_{};
// RNG state. All values are possible.
uint64_t state{};
// Controls which RNG sequence (stream) is selected. Must *always* be odd.
uint64_t inc{};
};
void Random::randomHex(uint8_t *bytes, int size) {
int i = 0;
while (i + 8 < size) {
uint32_t r = next();
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
bytes[i++] = "0123456789abcdef"[r & 0b1111];
}
uint32_t r = next();
while (i < size) {
bytes[i++] = "0123456789abcdef"[r & 0b1111];
r >>= 4;
}
}
Random seededRandom() {
FILE *f = fopen("/dev/urandom", "r");
if (f == nullptr) {
fprintf(stderr, "Failed to open /dev/urandom\n");
abort();
}
uint64_t seed[2];
if (fread(seed, sizeof(seed[0]), sizeof(seed) / sizeof(seed[0]), f) !=
sizeof(seed) / sizeof(seed[0])) {
fprintf(stderr, "Failed to read from /dev/urandom\n");
abort();
}
fclose(f);
return Random{seed[0], seed[1]};
}
namespace weaselab {
// 96 is enough for an entire search path in a tree with a size that
@@ -124,7 +234,7 @@ struct Entry {
static Entry *make(int64_t pointVersion, int64_t rangeVersion,
const uint8_t *key, int keyLen, const uint8_t *val,
int valLen) {
int valLen, uint32_t priority) {
auto e =
(Entry *)safe_malloc(sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
e->pointVersion = pointVersion;
@@ -132,7 +242,7 @@ struct Entry {
e->keyLen = keyLen;
e->valLen = valLen;
e->refCount = 1;
e->priority = XXH3_64bits(key, keyLen);
e->priority = priority;
if (keyLen > 0) {
memcpy((uint8_t *)e->getKey(), key, keyLen);
}
@@ -778,7 +888,8 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
node.pointer[0] = 0;
node.pointer[1] = 0;
node.updated.store(false, std::memory_order_relaxed);
node.entry = Entry::make(version, rangeVersion, key, keyLen, val, valLen);
node.entry = Entry::make(version, rangeVersion, key, keyLen, val, valLen,
random.next());
return result;
}
@@ -836,6 +947,7 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
void firstGeq(const Key *key, const int64_t *version, Iterator *iterator,
int count) const;
Random random = seededRandom();
MemManager mm;
RootSet roots;
// Only meaningful within the callstack of `addMutations`

View File

@@ -7,8 +7,11 @@ __tlv_bootstrap
_abort
_bzero
_calloc
_fclose
_fflush
_fopen
_fprintf
_fread
_free
_fwrite
_malloc

View File

@@ -1,7 +1,3 @@
add_library(nanobench ${CMAKE_CURRENT_SOURCE_DIR}/nanobench.cpp)
target_include_directories(nanobench SYSTEM
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/nanobench)
add_library(xxhash OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/xxhash.c)
target_include_directories(xxhash SYSTEM
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/xxhash)

File diff suppressed because it is too large Load Diff

43
third_party/xxhash.c vendored
View File

@@ -1,43 +0,0 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2021 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
*
* 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
* OWNER 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.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"