Add epoch logic to handle run down of map entries. (#43)

* Add epoch logic to handle run down of map entries.
Integrate with execution context to invoke epoch_enter/epoch_exit on entry/exit of execution context.

Resolve: #24

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
Co-authored-by: Dave Thaler <dthaler@microsoft.com>
This commit is contained in:
Alan Jowett 2021-04-19 16:43:45 -06:00 коммит произвёл GitHub
Родитель b115fce38d
Коммит a57bfb30d4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 1615 добавлений и 207 удалений

Просмотреть файл

@ -91,6 +91,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "maps_user", "src\ebpf\libs\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "maps_kernel", "src\ebpf\libs\maps\kernel\maps_kernel.vcxproj", "{08B41A2E-3AA3-49C4-A525-D45B902D9DB0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "epoch_user", "src\ebpf\libs\epoch\user\epoch_user.vcxproj", "{A7E21439-B561-43F0-9DDD-237425F42BCD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "epoch_kernel", "src\ebpf\libs\epoch\kernel\epoch_kernel.vcxproj", "{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@ -735,6 +739,82 @@ Global
{08B41A2E-3AA3-49C4-A525-D45B902D9DB0}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{08B41A2E-3AA3-49C4-A525-D45B902D9DB0}.RelWithDebInfo|x86.Build.0 = Release|Win32
{08B41A2E-3AA3-49C4-A525-D45B902D9DB0}.RelWithDebInfo|x86.Deploy.0 = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|ARM.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|ARM64.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|x64.ActiveCfg = Debug|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|x64.Build.0 = Debug|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|x86.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Debug|x86.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|ARM.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|ARM.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|ARM64.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|ARM64.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|x64.ActiveCfg = Debug|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|x64.Build.0 = Debug|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|x86.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.MinSizeRel|x86.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|ARM.ActiveCfg = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|ARM64.ActiveCfg = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|x64.ActiveCfg = Release|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|x64.Build.0 = Release|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|x86.ActiveCfg = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.Release|x86.Build.0 = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|ARM.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|ARM.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|ARM64.ActiveCfg = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|ARM64.Build.0 = Debug|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|x64.Build.0 = Release|x64
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{A7E21439-B561-43F0-9DDD-237425F42BCD}.RelWithDebInfo|x86.Build.0 = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM.ActiveCfg = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM.Build.0 = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM.Deploy.0 = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM64.Build.0 = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|ARM64.Deploy.0 = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x64.ActiveCfg = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x64.Build.0 = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x64.Deploy.0 = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x86.ActiveCfg = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x86.Build.0 = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Debug|x86.Deploy.0 = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM.ActiveCfg = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM.Build.0 = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM.Deploy.0 = Debug|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM64.ActiveCfg = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM64.Build.0 = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|ARM64.Deploy.0 = Debug|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x64.ActiveCfg = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x64.Build.0 = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x64.Deploy.0 = Debug|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x86.ActiveCfg = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x86.Build.0 = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.MinSizeRel|x86.Deploy.0 = Debug|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM.ActiveCfg = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM.Build.0 = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM.Deploy.0 = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM64.ActiveCfg = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM64.Build.0 = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|ARM64.Deploy.0 = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x64.ActiveCfg = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x64.Build.0 = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x64.Deploy.0 = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x86.ActiveCfg = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x86.Build.0 = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.Release|x86.Deploy.0 = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM.ActiveCfg = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM.Build.0 = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM.Deploy.0 = Release|ARM
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM64.ActiveCfg = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM64.Build.0 = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|ARM64.Deploy.0 = Release|ARM64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x64.Build.0 = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x64.Deploy.0 = Release|x64
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x86.Build.0 = Release|Win32
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}.RelWithDebInfo|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -761,6 +841,8 @@ Global
{FC3F9998-4085-4767-8386-5453F07C3AAD} = {7C2E30D9-E07F-4913-BD8A-345B38F18A81}
{EBC4B40C-2319-4F7E-9531-8232EF8B87F4} = {69CDB6A1-434D-4BC9-9BFF-D12DF7EDBB6B}
{08B41A2E-3AA3-49C4-A525-D45B902D9DB0} = {7C2E30D9-E07F-4913-BD8A-345B38F18A81}
{A7E21439-B561-43F0-9DDD-237425F42BCD} = {69CDB6A1-434D-4BC9-9BFF-D12DF7EDBB6B}
{FB2680FB-13CF-400C-8A5D-042C0AC20A3F} = {7C2E30D9-E07F-4913-BD8A-345B38F18A81}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3D5F862D-74C6-4357-9F95-0B152E33B7B8}

Просмотреть файл

@ -24,6 +24,6 @@ EXPORTS
ebpf_api_pin_map
ebpf_api_unpin_map
ebpf_api_get_next_map
ebpf_api_lookup_map
ebpf_api_get_pinned_map
ebpf_api_get_next_program
ebpf_api_program_query_information

Просмотреть файл

@ -37,7 +37,7 @@ extern "C"
* @brief Load an eBFP program into the kernel execution context.
* @param[in] file An ELF file containing one or more eBPF programs.
* @param[in] section_name Name of the section in the ELF file to load.
* @param[in] execution_type How this program should be run in the exeuction
* @param[in] execution_type How this program should be run in the execution
* context.
* @param[out] handle Handle to eBPF program.
* @param[out] error_message Error message describing what failed.
@ -214,13 +214,13 @@ extern "C"
* @brief Convert an eBPF program to human readable byte code.
* @param[in] file Name of ELF file containing eBPF program.
* @param[in] section The name of the section to query.
* @param[out] dissassembly On success points text version of the program.
* @param[out] disassembly On success points text version of the program.
* @param[out] error_message On failure points to a text description of
* the error.
*/
uint32_t
ebpf_api_elf_disassemble_section(
const char* file, const char* section, const char** dissassembly, const char** error_message);
const char* file, const char* section, const char** disassembly, const char** error_message);
/**
* @brief Convert an eBPF program to human readable byte code.
@ -259,8 +259,8 @@ extern "C"
ebpf_api_pin_map(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length);
/**
* @brief Desasociate a name with a map handle.
* @param[in] name Name to deassociate.
* @brief Dissociate a name with a map handle.
* @param[in] name Name to dissociate.
*/
uint32_t
ebpf_api_unpin_map(const uint8_t* name, uint32_t name_length);
@ -270,7 +270,7 @@ extern "C"
* @param[in] name Name to find.
*/
uint32_t
ebpf_api_lookup_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle);
ebpf_api_get_pinned_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle);
#ifdef __cplusplus
}

Просмотреть файл

@ -16,27 +16,24 @@ extern "C"
typedef uint32_t(__stdcall* ebpf_hook_function)(uint8_t*);
ebpf_error_code_t
ebpf_core_initialize();
ebpf_core_initiate();
void
ebpf_core_terminate();
ebpf_error_code_t
ebpf_core_invoke_hook(_In_ ebpf_program_type_t hook_point, _Inout_ void* context, _Inout_ uint32_t* result);
ebpf_core_invoke_hook(ebpf_program_type_t hook_point, _Inout_ void* context, _Inout_ uint32_t* result);
typedef struct _ebpf_protocol_handler
{
union
{
ebpf_error_code_t (*protocol_handler_no_reply)(_In_ const void* input_buffer);
ebpf_error_code_t (*protocol_handler_with_reply)(
_In_ const void* input_buffer, void* output_buffer, uint16_t output_buffer_length);
} dispatch;
size_t minimum_request_size;
size_t minimum_reply_size;
} const ebpf_protocol_handler_t;
ebpf_error_code_t
ebpf_core_invoke_protocol_handler(
ebpf_operation_id_t operation_id,
_In_ const void* input_buffer,
_Out_writes_bytes_(output_buffer_length) void* output_buffer,
uint16_t output_buffer_length);
extern ebpf_protocol_handler_t EbpfProtocolHandlers[EBPF_OPERATION_LOOKUP_MAP_PINNING + 1];
ebpf_error_code_t
ebpf_core_get_protocol_handler_properties(
ebpf_operation_id_t operation_id, _Out_ size_t* minimum_request_size, _Out_ size_t* minimum_reply_size);
#ifdef __cplusplus
}

Просмотреть файл

