Use hardware-seeded, high quality rng for priority
This fixes a potential denial of service attack
This commit is contained in:
@@ -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)
|
||||
|
120
VersionedMap.cpp
120
VersionedMap.cpp
@@ -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`
|
||||
|
@@ -7,8 +7,11 @@ __tlv_bootstrap
|
||||
_abort
|
||||
_bzero
|
||||
_calloc
|
||||
_fclose
|
||||
_fflush
|
||||
_fopen
|
||||
_fprintf
|
||||
_fread
|
||||
_free
|
||||
_fwrite
|
||||
_malloc
|
||||
|
4
third_party/CMakeLists.txt
vendored
4
third_party/CMakeLists.txt
vendored
@@ -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)
|
||||
|
6773
third_party/include/xxhash/xxhash.h
vendored
6773
third_party/include/xxhash/xxhash.h
vendored
File diff suppressed because it is too large
Load Diff
43
third_party/xxhash.c
vendored
43
third_party/xxhash.c
vendored
@@ -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"
|
Reference in New Issue
Block a user