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_subdirectory(third_party)
|
||||||
|
|
||||||
add_executable(versioned_map_main VersionedMap.cpp RootSet.cpp
|
add_executable(versioned_map_main VersionedMap.cpp RootSet.cpp)
|
||||||
$<TARGET_OBJECTS:xxhash>)
|
|
||||||
target_include_directories(versioned_map_main
|
target_include_directories(versioned_map_main
|
||||||
PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
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)
|
target_compile_definitions(versioned_map_main PRIVATE ENABLE_MAIN)
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
target_compile_options(versioned_map_main
|
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_compile_options(${PROJECT_NAME}-object PRIVATE -fno-exceptions -fno-rtti)
|
||||||
target_include_directories(${PROJECT_NAME}-object
|
target_include_directories(${PROJECT_NAME}-object
|
||||||
PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(${PROJECT_NAME}-object PRIVATE xxhash)
|
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
|
OUTPUT ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
|
||||||
COMMAND ld -r $<TARGET_OBJECTS:${PROJECT_NAME}-object>
|
COMMAND ld -r $<TARGET_OBJECTS:${PROJECT_NAME}-object> -o
|
||||||
$<TARGET_OBJECTS:xxhash> -o ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
|
${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o
|
||||||
DEPENDS $<TARGET_OBJECTS:${PROJECT_NAME}-object> $<TARGET_OBJECTS:xxhash>
|
DEPENDS $<TARGET_OBJECTS:${PROJECT_NAME}-object>
|
||||||
COMMAND_EXPAND_LISTS)
|
COMMAND_EXPAND_LISTS)
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} SHARED ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o)
|
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/mman.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.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::MutationType>);
|
||||||
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::Key>);
|
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 {
|
namespace weaselab {
|
||||||
|
|
||||||
// 96 is enough for an entire search path in a tree with a size that
|
// 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,
|
static Entry *make(int64_t pointVersion, int64_t rangeVersion,
|
||||||
const uint8_t *key, int keyLen, const uint8_t *val,
|
const uint8_t *key, int keyLen, const uint8_t *val,
|
||||||
int valLen) {
|
int valLen, uint32_t priority) {
|
||||||
auto e =
|
auto e =
|
||||||
(Entry *)safe_malloc(sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
|
(Entry *)safe_malloc(sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
|
||||||
e->pointVersion = pointVersion;
|
e->pointVersion = pointVersion;
|
||||||
@@ -132,7 +242,7 @@ struct Entry {
|
|||||||
e->keyLen = keyLen;
|
e->keyLen = keyLen;
|
||||||
e->valLen = valLen;
|
e->valLen = valLen;
|
||||||
e->refCount = 1;
|
e->refCount = 1;
|
||||||
e->priority = XXH3_64bits(key, keyLen);
|
e->priority = priority;
|
||||||
if (keyLen > 0) {
|
if (keyLen > 0) {
|
||||||
memcpy((uint8_t *)e->getKey(), key, keyLen);
|
memcpy((uint8_t *)e->getKey(), key, keyLen);
|
||||||
}
|
}
|
||||||
@@ -778,7 +888,8 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
node.pointer[0] = 0;
|
node.pointer[0] = 0;
|
||||||
node.pointer[1] = 0;
|
node.pointer[1] = 0;
|
||||||
node.updated.store(false, std::memory_order_relaxed);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,6 +947,7 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
void firstGeq(const Key *key, const int64_t *version, Iterator *iterator,
|
void firstGeq(const Key *key, const int64_t *version, Iterator *iterator,
|
||||||
int count) const;
|
int count) const;
|
||||||
|
|
||||||
|
Random random = seededRandom();
|
||||||
MemManager mm;
|
MemManager mm;
|
||||||
RootSet roots;
|
RootSet roots;
|
||||||
// Only meaningful within the callstack of `addMutations`
|
// Only meaningful within the callstack of `addMutations`
|
||||||
|
@@ -7,8 +7,11 @@ __tlv_bootstrap
|
|||||||
_abort
|
_abort
|
||||||
_bzero
|
_bzero
|
||||||
_calloc
|
_calloc
|
||||||
|
_fclose
|
||||||
_fflush
|
_fflush
|
||||||
|
_fopen
|
||||||
_fprintf
|
_fprintf
|
||||||
|
_fread
|
||||||
_free
|
_free
|
||||||
_fwrite
|
_fwrite
|
||||||
_malloc
|
_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)
|
add_library(nanobench ${CMAKE_CURRENT_SOURCE_DIR}/nanobench.cpp)
|
||||||
target_include_directories(nanobench SYSTEM
|
target_include_directories(nanobench SYSTEM
|
||||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/nanobench)
|
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