@ -0,0 +1,58 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#pragma once
#include "ebpf_platform.h"
#ifdef __cplusplus
extern "C"
{
#endif
ebpf_error_code_t
ebpf_epoch_initiate();
void
ebpf_epoch_terminate();
/**
* @brief Called prior to touching memory with lifetime under epoch control.
* @retval EBPF_ERROR_OUT_OF_RESOURCES Unable to allocate per-thread
* tracking state.
*/
ebpf_error_code_t
ebpf_epoch_enter();
/**
* @brief Called after touching memory with lifetime under epoch control.
*/
void
ebpf_epoch_exit();
/**
* @brief Allocate memory under epoch control.
* @param[in] size Size of memory to allocate
* @param[in] type Allocate memory as executable vs non-executable
* @returns Pointer to memory block allocated, or null on failure.
*/
void*
ebpf_epoch_allocate(size_t size, ebpf_memory_type_t type);
/**
* @brief Free memory under epoch control.
* @param[in] memory Allocation to be freed once epoch ends.
*/
void
ebpf_epoch_free(void* memory);
/**
* @Brief Release any memory that is associated with expired epochs.
*/
void
ebpf_epoch_flush();
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -26,8 +26,11 @@ extern "C"
EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE = 1
} ebpf_code_integrity_state_t;
typedef struct _epbf_non_preemptable_work_item epbf_non_preepmtable_work_item_t;
typedef struct _ebpf_timer_work_item ebpf_timer_work_item_t;
ebpf_error_code_t
ebpf_platform_initialize();
ebpf_platform_initiate();
void
ebpf_platform_terminate();
@ -59,10 +62,56 @@ extern "C"
void
ebpf_lock_unlock(ebpf_lock_t* lock, ebpf_lock_state_t* state);
ebpf_error_code_t
ebpf_get_cpu_count(uint32_t* cpu_count);
bool
ebpf_is_preemptable();
uint32_t
ebpf_get_current_cpu();
uint64_t
ebpf_get_current_thread_id();
bool
ebpf_is_non_preepmtable_work_item_supported();
ebpf_error_code_t
ebpf_allocate_non_preemptable_work_item(
epbf_non_preepmtable_work_item_t** work_item,
uint32_t cpu_id,
void (*work_item_routine)(void* work_item_context, void* parameter_1),
void* work_item_context);
void
ebpf_free_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item);
bool
ebpf_queue_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item, void* parameter_1);
ebpf_error_code_t
ebpf_allocate_timer_work_item(
ebpf_timer_work_item_t** work_item,
void (*work_item_routine)(void* work_item_context),
void* work_item_context);
void
ebpf_schedule_timer_work_item(ebpf_timer_work_item_t* work_item, uint32_t elaped_microseconds);
void
ebpf_free_timer_work_item(ebpf_timer_work_item_t* work_item);
typedef struct _ebpf_hash_table ebpf_hash_table_t;
ebpf_error_code_t
ebpf_hash_table_create(ebpf_hash_table_t** hash_table, size_t key_size, size_t value_size);
ebpf_hash_table_create(
ebpf_hash_table_t** hash_table,
void* (*allocate)(size_t size, ebpf_memory_type_t type),
void (*free)(void* memory),
size_t key_size,
size_t value_size);
void
ebpf_hash_table_destroy(ebpf_hash_table_t* hash_table);
ebpf_error_code_t
@ -75,10 +124,19 @@ extern "C"
ebpf_hash_table_next_key(ebpf_hash_table_t* hash_table, const uint8_t* previous_key, uint8_t* next_key);
int32_t
ebpf_interlocked_increment(volatile int32_t* addend);
ebpf_interlocked_increment_int32(volatile int32_t* addend);
int32_t
ebpf_interlocked_decrement(volatile int32_t* addend);
ebpf_interlocked_decrement_int32(volatile int32_t* addend);
int64_t
ebpf_interlocked_increment_int64(volatile int64_t* addend);
int64_t
ebpf_interlocked_decrement_int64(volatile int64_t* addend);
int32_t
ebpf_interlocked_compare_exchange_int32(volatile int32_t* destination, int32_t exchange, int32_t comperand);
#ifdef __cplusplus
}

Просмотреть файл

@ -7,7 +7,6 @@
typedef enum _ebpf_operation_id
{
EBPF_OPERATION_EVIDENCE,
EBPF_OPERATION_RESOLVE_HELPER,
EBPF_OPERATION_RESOLVE_MAP,
EBPF_OPERATION_LOAD_CODE,
@ -24,7 +23,7 @@ typedef enum _ebpf_operation_id
EBPF_OPERATION_QUERY_MAP_DEFINITION,
EBPF_OPERATION_QUERY_PROGRAM_INFORMATION,
EBPF_OPERATION_UPDATE_MAP_PINNING,
EBPF_OPERATION_LOOKUP_MAP_PINNING,
EBPF_OPERATION_GET_MAP_PINNING,
} ebpf_operation_id_t;
typedef enum _ebpf_code_type
@ -39,18 +38,6 @@ typedef struct _ebpf_operation_header
ebpf_operation_id_t id;
} ebpf_operation_header_t;
typedef struct _ebpf_operation_eidence_request
{
struct _ebpf_operation_header header;
uint8_t EBPF_OPERATION_EVIDENCE[1];
} ebpf_operation_eidence_request_t;
typedef struct _ebpf_operation_evidence_reply
{
struct _ebpf_operation_header header;
uint32_t status;
} ebpf_operation_evidence_reply_t;
typedef struct _ebpf_operation_resolve_helper_request
{
struct _ebpf_operation_header header;
@ -215,14 +202,14 @@ typedef struct _ebpf_operation_update_map_pinning_request
uint8_t name[1];
} ebpf_operation_update_map_pinning_request_t;
typedef struct _ebpf_operation_lookup_map_pinning_request
typedef struct _ebpf_operation_get_map_pinning_request
{
struct _ebpf_operation_header header;
uint8_t name[1];
} ebpf_operation_lookup_map_pinning_request_t;
} ebpf_operation_get_map_pinning_request_t;
typedef struct _ebpf_operation_lookup_map_pinning_reply
typedef struct _ebpf_operation_get_map_pinning_reply
{
struct _ebpf_operation_header header;
uint64_t handle;
} ebpf_operation_lookup_map_pinning_reply_t;
} ebpf_operation_get_map_pinning_reply_t;

Просмотреть файл

@ -443,13 +443,13 @@ ebpf_api_unpin_map(const uint8_t* name, uint32_t name_length)
}
uint32_t
ebpf_api_lookup_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle)
ebpf_api_get_pinned_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle)
{
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_lookup_map_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_lookup_map_pinning_request_t*>(request_buffer.data());
ebpf_operation_lookup_map_pinning_reply_t reply;
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_get_map_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_get_map_pinning_request_t*>(request_buffer.data());
ebpf_operation_get_map_pinning_reply_t reply;
request->header.id = EBPF_OPERATION_LOOKUP_MAP_PINNING;
request->header.id = EBPF_OPERATION_GET_MAP_PINNING;
request->header.length = static_cast<uint16_t>(request_buffer.size());
std::copy(name, name + name_length, request->name);
auto result = invoke_ioctl(device_handle, request_buffer, reply);
@ -457,7 +457,7 @@ ebpf_api_lookup_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* ha
return result;
}
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_LOOKUP_MAP_PINNING) {
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_GET_MAP_PINNING) {
return ERROR_INVALID_PARAMETER;
}

Просмотреть файл

