Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement bpf_get_prandom_u32 using linear congruential generator #2761

Merged
merged 4 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions libs/execution_context/ebpf_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ebpf_native.h"
#include "ebpf_pinning_table.h"
#include "ebpf_program.h"
#include "ebpf_random.h"
#include "ebpf_serialize.h"
#include "ebpf_state.h"
#include "ebpf_tracelog.h"
Expand Down Expand Up @@ -181,6 +182,11 @@ ebpf_core_initiate()
goto Done;
}

return_value = ebpf_random_initiate();
if (return_value != EBPF_SUCCESS) {
goto Done;
}

return_value = ebpf_trace_initiate();
if (return_value != EBPF_SUCCESS) {
goto Done;
Expand Down Expand Up @@ -286,6 +292,8 @@ ebpf_core_terminate()

ebpf_trace_terminate();

ebpf_random_terminate();

ebpf_platform_terminate();
}

Expand Down
3 changes: 3 additions & 0 deletions libs/platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ set(platform_sources
ebpf_interlocked.c
ebpf_serialize.c
ebpf_trampoline.c

ebpf_random.c
ebpf_random.h
)

set(platform_kernel_include_dirs
Expand Down
1 change: 1 addition & 0 deletions libs/platform/ebpf_hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ebpf_epoch.h"
#include "ebpf_hash_table.h"
#include "ebpf_random.h"

// Buckets contain an array of pointers to value and keys.
// Buckets are immutable once inserted in to the hash-table and replaced when
Expand Down
8 changes: 0 additions & 8 deletions libs/platform/ebpf_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,6 @@ ebpf_safe_size_t_subtract(
return RtlSizeTSub(minuend, subtrahend, result) == STATUS_SUCCESS ? EBPF_SUCCESS : EBPF_ARITHMETIC_OVERFLOW;
}

uint32_t
ebpf_random_uint32()
{
LARGE_INTEGER p = KeQueryPerformanceCounter(NULL);
unsigned long seed = p.LowPart ^ (unsigned long)p.HighPart;
return RtlRandomEx(&seed);
}

ebpf_result_t
ebpf_utf8_string_to_unicode(_In_ const ebpf_utf8_string_t* input, _Outptr_ wchar_t** output)
{
Expand Down
8 changes: 0 additions & 8 deletions libs/platform/ebpf_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,14 +780,6 @@ extern "C"
ebpf_validate_security_descriptor(
_In_ const ebpf_security_descriptor_t* security_descriptor, size_t security_descriptor_length);

/**
* @brief Return a pseudorandom number.
*
* @return A pseudorandom number.
*/
uint32_t
ebpf_random_uint32();

/**
* @brief Return time elapsed since boot in units of 100 nanoseconds.
*
Expand Down
62 changes: 62 additions & 0 deletions libs/platform/ebpf_random.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT

#include "ebpf_platform.h"
#include "ebpf_random.h"

// Pointer to cache aligned array of random number generator state.

typedef __declspec(align(EBPF_CACHE_LINE_SIZE)) struct _ebpf_random_state
{
uint64_t state;
uint8_t _padding[EBPF_CACHE_LINE_SIZE - sizeof(uint64_t)];
} ebpf_random_state_t;

static volatile ebpf_random_state_t* _ebpf_random_number_generator_state = NULL;

_Must_inspect_result_ ebpf_result_t
ebpf_random_initiate()
{
LARGE_INTEGER p = KeQueryPerformanceCounter(NULL);
unsigned long seed = p.LowPart ^ (unsigned long)p.HighPart;

uint32_t cpu_count = ebpf_get_cpu_count();
size_t state_size = cpu_count * sizeof(ebpf_random_state_t);
_ebpf_random_number_generator_state = ebpf_allocate_cache_aligned(state_size);
if (_ebpf_random_number_generator_state == NULL) {
return EBPF_NO_MEMORY;
}
for (uint32_t i = 0; i < cpu_count; i++) {
_ebpf_random_number_generator_state[i].state = RtlRandomEx(&seed);
}
return EBPF_SUCCESS;
}

void
ebpf_random_terminate()
{
ebpf_free_cache_aligned((void*)_ebpf_random_number_generator_state);
_ebpf_random_number_generator_state = NULL;
}

#define LCG_MULTIPLIER ((uint64_t)1664525)
#define LCG_OFFSET ((uint64_t)1013904223)
#define LCG_MODULUS ((uint64_t)4294967296)

// Implement a linear congruential random number generator.
// x(n+1) = (a * x(n) + c) % m
// where a = 1664525, c = 1013904223, and m = 4294967296
// See: https://www.researchgate.net/publication/220420979_Random_Number_Generators_Good_Ones_Are_Hard_to_Find
// for more details.
// Note the linear congruential random number generator is not cryptographically secure.
// The values for a, c, and m are chosen to be fast to compute on 32-bit processors and to also have a long period.
uint32_t
ebpf_random_uint32()
{
uint32_t cpu_index = ebpf_get_current_cpu();
volatile ebpf_random_state_t* state = &_ebpf_random_number_generator_state[cpu_index];
uint64_t state64 = state->state;
uint64_t next_state64 = (state64 * LCG_MULTIPLIER + LCG_OFFSET) % LCG_MODULUS;
state->state = next_state64;
return (uint32_t)next_state64;
}
37 changes: 37 additions & 0 deletions libs/platform/ebpf_random.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT

#include "ebpf_platform.h"

#ifdef __cplusplus
extern "C"
{
#endif

/**
* @brief Initialize the random number generator.
*
* @retval EBPF_SUCCESS The operation was successful.
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
* operation.
*/
_Must_inspect_result_ ebpf_result_t
ebpf_random_initiate();

/**
* @brief Terminate the random number generator.
*/
void
ebpf_random_terminate();

/**
* @brief Return a pseudorandom number.
*
* @return A pseudorandom number.
*/
uint32_t
ebpf_random_uint32();

#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions libs/platform/kernel/platform_kernel.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<ClCompile Include="..\ebpf_epoch.c" />
<ClCompile Include="..\ebpf_error.c" />
<ClCompile Include="..\ebpf_platform.c" />
<ClCompile Include="..\ebpf_random.c" />
<ClCompile Include="..\ebpf_tracelog.c" />
<ClCompile Include="..\ebpf_hash_table.c" />
<ClCompile Include="..\ebpf_interlocked.c" />
Expand Down Expand Up @@ -57,6 +58,7 @@
<ClInclude Include="..\ebpf_object.h" />
<ClInclude Include="..\ebpf_pinning_table.h" />
<ClInclude Include="..\ebpf_platform.h" />
<ClInclude Include="..\ebpf_random.h" />
<ClInclude Include="..\ebpf_ring_buffer.h" />
<ClInclude Include="..\ebpf_serialize.h" />
<ClInclude Include="..\ebpf_state.h" />
Expand Down
8 changes: 7 additions & 1 deletion libs/platform/kernel/platform_kernel.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@
<ClCompile Include="..\ebpf_platform.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include=".\ebpf_fault_injection_kernel.c">
<ClCompile Include="ebpf_fault_injection_kernel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_random.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
Expand Down Expand Up @@ -135,5 +138,8 @@
<ClInclude Include="..\ebpf_platform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ebpf_random.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
6 changes: 6 additions & 0 deletions libs/platform/unit/platform_unit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ebpf_pinning_table.h"
#include "ebpf_platform.h"
#include "ebpf_program_types.h"
#include "ebpf_random.h"
#include "ebpf_ring_buffer.h"
#include "ebpf_serialize.h"
#include "ebpf_state.h"
Expand Down Expand Up @@ -64,6 +65,7 @@ class _test_helper
{
REQUIRE(ebpf_platform_initiate() == EBPF_SUCCESS);
platform_initiated = true;
REQUIRE(ebpf_random_initiate() == EBPF_SUCCESS);
REQUIRE(ebpf_epoch_initiate() == EBPF_SUCCESS);
epoch_initiated = true;
REQUIRE(ebpf_async_initiate() == EBPF_SUCCESS);
Expand All @@ -83,6 +85,7 @@ class _test_helper
ebpf_epoch_flush();
ebpf_epoch_terminate();
}
ebpf_random_terminate();
if (platform_initiated) {
ebpf_platform_terminate();
}
Expand Down Expand Up @@ -118,6 +121,9 @@ TEST_CASE("hash_table_test", "[platform]")
uint8_t* returned_value = nullptr;
std::vector<uint8_t> returned_key(13);

_test_helper test_helper;
test_helper.initialize();

for (auto& v : key_1) {
v = static_cast<uint8_t>(ebpf_random_uint32());
}
Expand Down
2 changes: 2 additions & 0 deletions libs/platform/user/platform_user.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ClCompile Include="..\ebpf_epoch.c" />
<ClCompile Include="..\ebpf_error.c" />
<ClCompile Include="..\ebpf_platform.c" />
<ClCompile Include="..\ebpf_random.c" />
<ClCompile Include="..\ebpf_tracelog.c" />
<ClCompile Include="..\ebpf_hash_table.c" />
<ClCompile Include="..\ebpf_interlocked.c" />
Expand All @@ -44,6 +45,7 @@
<ClInclude Include="..\ebpf_object.h" />
<ClInclude Include="..\ebpf_pinning_table.h" />
<ClInclude Include="..\ebpf_platform.h" />
<ClInclude Include="..\ebpf_random.h" />
<ClInclude Include="..\ebpf_ring_buffer.h" />
<ClInclude Include="..\ebpf_state.h" />
<ClInclude Include="..\ebpf_tracelog.h" />
Expand Down
6 changes: 6 additions & 0 deletions libs/platform/user/platform_user.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
<ClCompile Include="..\ebpf_platform.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_random.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\ebpf_epoch.h">
Expand Down Expand Up @@ -111,5 +114,8 @@
<ClInclude Include="..\ebpf_tracelog.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ebpf_random.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions tests/performance/performance.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "ebpf_maps.h"
#include "ebpf_object.h"
#include "ebpf_program.h"
#include "ebpf_random.h"
#include "helpers.h"
#include "performance_measure.h"

Expand Down
2 changes: 1 addition & 1 deletion tools/bpf2c/templates/kernel_mode_bpf2c.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
<ProjectName>$(FileName)_km</ProjectName>
<!-- Required for Microsoft OneBranch builds -->
<UseInternalMSUniCrtPackage>true</UseInternalMSUniCrtPackage>
<UseInternalMSUniCrtPackage>true</UseInternalMSUniCrtPackage>
<UndockedKernelModeBuild>true</UndockedKernelModeBuild>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
Expand Down
Loading