@ -0,0 +1,356 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#include "ebpf_epoch.h"
// Brief summary of how epoch tracking works.
// Each free operation increments the epoch and the freed memory is stamped with
// that epoch.
//
// Each block of code that accesses epoch freed memory wraps access in calls to
// ebpf_epoch_enter/ebpf_epoch_exit.
//
// Epoch tracking is handled differently for pre-emptable vs non-pre-emptable
// invocations.
//
// Non-pre-emptable invocations are:
// 1) Tracked by the CPU they are running on as they don't switch CPUs.
// 2) Accessed without synchronization.
// 3) Set to the current epoch on entry.
//
// Pre-emptable invocations are:
// 1) Tracked by thread ID.
// 2) Accessed under a lock.
// 3) Set to the current epoch on entry.
// 4) Set to epoch 0 on exit.
//
// Memory can be freed only if there is no code using that epoch.
// The CPU epoch table and thread table are scanned to find the lowest epoch in use.
// The release epoch is then lowest epoch - 1 (if not 0).
//
// Note:
// CPU table entries aren't cleared on exit as we can't rely on
// memory ordering.
// I.e., the thread doing the cleanup may have a stale view of the CPU table.
// As long as the entries in the CPU table increase, this gives correct behavior.
//
#define EBPF_EPOCH_FLUSH_DELAY_IN_MICROSECONDS 1000
// TODO: This lock may become a contention point.
// Investigate partitioning the table.
static ebpf_lock_t _ebpf_epoch_thread_table_lock = {0};
// Table to track what epoch each thread is on.
static ebpf_hash_table_t* _ebpf_epoch_thread_table = NULL;
// Table to track what epoch each CPU is on.
typedef struct _ebpf_epoch_cpu_entry
{
int64_t epoch;
epbf_non_preepmtable_work_item_t* non_preemtable_work_item;
} ebpf_epoch_cpu_entry_t;
static ebpf_epoch_cpu_entry_t* _ebpf_epoch_cpu_table = NULL;
static uint32_t _ebpf_epoch_cpu_table_size = 0;
static volatile int64_t _ebpf_current_epoch = 1;
static ebpf_timer_work_item_t* _ebpf_flush_timer = NULL;
static volatile int32_t _ebpf_flush_timer_set = 0;
typedef struct _ebpf_epoch_allocation_header
{
struct _ebpf_epoch_allocation_header* next;
int64_t freed_epoch;
} ebpf_epoch_allocation_header_t;
static ebpf_lock_t _ebpf_epoch_free_list_lock = {0};
static ebpf_epoch_allocation_header_t _ebpf_epoch_free_list = {0};
// Release memory that was freed during this epoch or a prior epoch.
static void
ebpf_epoch_release_free_list(int64_t released_epoch);
// Get the highest epoch that is no longer in use.
static ebpf_error_code_t
ebpf_epoch_get_release_epoch(int64_t* released_epoch);
static void
_ebpf_epoch_update_cpu_entry(void* context, void* parameter_1);
static void
_ebpf_flush_worker(void* context);
ebpf_error_code_t
ebpf_epoch_initiate()
{
ebpf_error_code_t return_value;
uint32_t cpu_id;
_ebpf_current_epoch = 1;
ebpf_lock_create(&_ebpf_epoch_thread_table_lock);
ebpf_lock_create(&_ebpf_epoch_free_list_lock);
if (ebpf_is_non_preepmtable_work_item_supported()) {
return_value = ebpf_get_cpu_count(&_ebpf_epoch_cpu_table_size);
if (return_value != EBPF_ERROR_SUCCESS) {
goto Error;
}
_ebpf_epoch_cpu_table =
ebpf_allocate(_ebpf_epoch_cpu_table_size * sizeof(ebpf_epoch_cpu_entry_t), EBPF_MEMORY_NO_EXECUTE);
if (!_ebpf_epoch_cpu_table) {
return_value = EBPF_ERROR_OUT_OF_RESOURCES;
goto Error;
}
memset(_ebpf_epoch_cpu_table, 0, _ebpf_epoch_cpu_table_size * sizeof(ebpf_epoch_cpu_entry_t));
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_table_size; cpu_id++) {
_ebpf_epoch_cpu_table[cpu_id].epoch = 0;
return_value = ebpf_allocate_non_preemptable_work_item(
&_ebpf_epoch_cpu_table[cpu_id].non_preemtable_work_item,
cpu_id,
_ebpf_epoch_update_cpu_entry,
&_ebpf_epoch_cpu_table[cpu_id]);
if (return_value != EBPF_ERROR_SUCCESS)
break;
}
if (return_value != EBPF_ERROR_SUCCESS) {
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_table_size; cpu_id++) {
ebpf_free_non_preemptable_work_item(_ebpf_epoch_cpu_table[cpu_id].non_preemtable_work_item);
}
}
if (return_value != EBPF_ERROR_SUCCESS)
goto Error;
}
return_value =
ebpf_hash_table_create(&_ebpf_epoch_thread_table, ebpf_allocate, ebpf_free, sizeof(uint64_t), sizeof(int64_t));
if (return_value != EBPF_ERROR_SUCCESS) {
goto Error;
}
return_value = ebpf_allocate_timer_work_item(&_ebpf_flush_timer, _ebpf_flush_worker, NULL);
if (return_value != EBPF_ERROR_SUCCESS) {
goto Error;
}
return return_value;
Error:
ebpf_epoch_terminate();
return return_value;
}
void
ebpf_epoch_terminate()
{
ebpf_free_timer_work_item(_ebpf_flush_timer);
ebpf_hash_table_destroy(_ebpf_epoch_thread_table);
ebpf_free(_ebpf_epoch_cpu_table);
ebpf_lock_destroy(&_ebpf_epoch_thread_table_lock);
ebpf_epoch_release_free_list(INT64_MAX);
ebpf_lock_destroy(&_ebpf_epoch_free_list_lock);
}
ebpf_error_code_t
ebpf_epoch_enter()
{
if (!ebpf_is_non_preepmtable_work_item_supported() || ebpf_is_preemptable()) {
ebpf_error_code_t return_value;
ebpf_lock_state_t lock_state;
uint64_t current_thread_id = ebpf_get_current_thread_id();
int64_t current_epoch = _ebpf_current_epoch;
ebpf_lock_lock(&_ebpf_epoch_thread_table_lock, &lock_state);
return_value = ebpf_hash_table_update(
_ebpf_epoch_thread_table, (const uint8_t*)&current_thread_id, (const uint8_t*)&current_epoch);
ebpf_lock_unlock(&_ebpf_epoch_thread_table_lock, &lock_state);
return return_value;
} else {
uint32_t current_cpu = ebpf_get_current_cpu();
if (current_cpu >= _ebpf_epoch_cpu_table_size) {
return EBPF_ERROR_NOT_SUPPORTED;
}
_ebpf_epoch_cpu_table[current_cpu].epoch = _ebpf_current_epoch;
return EBPF_ERROR_SUCCESS;
}
}
void
ebpf_epoch_exit()
{
if (ebpf_is_preemptable()) {
ebpf_lock_state_t lock_state;
uint64_t current_thread_id = ebpf_get_current_thread_id();
int64_t current_epoch = 0;
ebpf_lock_lock(&_ebpf_epoch_thread_table_lock, &lock_state);
ebpf_hash_table_update(
_ebpf_epoch_thread_table, (const uint8_t*)&current_thread_id, (const uint8_t*)&current_epoch);
ebpf_lock_unlock(&_ebpf_epoch_thread_table_lock, &lock_state);
} else {
uint32_t current_cpu = ebpf_get_current_cpu();
if (current_cpu >= _ebpf_epoch_cpu_table_size) {
return;
}
_ebpf_epoch_cpu_table[current_cpu].epoch = _ebpf_current_epoch;
}
if (_ebpf_epoch_free_list.next != NULL &&
(ebpf_interlocked_compare_exchange_int32(&_ebpf_flush_timer_set, 0, 1) != 0)) {
ebpf_schedule_timer_work_item(_ebpf_flush_timer, EBPF_EPOCH_FLUSH_DELAY_IN_MICROSECONDS);
}
}
void
ebpf_epoch_flush()
{
ebpf_error_code_t return_value;
int64_t released_epoch;
uint32_t cpu_id;
if (ebpf_is_non_preepmtable_work_item_supported()) {
// Schedule a non-preemptable work item to bring the CPU up to the current
// epoch.
// Note: May not affect the current flush.
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_table_size; cpu_id++) {
if (!_ebpf_epoch_cpu_table[cpu_id].non_preemtable_work_item)
break;
// Don't synchronize CPUs that have never participated.
if (_ebpf_epoch_cpu_table[cpu_id].epoch == 0)
continue;
// Note: Either the per-cpu epoch or the global epoch could be out of date.
// That is acceptable as it may schedule an extra work item.
if (_ebpf_epoch_cpu_table[cpu_id].epoch != _ebpf_current_epoch)
ebpf_queue_non_preemptable_work_item(_ebpf_epoch_cpu_table[cpu_id].non_preemtable_work_item, NULL);
}
}
return_value = ebpf_epoch_get_release_epoch(&released_epoch);
if (return_value == EBPF_ERROR_SUCCESS) {
ebpf_epoch_release_free_list(released_epoch);
}
}
void*
ebpf_epoch_allocate(size_t size, ebpf_memory_type_t type)
{
ebpf_epoch_allocation_header_t* header;
size += sizeof(ebpf_epoch_allocation_header_t);
header = (ebpf_epoch_allocation_header_t*)ebpf_allocate(size, type);
if (header)
header++;
return header;
}
void
ebpf_epoch_free(void* memory)
{
ebpf_epoch_allocation_header_t* header = (ebpf_epoch_allocation_header_t*)memory;
ebpf_lock_state_t lock_state;
header--;
header->freed_epoch = ebpf_interlocked_increment_int64(&_ebpf_current_epoch) - 1;
ebpf_lock_lock(&_ebpf_epoch_free_list_lock, &lock_state);
header->next = _ebpf_epoch_free_list.next;
_ebpf_epoch_free_list.next = header;
ebpf_lock_unlock(&_ebpf_epoch_free_list_lock, &lock_state);
}
static void
ebpf_epoch_release_free_list(int64_t released_epoch)
{
ebpf_lock_state_t lock_state;
ebpf_epoch_allocation_header_t* header;
ebpf_epoch_allocation_header_t* previous_header;
ebpf_lock_lock(&_ebpf_epoch_free_list_lock, &lock_state);
header = _ebpf_epoch_free_list.next;
previous_header = &_ebpf_epoch_free_list;
while (header) {
if (header->freed_epoch <= released_epoch) {
previous_header->next = header->next;
ebpf_free(header);
header = previous_header->next;
} else {
previous_header = header;
header = header->next;
}
}
ebpf_lock_unlock(&_ebpf_epoch_free_list_lock, &lock_state);
}
static ebpf_error_code_t
ebpf_epoch_get_release_epoch(int64_t* release_epoch)
{
int64_t lowest_epoch = INT64_MAX;
int64_t* thread_epoch;
uint32_t cpu_id;
uint64_t thread_id = 0;
ebpf_lock_state_t lock_state;
ebpf_error_code_t return_value;
if (ebpf_is_non_preepmtable_work_item_supported()) {
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_table_size; cpu_id++) {
if ((_ebpf_epoch_cpu_table[cpu_id].epoch != 0) && _ebpf_epoch_cpu_table[cpu_id].epoch < lowest_epoch)
lowest_epoch = _ebpf_epoch_cpu_table[cpu_id].epoch;
}
}
ebpf_lock_lock(&_ebpf_epoch_thread_table_lock, &lock_state);
return_value = ebpf_hash_table_next_key(_ebpf_epoch_thread_table, NULL, (uint8_t*)&thread_id);
if (return_value == EBPF_ERROR_SUCCESS)
for (;;) {
return_value =
ebpf_hash_table_lookup(_ebpf_epoch_thread_table, (uint8_t*)&thread_id, (uint8_t**)&thread_epoch);
if (return_value != EBPF_ERROR_SUCCESS)
break;
if (*thread_epoch != 0 && *thread_epoch < lowest_epoch)
lowest_epoch = *thread_epoch;
return_value =
ebpf_hash_table_next_key(_ebpf_epoch_thread_table, (uint8_t*)&thread_id, (uint8_t*)&thread_id);
if (return_value != EBPF_ERROR_SUCCESS)
break;
}
ebpf_lock_unlock(&_ebpf_epoch_thread_table_lock, &lock_state);
if (return_value != EBPF_ERROR_NO_MORE_KEYS) {
return return_value;
}
*release_epoch = lowest_epoch - 1;
return EBPF_ERROR_SUCCESS;
}
static void
_ebpf_epoch_update_cpu_entry(void* context, void* parameter_1)
{
ebpf_epoch_cpu_entry_t* cpu_entry = (ebpf_epoch_cpu_entry_t*)context;
UNREFERENCED_PARAMETER(parameter_1);
cpu_entry->epoch = _ebpf_current_epoch;
}
static void
_ebpf_flush_worker(void* context)
{
UNREFERENCED_PARAMETER(context);
if (ebpf_interlocked_compare_exchange_int32(&_ebpf_flush_timer_set, 1, 0) != 1) {
return;
}
ebpf_epoch_flush();
}

Просмотреть файл

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: MIT
-->
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_epoch.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\include\ebpf_epoch.h" />
<ClInclude Include="..\..\..\include\ebpf_platform.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{FB2680FB-13CF-400C-8A5D-042C0AC20A3F}</ProjectGuid>
<TemplateGuid>{0a049372-4c4d-4ea0-a64e-dc6ad88ceca1}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>epoch_kernel</RootNamespace>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)\src\ebpf\include;$(SolutionDir)\src\ebpf\include\kernel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)\src\ebpf\include;$(SolutionDir)\src\ebpf\include\kernel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ClCompile>
<PreprocessorDefinitions>WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<PreprocessorDefinitions>WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: MIT
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_epoch.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\include\ebpf_epoch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\include\ebpf_platform.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: MIT
-->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\include\ebpf_epoch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_epoch.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{a7e21439-b561-43f0-9ddd-237425f42bcd}</ProjectGuid>
<RootNamespace>epochuser</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(SolutionDir)\src\ebpf\include;$(SolutionDir)\src\ebpf\include\user</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(SolutionDir)\src\ebpf\include;$(SolutionDir)\src\ebpf\include\user</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: MIT
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\include\ebpf_epoch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_epoch.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

Просмотреть файл

@ -5,6 +5,7 @@
#include "ebpf_core.h"
#include "ebpf_epoch.h"
#include "ebpf_maps.h"
#include "ubpf.h"
@ -262,20 +263,37 @@ _ebpf_core_delete_code_entry(uint64_t handle)
}
ebpf_error_code_t
ebpf_core_initialize()
ebpf_core_initiate()
{
ebpf_error_code_t return_value;
return_value = ebpf_platform_initialize();
if (return_value != EBPF_ERROR_SUCCESS) {
return return_value;
}
bool platform_initialized = false;
bool epoch_initialize = false;
return_value = ebpf_platform_initiate();
if (return_value != EBPF_ERROR_SUCCESS)
goto Done;
platform_initialized = true;
return_value = ebpf_epoch_initiate();
if (return_value != EBPF_ERROR_SUCCESS)
goto Done;
epoch_initialize = true;
ebpf_lock_create(&_ebpf_core_code_entry_table_lock);
ebpf_lock_create(&_ebpf_core_map_entry_table_lock);
ebpf_lock_create(&_ebpf_core_hook_table_lock);
ebpf_lock_create(&_ebpf_core_pinning_table_lock);
return ebpf_query_code_integrity_state(&_ebpf_core_code_integrity_state);
return_value = ebpf_query_code_integrity_state(&_ebpf_core_code_integrity_state);
Done:
if (return_value != EBPF_ERROR_SUCCESS) {
if (epoch_initialize)
ebpf_epoch_terminate();
if (platform_initialized)
ebpf_platform_terminate();
}
return return_value;
}
void
@ -298,6 +316,10 @@ ebpf_core_terminate()
for (index = 0; index < EBPF_COUNT_OF(_ebpf_core_pinning_table); index++)
ebpf_free(_ebpf_core_pinning_table[index]);
ebpf_lock_unlock(&_ebpf_core_pinning_table_lock, &state);
ebpf_epoch_terminate();
ebpf_platform_terminate();
}
static ebpf_error_code_t
@ -449,7 +471,7 @@ ebpf_core_protocol_load_code(
goto Done;
}
// BUG - ubpf implements bounds checking to detect interpreted code accesing
// BUG - ubpf implements bounds checking to detect interpreted code accessing
// memory out of bounds. Currently this is flagging valid access checks and
// failing.
toggle_bounds_check(code_entry->code_or_vm.vm, false);
@ -536,27 +558,31 @@ ebpf_core_protocol_resolve_map(
}
ebpf_error_code_t
ebpf_core_invoke_hook(_In_ ebpf_program_type_t hook_point, _Inout_ void* context, _Inout_ uint32_t* result)
ebpf_core_invoke_hook(ebpf_program_type_t hook_point, _Inout_ void* context, _Inout_ uint32_t* result)
{
ebpf_error_code_t retval;
ebpf_core_code_entry_t* code = NULL;
ebpf_hook_function function_pointer;
char* error_message = NULL;
retval = ebpf_epoch_enter();
if (retval != EBPF_ERROR_SUCCESS)
return retval;
code = _ebpf_core_get_hook_entry(hook_point);
if (code) {
if (code->code_type == EBPF_CODE_NATIVE) {
function_pointer = (ebpf_hook_function)(code->code_or_vm.code);
*result = (function_pointer)(context);
return EBPF_ERROR_SUCCESS;
} else {
*result = (uint32_t)(ubpf_exec(code->code_or_vm.vm, context, 1024, &error_message));
if (error_message) {
ebpf_free(error_message);
}
return EBPF_ERROR_SUCCESS;
}
}
// Nothing to do if no hook is registered.
ebpf_epoch_exit();
return EBPF_ERROR_SUCCESS;
}
@ -742,7 +768,7 @@ ebpf_core_protocol_get_next_map(
uint64_t next_handle = request->previous_handle;
UNREFERENCED_PARAMETER(reply_length);
// Start search from begining
// Start search from beginning
if (next_handle == UINT64_MAX) {
next_handle = 1;
} else {
@ -776,7 +802,7 @@ ebpf_core_protocol_get_next_program(
uint64_t next_handle = request->previous_handle;
UNREFERENCED_PARAMETER(reply_length);
// Start search from begining
// Start search from beginning
if (next_handle == UINT64_MAX) {
next_handle = 1;
} else {
@ -895,14 +921,14 @@ Done:
}
static ebpf_error_code_t
ebpf_core_protocol_lookup_map_pinning(
_In_ const struct _ebpf_operation_lookup_map_pinning_request* request,
_Inout_ struct _ebpf_operation_lookup_map_pinning_reply* reply,
ebpf_core_protocol_get_pinned_map(
_In_ const struct _ebpf_operation_get_map_pinning_request* request,
_Inout_ struct _ebpf_operation_get_map_pinning_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
const uint8_t* name = request->name;
size_t name_length = request->header.length - EBPF_OFFSET_OF(ebpf_operation_lookup_map_pinning_request_t, name);
size_t name_length = request->header.length - EBPF_OFFSET_OF(ebpf_operation_get_map_pinning_request_t, name);
UNREFERENCED_PARAMETER(reply_length);
if (name_length == 0) {
@ -950,8 +976,21 @@ ebpf_core_interpreter_helper_resolver(void* context, uint32_t helper_id)
return (uint64_t)_ebpf_program_helpers[helper_id];
}
ebpf_protocol_handler_t EbpfProtocolHandlers[EBPF_OPERATION_LOOKUP_MAP_PINNING + 1] = {
{NULL, sizeof(struct _ebpf_operation_eidence_request)}, // EBPF_OPERATION_EVIDENCE
typedef struct _ebpf_protocol_handler
{
union
{
ebpf_error_code_t (*protocol_handler_no_reply)(_In_ const void* input_buffer);
ebpf_error_code_t (*protocol_handler_with_reply)(
_In_ const void* input_buffer,
_Out_writes_bytes_(output_buffer_length) void* output_buffer,
uint16_t output_buffer_length);
} dispatch;
size_t minimum_request_size;
size_t minimum_reply_size;
} const ebpf_protocol_handler_t;
static ebpf_protocol_handler_t _ebpf_protocol_handlers[EBPF_OPERATION_GET_MAP_PINNING + 1] = {
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_resolve_helper,
sizeof(struct _ebpf_operation_resolve_helper_request),
sizeof(struct _ebpf_operation_resolve_helper_reply)},
@ -988,7 +1027,52 @@ ebpf_protocol_handler_t EbpfProtocolHandlers[EBPF_OPERATION_LOOKUP_MAP_PINNING +
sizeof(struct _ebpf_operation_query_program_information_request),
sizeof(struct _ebpf_operation_query_program_information_reply)},
{ebpf_core_protocol_update_map_pinning, sizeof(struct _ebpf_operation_update_map_pinning_request), 0},
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_lookup_map_pinning,
sizeof(struct _ebpf_operation_lookup_map_pinning_request),
sizeof(struct _ebpf_operation_lookup_map_pinning_reply)},
};
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_get_pinned_map,
sizeof(struct _ebpf_operation_get_map_pinning_request),
sizeof(struct _ebpf_operation_get_map_pinning_reply)},
};
ebpf_error_code_t
ebpf_core_get_protocol_handler_properties(
ebpf_operation_id_t operation_id, _Out_ size_t* minimum_request_size, _Out_ size_t* minimum_reply_size)
{
*minimum_request_size = 0;
*minimum_reply_size = 0;
if (operation_id > EBPF_OPERATION_GET_MAP_PINNING || operation_id < EBPF_OPERATION_RESOLVE_HELPER)
return EBPF_ERROR_NOT_SUPPORTED;
if (!_ebpf_protocol_handlers[operation_id].dispatch.protocol_handler_no_reply)
return EBPF_ERROR_NOT_SUPPORTED;
*minimum_request_size = _ebpf_protocol_handlers[operation_id].minimum_request_size;
*minimum_reply_size = _ebpf_protocol_handlers[operation_id].minimum_reply_size;
return EBPF_ERROR_SUCCESS;
}
ebpf_error_code_t
ebpf_core_invoke_protocol_handler(
ebpf_operation_id_t operation_id,
_In_ const void* input_buffer,
_Out_writes_bytes_(output_buffer_length) void* output_buffer,
uint16_t output_buffer_length)
{
ebpf_error_code_t retval;
if (operation_id > EBPF_OPERATION_GET_MAP_PINNING || operation_id < EBPF_OPERATION_RESOLVE_HELPER) {
return EBPF_ERROR_NOT_SUPPORTED;
}
retval = ebpf_epoch_enter();
if (retval != EBPF_ERROR_SUCCESS)
return retval;
if (output_buffer == NULL)
retval = _ebpf_protocol_handlers[operation_id].dispatch.protocol_handler_no_reply(input_buffer);
else
retval = _ebpf_protocol_handlers[operation_id].dispatch.protocol_handler_with_reply(
input_buffer, output_buffer, output_buffer_length);
ebpf_epoch_exit();
return retval;
}

Просмотреть файл

@ -4,6 +4,7 @@
*/
#include "ebpf_maps.h"
#include "ebpf_epoch.h"
typedef struct _ebpf_core_map
{
@ -52,13 +53,13 @@ ebpf_map_create(const ebpf_map_definition_t* ebpf_map_definition, ebpf_map_t** e
void
ebpf_map_acquire_reference(ebpf_map_t* map)
{
ebpf_interlocked_increment(&map->reference_count);
ebpf_interlocked_increment_int32(&map->reference_count);
}
void
ebpf_map_release_reference(ebpf_map_t* map)
{
uint32_t new_ref_count = ebpf_interlocked_decrement(&map->reference_count);
uint32_t new_ref_count = ebpf_interlocked_decrement_int32(&map->reference_count);
if (new_ref_count == 0)
ebpf_map_function_tables[map->ebpf_map_definition.type].delete_map(map);
}
@ -197,7 +198,11 @@ ebpf_create_hash_map(_In_ const ebpf_map_definition_t* map_definition)
map->data = NULL;
retval = ebpf_hash_table_create(
(ebpf_hash_table_t**)&map->data, map->ebpf_map_definition.key_size, map->ebpf_map_definition.value_size);
(ebpf_hash_table_t**)&map->data,
ebpf_epoch_allocate,
ebpf_epoch_free,
map->ebpf_map_definition.key_size,
map->ebpf_map_definition.value_size);
if (retval != EBPF_ERROR_SUCCESS) {
goto Done;
}

Просмотреть файл

@ -9,6 +9,8 @@ struct _ebpf_hash_table
struct _RTL_AVL_TABLE avl_table;
size_t key_size;
size_t value_size;
void* (*allocate)(size_t size, ebpf_memory_type_t type);
void (*free)(void* memory);
};
// NOTE:
@ -31,21 +33,26 @@ ebpf_hash_map_compare(struct _RTL_AVL_TABLE* avl_table, void* first_struct, void
}
static void*
ebpf_hash_map_allocate(struct _RTL_AVL_TABLE* table, unsigned long byte_size)
ebpf_hash_map_allocate(struct _RTL_AVL_TABLE* avl_table, unsigned long byte_size)
{
UNREFERENCED_PARAMETER(table);
return ebpf_allocate(byte_size, EBPF_MEMORY_NO_EXECUTE);
ebpf_hash_table_t* table = (ebpf_hash_table_t*)avl_table;
return table->allocate(byte_size, EBPF_MEMORY_NO_EXECUTE);
}
static void
ebpf_hash_map_free(struct _RTL_AVL_TABLE* table, void* buffer)
ebpf_hash_map_free(struct _RTL_AVL_TABLE* avl_table, void* buffer)
{
UNREFERENCED_PARAMETER(table);
ebpf_free(buffer);
ebpf_hash_table_t* table = (ebpf_hash_table_t*)avl_table;
table->free(buffer);
}
ebpf_error_code_t
ebpf_hash_table_create(ebpf_hash_table_t** hash_table, size_t key_size, size_t value_size)
ebpf_hash_table_create(
ebpf_hash_table_t** hash_table,
void* (*allocate)(size_t size, ebpf_memory_type_t type),
void (*free)(void* memory),
size_t key_size,
size_t value_size)
{
ebpf_error_code_t retval;
ebpf_hash_table_t* table = NULL;
@ -62,6 +69,8 @@ ebpf_hash_table_create(ebpf_hash_table_t** hash_table, size_t key_size, size_t v
table->key_size = key_size;
table->value_size = value_size;
table->allocate = allocate;
table->free = free;
*hash_table = table;
retval = EBPF_ERROR_SUCCESS;
@ -165,7 +174,7 @@ ebpf_hash_table_next_key(ebpf_hash_table_t* hash_table, const uint8_t* previous_
if (!entry) {
// Entry deleted.
// Start at the begining of the table.
// Start at the beginning of the table.
entry = RtlEnumerateGenericTableAvl(table, TRUE);
if (entry == NULL) {
return EBPF_ERROR_NO_MORE_KEYS;

Просмотреть файл

@ -10,7 +10,7 @@ typedef enum _ebpf_pool_tag
} ebpf_pool_tag_t;
ebpf_error_code_t
ebpf_platform_initialize()
ebpf_platform_initiate()
{
return EBPF_ERROR_SUCCESS;
}
@ -109,13 +109,174 @@ ebpf_lock_unlock(ebpf_lock_t* lock, ebpf_lock_state_t* state)
}
int32_t
ebpf_interlocked_increment(volatile int32_t* addend)
ebpf_interlocked_increment_int32(volatile int32_t* addend)
{
return InterlockedIncrement((volatile LONG*)addend);
return InterlockedIncrement((volatile long*)addend);
}
int32_t
ebpf_interlocked_decrement(volatile int32_t* addend)
ebpf_interlocked_decrement_int32(volatile int32_t* addend)
{
return InterlockedDecrement((volatile LONG*)addend);
}
return InterlockedDecrement((volatile long*)addend);
}
int64_t
ebpf_interlocked_increment_int64(volatile int64_t* addend)
{
return InterlockedIncrement64(addend);
}
int64_t
ebpf_interlocked_decrement_int64(volatile int64_t* addend)
{
return InterlockedDecrement64(addend);
}
int32_t
ebpf_interlocked_compare_exchange_int32(volatile int32_t* destination, int32_t exchange, int32_t comperand)
{
return InterlockedCompareExchange((long volatile*)destination, exchange, comperand);
}
ebpf_error_code_t
ebpf_get_cpu_count(uint32_t* cpu_count)
{
*cpu_count = KeQueryMaximumProcessorCount();
return EBPF_ERROR_SUCCESS;
}
bool
ebpf_is_preemptable()
{
KIRQL irql = KeGetCurrentIrql();
return irql >= DISPATCH_LEVEL;
}
bool
ebpf_is_non_preepmtable_work_item_supported()
{
return true;
}
uint32_t
ebpf_get_current_cpu()
{
return KeGetCurrentProcessorNumber();
}
uint64_t
ebpf_get_current_thread_id()
{
return (uint64_t)KeGetCurrentThread();
}
typedef struct _epbf_non_preemptable_work_item
{
KDPC deferred_procedure_call;
void (*work_item_routine)(void* work_item_context, void* parameter_1);
} epbf_non_preepmtable_work_item_t;
static void
_ebpf_deferred_routine(
KDPC* deferred_procedure_call, PVOID deferred_context, PVOID system_argument_1, PVOID system_argument_2)
{
epbf_non_preepmtable_work_item_t* deferred_routine_context =
(epbf_non_preepmtable_work_item_t*)deferred_procedure_call;
UNREFERENCED_PARAMETER(system_argument_2);
deferred_routine_context->work_item_routine(deferred_context, system_argument_1);
}
ebpf_error_code_t
ebpf_allocate_non_preemptable_work_item(
epbf_non_preepmtable_work_item_t** work_item,
uint32_t cpu_id,
void (*work_item_routine)(void* work_item_context, void* parameter_1),
void* work_item_context)
{
*work_item = ebpf_allocate(sizeof(epbf_non_preepmtable_work_item_t), EBPF_MEMORY_NO_EXECUTE);
if (*work_item == NULL) {
return EBPF_ERROR_OUT_OF_RESOURCES;
}
(*work_item)->work_item_routine = work_item_routine;
KeInitializeDpc(&(*work_item)->deferred_procedure_call, _ebpf_deferred_routine, work_item_context);
KeSetTargetProcessorDpc(&(*work_item)->deferred_procedure_call, (uint8_t)cpu_id);
return EBPF_ERROR_SUCCESS;
}
void
ebpf_free_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item)
{
if (!work_item)
return;
KeRemoveQueueDpc(&work_item->deferred_procedure_call);
ebpf_free(work_item);
}
bool
ebpf_queue_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item, void* parameter_1)
{
return KeInsertQueueDpc(&work_item->deferred_procedure_call, parameter_1, NULL);
}
typedef struct _ebpf_timer_work_item
{
KTIMER timer;
KDPC deferred_procedure_call;
void (*work_item_routine)(void* work_item_context);
void* work_item_context;
} ebpf_timer_work_item_t;
static void
_ebpf_timer_routine(
KDPC* deferred_procedure_call, PVOID deferred_context, PVOID system_argument_1, PVOID system_argument_2)
{
ebpf_timer_work_item_t* timer_work_item = (ebpf_timer_work_item_t*)deferred_procedure_call;
UNREFERENCED_PARAMETER(system_argument_1);
UNREFERENCED_PARAMETER(system_argument_2);
timer_work_item->work_item_routine(deferred_context);
}
ebpf_error_code_t
ebpf_allocate_timer_work_item(
ebpf_timer_work_item_t** timer_work_item,
void (*work_item_routine)(void* work_item_context),
void* work_item_context)
{
*timer_work_item = ebpf_allocate(sizeof(ebpf_timer_work_item_t), EBPF_MEMORY_NO_EXECUTE);
if (*timer_work_item == NULL)
return EBPF_ERROR_OUT_OF_RESOURCES;
(*timer_work_item)->work_item_routine = work_item_routine;
(*timer_work_item)->work_item_context = work_item_context;
KeInitializeTimer(&(*timer_work_item)->timer);
KeInitializeDpc(&(*timer_work_item)->deferred_procedure_call, _ebpf_timer_routine, work_item_context);
return EBPF_ERROR_SUCCESS;
}
#define MICROSECONDS_PER_TICK 10
#define MICROSECONDS_PER_MILLISECOND 1000
void
ebpf_schedule_timer_work_item(ebpf_timer_work_item_t* work_item, uint32_t elaped_microseconds)
{
LARGE_INTEGER due_time;
due_time.QuadPart = -((int64_t)elaped_microseconds * MICROSECONDS_PER_TICK);
KeSetTimer(&work_item->timer, due_time, &work_item->deferred_procedure_call);
}
void
ebpf_free_timer_work_item(ebpf_timer_work_item_t* work_item)
{
if (!work_item)
return;
KeCancelTimer(&work_item->timer);
KeRemoveQueueDpc(&work_item->deferred_procedure_call);
ebpf_free(work_item);
}

Просмотреть файл

@ -13,7 +13,11 @@
std::set<uint64_t> _executable_segments;
// Global variables used to override behavior for testing.
// Permit the test to simulate both Hyper-V Code Integrity.
bool _ebpf_platform_code_integrity_enabled = false;
// Permit the test to simulate non-preemptable execution.
bool _ebpf_platform_is_preemptable = true;
void (*RtlInitializeGenericTableAvl)(
_Out_ PRTL_AVL_TABLE Table,
@ -46,7 +50,7 @@ resolve_function(HMODULE module_handle, fn& function, const char* function_name)
}
ebpf_error_code_t
ebpf_platform_initialize()
ebpf_platform_initiate()
{
HMODULE ntdll_module = nullptr;
@ -167,13 +171,161 @@ ebpf_lock_unlock(ebpf_lock_t* lock, ebpf_lock_state_t* state)
}
int32_t
ebpf_interlocked_increment(volatile int32_t* addend)
ebpf_interlocked_increment_int32(volatile int32_t* addend)
{
return InterlockedIncrement((volatile LONG*)addend);
return InterlockedIncrement((volatile long*)addend);
}
int32_t
ebpf_interlocked_decrement(volatile int32_t* addend)
ebpf_interlocked_decrement_int32(volatile int32_t* addend)
{
return InterlockedDecrement((volatile LONG*)addend);
}
return InterlockedDecrement((volatile long*)addend);
}
int64_t
ebpf_interlocked_increment_int64(volatile int64_t* addend)
{
return InterlockedIncrement64(addend);
}
int64_t
ebpf_interlocked_decrement_int64(volatile int64_t* addend)
{
return InterlockedDecrement64(addend);
}
int32_t
ebpf_interlocked_compare_exchange_int32(volatile int32_t* destination, int32_t exchange, int32_t comperand)
{
return InterlockedCompareExchange((long volatile*)destination, exchange, comperand);
}
ebpf_error_code_t
ebpf_get_cpu_count(uint32_t* cpu_count)
{
SYSTEM_INFO system_information;
GetNativeSystemInfo(&system_information);
*cpu_count = system_information.dwNumberOfProcessors;
return EBPF_ERROR_SUCCESS;
}
bool
ebpf_is_preemptable()
{
return _ebpf_platform_is_preemptable;
}
bool
ebpf_is_non_preepmtable_work_item_supported()
{
return false;
}
uint32_t
ebpf_get_current_cpu()
{
return GetCurrentProcessorNumber();
}
uint64_t
ebpf_get_current_thread_id()
{
return GetCurrentThreadId();
}
ebpf_error_code_t
ebpf_allocate_non_preemptable_work_item(
epbf_non_preepmtable_work_item_t** work_item,
uint32_t cpu_id,
void (*work_item_routine)(void* work_item_context, void* parameter_1),
void* work_item_context)
{
UNREFERENCED_PARAMETER(work_item);
UNREFERENCED_PARAMETER(cpu_id);
UNREFERENCED_PARAMETER(work_item_routine);
UNREFERENCED_PARAMETER(work_item_context);
return EBPF_ERROR_NOT_SUPPORTED;
}
void
ebpf_free_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item)
{
UNREFERENCED_PARAMETER(work_item);
}
bool
ebpf_queue_non_preemptable_work_item(epbf_non_preepmtable_work_item_t* work_item, void* parameter_1)
{
UNREFERENCED_PARAMETER(work_item);
UNREFERENCED_PARAMETER(parameter_1);
return false;
}
typedef struct _ebpf_timer_work_item
{
TP_TIMER* threadpool_timer;
void (*work_item_routine)(void* work_item_context);
void* work_item_context;
} ebpf_timer_work_item_t;
void
_ebpf_timer_callback(_Inout_ TP_CALLBACK_INSTANCE* instance, _Inout_opt_ void* Context, _Inout_ TP_TIMER* Timer)
{
ebpf_timer_work_item_t* timer_work_item = reinterpret_cast<ebpf_timer_work_item_t*>(Context);
UNREFERENCED_PARAMETER(instance);
UNREFERENCED_PARAMETER(Timer);
timer_work_item->work_item_routine(timer_work_item->work_item_context);
}
ebpf_error_code_t
ebpf_allocate_timer_work_item(
ebpf_timer_work_item_t** work_item, void (*work_item_routine)(void* work_item_context), void* work_item_context)
{
*work_item = (ebpf_timer_work_item_t*)ebpf_allocate(sizeof(ebpf_timer_work_item_t), EBPF_MEMORY_NO_EXECUTE);
if (*work_item == NULL)
goto Error;
(*work_item)->threadpool_timer = CreateThreadpoolTimer(_ebpf_timer_callback, *work_item, NULL);
if ((*work_item)->threadpool_timer == NULL)
goto Error;
(*work_item)->work_item_routine = work_item_routine;
(*work_item)->work_item_context = work_item_context;
return EBPF_ERROR_SUCCESS;
Error:
if (*work_item != NULL) {
if ((*work_item)->threadpool_timer != NULL)
CloseThreadpoolTimer((*work_item)->threadpool_timer);
ebpf_free(*work_item);
}
return EBPF_ERROR_OUT_OF_RESOURCES;
}
#define MICROSECONDS_PER_TICK 10
#define MICROSECONDS_PER_MILLISECOND 1000
void
ebpf_schedule_timer_work_item(ebpf_timer_work_item_t* work_item, uint32_t elaped_microseconds)
{
int64_t due_time;
due_time = -static_cast<int64_t>(elaped_microseconds) * MICROSECONDS_PER_TICK;
SetThreadpoolTimer(
work_item->threadpool_timer,
reinterpret_cast<FILETIME*>(&due_time),
0,
elaped_microseconds / MICROSECONDS_PER_MILLISECOND);
}
void
ebpf_free_timer_work_item(ebpf_timer_work_item_t* work_item)
{
WaitForThreadpoolTimerCallbacks(work_item->threadpool_timer, true);
CloseThreadpoolTimer(work_item->threadpool_timer);
ebpf_free(work_item);
}

Просмотреть файл

@ -135,6 +135,9 @@
<ClInclude Include="ebpf_l2_hook.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libs\epoch\kernel\epoch_kernel.vcxproj">
<Project>{fb2680fb-13cf-400c-8a5d-042c0ac20a3f}</Project>
</ProjectReference>
<ProjectReference Include="..\libs\execution_context\kernel\execution_context_kernel.vcxproj">
<Project>{26e7ed0b-c128-4d7c-a90e-c246def40ad3}</Project>
</ProjectReference>

Просмотреть файл

@ -196,7 +196,7 @@ EbpfCoreInitDriverObjects(
goto Exit;
}
status = ebpf_error_code_to_ntstatus(ebpf_core_initialize());
status = ebpf_error_code_to_ntstatus(ebpf_core_initiate());
if (!NT_SUCCESS(status)) {
goto Exit;
}
@ -262,6 +262,8 @@ EbpfCoreEvtIoDeviceControl(
}
if (input_buffer != NULL) {
size_t minimum_request_size = 0;
size_t minimum_reply_size = 0;
status = ebpf_hook_register_callouts(_wdm_device_object);
// non fatal for now while testing
@ -272,23 +274,13 @@ EbpfCoreEvtIoDeviceControl(
goto Done;
}
if (user_request->id >= sizeof(EbpfProtocolHandlers) / sizeof(EbpfProtocolHandlers[0])) {
status = STATUS_INVALID_PARAMETER;
status = ebpf_error_code_to_ntstatus(ebpf_core_get_protocol_handler_properties(
user_request->id, &minimum_request_size, &minimum_reply_size));
if (status != STATUS_SUCCESS)
goto Done;
}
if (user_request->length < EbpfProtocolHandlers[user_request->id].minimum_request_size) {
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (!EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_no_reply) {
status = STATUS_INVALID_PARAMETER;
goto Done;
}
// Be aware: Input and output buffer point to the same memory.
if (EbpfProtocolHandlers[user_request->id].minimum_reply_size > 0) {
if (minimum_reply_size > 0) {
// Retrieve output buffer associated with the request object
status = WdfRequestRetrieveOutputBuffer(
request, output_buffer_length, &output_buffer, &actual_output_length);
@ -302,21 +294,15 @@ EbpfCoreEvtIoDeviceControl(
goto Done;
}
if (actual_output_length < EbpfProtocolHandlers[user_request->id].minimum_reply_size) {
if (actual_output_length < minimum_reply_size) {
status = STATUS_BUFFER_TOO_SMALL;
goto Done;
}
user_reply = output_buffer;
}
if (EbpfProtocolHandlers[user_request->id].minimum_reply_size == 0) {
status = ebpf_error_code_to_ntstatus(
EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_no_reply(user_request));
} else {
status = ebpf_error_code_to_ntstatus(
EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_with_reply(
user_request, user_reply, (uint16_t)actual_output_length));
}
status = ebpf_error_code_to_ntstatus(ebpf_core_invoke_protocol_handler(
user_request->id, user_request, user_reply, (uint16_t)actual_output_length));
// Fill out the rest of the out buffer after processing the input
// buffer.
@ -362,7 +348,7 @@ DriverEntry(_In_ DRIVER_OBJECT* driver_object, _In_ UNICODE_STRING* registry_pat
ebpf_hook_register_callouts(_wdm_device_object);
// ignore status. at boot, registration can fail.
// we will try to re-register during prog load.
// we will try to re-register during program load.
Exit:

Просмотреть файл

@ -4,10 +4,16 @@
*/
#define CATCH_CONFIG_MAIN
#include "catch2\catch.hpp"
#include <chrono>
#include <mutex>
#include <thread>
#include <WinSock2.h>
#include "catch2\catch.hpp"
#include "ebpf_api.h"
#include "ebpf_core.h"
#include "ebpf_epoch.h"
#include "ebpf_protocol.h"
#include "mock.h"
#include "tlv.h"
@ -19,7 +25,6 @@ namespace ebpf {
}; // namespace ebpf
#include "unwind_helper.h"
#include <WinSock2.h>
ebpf_handle_t
GlueCreateFileW(
@ -70,33 +75,42 @@ GlueDeviceIoControl(
ebpf_operation_header_t* user_reply = nullptr;
*lpBytesReturned = 0;
auto request_id = user_request->id;
if (request_id >= _countof(EbpfProtocolHandlers)) {
size_t minimum_request_size = 0;
size_t minimum_reply_size = 0;
retval = ebpf_core_get_protocol_handler_properties(request_id, &minimum_request_size, &minimum_reply_size);
if (retval != EBPF_ERROR_SUCCESS)
goto Fail;
if (user_request->length < minimum_request_size) {
retval = EBPF_ERROR_INVALID_PARAMETER;
goto Fail;
}
if (user_request->length < EbpfProtocolHandlers[request_id].minimum_request_size) {
goto Fail;
}
if (EbpfProtocolHandlers[request_id].minimum_reply_size > 0) {
if (minimum_reply_size > 0) {
user_reply = reinterpret_cast<decltype(user_reply)>(lpOutBuffer);
if (!user_reply) {
retval = EBPF_ERROR_INVALID_PARAMETER;
goto Fail;
}
if (nOutBufferSize < EbpfProtocolHandlers[request_id].minimum_reply_size) {
if (nOutBufferSize < minimum_reply_size) {
retval = EBPF_ERROR_INVALID_PARAMETER;
goto Fail;
}
user_reply->length = static_cast<uint16_t>(nOutBufferSize);
user_reply->id = user_request->id;
*lpBytesReturned = user_reply->length;
}
if (EbpfProtocolHandlers[request_id].minimum_reply_size == 0) {
retval = EbpfProtocolHandlers[request_id].dispatch.protocol_handler_no_reply(user_request);
} else {
retval = EbpfProtocolHandlers[request_id].dispatch.protocol_handler_with_reply(
user_request, user_reply, static_cast<uint16_t>(nOutBufferSize));
}
retval =
ebpf_core_invoke_protocol_handler(request_id, user_request, user_reply, static_cast<uint16_t>(nOutBufferSize));
if (retval != EBPF_ERROR_SUCCESS)
goto Fail;
return TRUE;
Fail:
if (retval != EBPF_ERROR_SUCCESS) {
switch (retval) {
case EBPF_ERROR_OUT_OF_RESOURCES:
@ -115,13 +129,8 @@ GlueDeviceIoControl(
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
goto Fail;
}
return TRUE;
Fail:
return FALSE;
}
@ -162,7 +171,7 @@ TEST_CASE("droppacket-jit", "[droppacket_jit]")
ebpf_core_terminate();
});
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
ec_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
@ -238,7 +247,7 @@ TEST_CASE("droppacket-interpret", "[droppacket_interpret]")
});
uint32_t result = 0;
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
ec_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
@ -308,7 +317,7 @@ TEST_CASE("enum section", "[enum sections]")
ebpf_core_terminate();
});
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
ec_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
api_initialized = true;
@ -355,7 +364,7 @@ TEST_CASE("verify section", "[verify section]")
ebpf_core_terminate();
});
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
api_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
ec_initialized = true;
@ -437,7 +446,7 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
ebpf_core_terminate();
});
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
ec_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
@ -470,13 +479,13 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
ebpf_handle_t test_handle;
REQUIRE(
ebpf_api_lookup_map(
ebpf_api_get_pinned_map(
reinterpret_cast<const uint8_t*>(process_maps_name.c_str()),
static_cast<uint32_t>(process_maps_name.size()),
&test_handle) == ERROR_SUCCESS);
REQUIRE(test_handle == map_handles[0]);
REQUIRE(
ebpf_api_lookup_map(
ebpf_api_get_pinned_map(
reinterpret_cast<const uint8_t*>(limit_maps_name.c_str()),
static_cast<uint32_t>(limit_maps_name.size()),
&test_handle) == ERROR_SUCCESS);
@ -491,12 +500,12 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
reinterpret_cast<const uint8_t*>(limit_maps_name.c_str()), static_cast<uint32_t>(limit_maps_name.size())) ==
ERROR_SUCCESS);
REQUIRE(
ebpf_api_lookup_map(
ebpf_api_get_pinned_map(
reinterpret_cast<const uint8_t*>(process_maps_name.c_str()),
static_cast<uint32_t>(process_maps_name.size()),
&test_handle) == ERROR_NOT_FOUND);
REQUIRE(
ebpf_api_lookup_map(
ebpf_api_get_pinned_map(
reinterpret_cast<const uint8_t*>(limit_maps_name.c_str()),
static_cast<uint32_t>(limit_maps_name.size()),
&test_handle) == ERROR_NOT_FOUND);
@ -583,7 +592,7 @@ TEST_CASE("enumerate_and_query_programs", "[enumerate_and_query_programs]")
ebpf_api_free_string(section_name);
});
REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS);
REQUIRE(ebpf_core_initiate() == EBPF_ERROR_SUCCESS);
ec_initialized = true;
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
@ -634,3 +643,48 @@ TEST_CASE("enumerate_and_query_programs", "[enumerate_and_query_programs]")
REQUIRE(ebpf_api_get_next_program(program_handle, &program_handle) == ERROR_SUCCESS);
REQUIRE(program_handle == INVALID_HANDLE_VALUE);
}
TEST_CASE("epoch_test_single_epoch", "[epoch_test_single_epoch]")
{
bool ep_initialized = false;
_unwind_helper on_exit([&] {
if (ep_initialized)
ebpf_epoch_terminate();
});
REQUIRE(ebpf_epoch_initiate() == EBPF_ERROR_SUCCESS);
ep_initialized = true;
REQUIRE(ebpf_epoch_enter() == EBPF_ERROR_SUCCESS);
void* memory = ebpf_epoch_allocate(10, EBPF_MEMORY_NO_EXECUTE);
ebpf_epoch_free(memory);
ebpf_epoch_exit();
ebpf_epoch_flush();
}
TEST_CASE("epoch_test_two_threads", "[epoch_test_two_threads]")
{
bool ep_initialized = false;
_unwind_helper on_exit([&] {
if (ep_initialized)
ebpf_epoch_terminate();
});
REQUIRE(ebpf_epoch_initiate() == EBPF_ERROR_SUCCESS);
ep_initialized = true;
auto epoch = []() {
ebpf_epoch_enter();
void* memory = ebpf_epoch_allocate(10, EBPF_MEMORY_NO_EXECUTE);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
ebpf_epoch_free(memory);
ebpf_epoch_exit();
ebpf_epoch_flush();
};
std::thread thread_1(epoch);
std::thread thread_2(epoch);
thread_1.join();
thread_2.join();
}

Просмотреть файл

@ -112,6 +112,9 @@
<ProjectReference Include="..\..\ebpf\libs\api\api.vcxproj">
<Project>{c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}</Project>
</ProjectReference>
<ProjectReference Include="..\..\ebpf\libs\epoch\user\epoch_user.vcxproj">
<Project>{a7e21439-b561-43f0-9ddd-237425f42bcd}</Project>
</ProjectReference>
<ProjectReference Include="..\..\ebpf\libs\execution_context\user\execution_context_user.vcxproj">
<Project>{18127b0d-8381-4afe-9a3a-cf53241992d3}</Project>
</ProjectReference>

Просмотреть файл

@ -10,69 +10,71 @@
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, const char **argv) {
WSAData data;
int
main(int argc, const char** argv)
{
WSAData data;
if (argc != 2) {
printf("Usage: %s target_ip\n", argv[0]);
return 1;
}
if (argc != 2) {
printf("Usage: %s target_ip\n", argv[0]);
return 1;
}
if (WSAStartup(2, &data) != 0) {
printf("WSAStartup failed\n");
return 1;
}
if (WSAStartup(2, &data) != 0) {
printf("WSAStartup failed\n");
return 1;
}
unsigned short us = 0x1234;
us = us >> 8 | us << 8;
printf("%.2X\n", us);
Sleep(10000);
unsigned short us = 0x1234;
us = us >> 8 | us << 8;
printf("%.2X\n", us);
Sleep(10000);
auto socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, nullptr, 0, 0);
if (socket == INVALID_SOCKET) {
printf("WSASocket failed\n");
return 1;
}
ADDRINFOA *addrinfo = nullptr;
auto socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, nullptr, 0, 0);
if (socket == INVALID_SOCKET) {
printf("WSASocket failed\n");
return 1;
}
ADDRINFOA* addrinfo = nullptr;
if (getaddrinfo(argv[1], "53", nullptr, &addrinfo) != 0) {
printf("getaddrinfo failed \n");
return 1;
}
if (getaddrinfo(argv[1], "53", nullptr, &addrinfo) != 0) {
printf("getaddrinfo failed \n");
return 1;
}
if (connect(socket, addrinfo->ai_addr,
static_cast<int>(addrinfo->ai_addrlen)) != 0) {
printf("connect failed \n");
return 1;
}
if (connect(socket, addrinfo->ai_addr, static_cast<int>(addrinfo->ai_addrlen)) != 0) {
printf("connect failed \n");
return 1;
}
std::vector<WSABUF> buffers(1024);
char a = 'A';
for (auto &b : buffers) {
b.buf = &a;
b.len = 0;
}
DWORD bytes_sent;
std::vector<WSABUF> buffers(1024);
char a = 'A';
for (auto& b : buffers) {
b.buf = &a;
b.len = 0;
}
DWORD bytes_sent;
volatile long packet_sent = 0;
std::vector<std::thread> threads(4);
volatile long packet_sent = 0;
std::vector<std::thread> threads(4);
for (auto &t : threads) {
t = std::thread([&] {
for (;;) {
if (WSASend(socket, buffers.data(), static_cast<DWORD>(buffers.size()),
&bytes_sent, 0, nullptr, nullptr) != 0) {
printf("WSASend failed\n");
return 1;
}
InterlockedAdd(&packet_sent, static_cast<LONG>(buffers.size()));
}
});
}
for (auto& t : threads) {
t = std::thread([&] {
for (;;) {
if (WSASend(
socket, buffers.data(), static_cast<DWORD>(buffers.size()), &bytes_sent, 0, nullptr, nullptr) !=
0) {
printf("WSASend failed\n");
return 1;
}
InterlockedAdd(&packet_sent, static_cast<long>(buffers.size()));
}
});
}
for (;;) {
long old = packet_sent;
Sleep(1000);
printf("%d\n", packet_sent - old);
}
for (;;) {
long old = packet_sent;
Sleep(1000);
printf("%d\n", packet_sent - old);
}
}

Просмотреть файл

@ -70,7 +70,7 @@ stats(int argc, char** argv)
uint64_t pid;
process_entry_t process_entry;
result = ebpf_api_lookup_map(process_map, sizeof(process_map), &map);
result = ebpf_api_get_pinned_map(process_map, sizeof(process_map), &map);
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to look up eBPF map: %d\n", result);
return 1;
@ -111,7 +111,7 @@ limit(int argc, char** argv)
uint32_t result;
uint32_t key = 0;
result = ebpf_api_lookup_map(limits_map, sizeof(limits_map), &map);
result = ebpf_api_get_pinned_map(limits_map, sizeof(limits_map), &map);
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to look up eBPF map: %d\n", result);
return 1;