Remove allocations from executable memory pool (#251)

* Remove allocations from executable memory pool

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Add direction to doxygen

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Clarify use of 4096 as page size

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* PR feedback

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2021-06-07 14:07:24 -06:00 коммит произвёл GitHub
Родитель c059112b78
Коммит 7e033f0200
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 239 добавлений и 138 удалений

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

@ -62,9 +62,8 @@ ebpf_core_initiate()
if (return_value != EBPF_SUCCESS)
goto Done;
_ebpf_global_helper_function_dispatch_table = ebpf_allocate(
EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function) + sizeof(_ebpf_program_helpers),
EBPF_MEMORY_NO_EXECUTE);
_ebpf_global_helper_function_dispatch_table =
ebpf_allocate(EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function) + sizeof(_ebpf_program_helpers));
if (!_ebpf_global_helper_function_dispatch_table) {
return_value = EBPF_NO_MEMORY;
goto Done;

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

@ -46,7 +46,7 @@ _ebpf_link_free(ebpf_object_t* object)
ebpf_result_t
ebpf_link_create(ebpf_link_t** link)
{
*link = ebpf_epoch_allocate(sizeof(ebpf_link_t), EBPF_MEMORY_NO_EXECUTE);
*link = ebpf_epoch_allocate(sizeof(ebpf_link_t));
if (*link == NULL)
return EBPF_NO_MEMORY;
@ -65,7 +65,7 @@ ebpf_link_initialize(
ebpf_safe_size_t_add(sizeof(ebpf_extension_data_t), context_data_length, &client_data_length);
link->client_data = ebpf_allocate(client_data_length, EBPF_MEMORY_NO_EXECUTE);
link->client_data = ebpf_allocate(client_data_length);
if (!link->client_data)
return EBPF_NO_MEMORY;

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

@ -102,7 +102,7 @@ ebpf_create_array_map(_In_ const ebpf_map_definition_t* map_definition)
}
// allocate
map = ebpf_allocate(map_entry_size, EBPF_MEMORY_NO_EXECUTE);
map = ebpf_allocate(map_entry_size);
if (map == NULL) {
goto Done;
}
@ -198,7 +198,7 @@ ebpf_create_hash_map(_In_ const ebpf_map_definition_t* map_definition)
size_t map_size = sizeof(ebpf_core_map_t);
ebpf_core_map_t* map = NULL;
map = ebpf_allocate(map_size, EBPF_MEMORY_NO_EXECUTE);
map = ebpf_allocate(map_size);
if (map == NULL) {
retval = EBPF_NO_MEMORY;
goto Done;

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

@ -46,8 +46,7 @@ typedef struct _ebpf_program
const ebpf_extension_dispatch_table_t* program_information_provider_dispatch_table;
bool program_invalidated;
size_t trampoline_entry_count;
ebpf_trampoline_entry_t* trampoline_entries;
ebpf_trampoline_table_t* trampoline_table;
ebpf_epoch_work_item_t* cleanup_work_item;
} ebpf_program_t;
@ -63,13 +62,26 @@ _ebpf_program_program_information_provider_changed(
ebpf_program_t* program = (ebpf_program_t*)client_binding_context;
if (program->program_information_provider_dispatch_table != NULL) {
size_t function_count = (program->program_information_provider_dispatch_table->size -
EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function)) /
sizeof(program->program_information_provider_dispatch_table->function[0]);
if (provider_dispatch_table == NULL) {
program->program_invalidated = true;
return;
}
return_value = ebpf_build_trampoline_table(
&program->trampoline_entry_count, &program->trampoline_entries, provider_dispatch_table);
if (!program->trampoline_table) {
return_value = ebpf_allocate_trampoline_table(function_count, &program->trampoline_table);
if (return_value != EBPF_SUCCESS) {
program->program_invalidated = true;
return;
}
}
return_value = ebpf_update_trampoline_table(
program->trampoline_table, program->program_information_provider_dispatch_table);
if (return_value != EBPF_SUCCESS) {
program->program_invalidated = true;
return;
@ -132,6 +144,8 @@ _ebpf_program_epoch_free(void* context)
ebpf_free(program->maps);
ebpf_free_trampoline_table(program->trampoline_table);
ebpf_free(program->cleanup_work_item);
ebpf_free(program);
}
@ -180,7 +194,7 @@ ebpf_program_create(ebpf_program_t** program)
ebpf_result_t retval;
ebpf_program_t* local_program;
local_program = (ebpf_program_t*)ebpf_allocate(sizeof(ebpf_program_t), EBPF_MEMORY_NO_EXECUTE);
local_program = (ebpf_program_t*)ebpf_allocate(sizeof(ebpf_program_t));
if (!local_program) {
retval = EBPF_NO_MEMORY;
goto Done;
@ -260,7 +274,7 @@ ebpf_result_t
ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, size_t maps_count)
{
size_t index;
program->maps = ebpf_allocate(maps_count * sizeof(ebpf_map_t*), EBPF_MEMORY_NO_EXECUTE);
program->maps = ebpf_allocate(maps_count * sizeof(ebpf_map_t*));
if (!program->maps)
return EBPF_NO_MEMORY;
@ -398,11 +412,14 @@ ebpf_program_get_helper_function_address(const ebpf_program_t* program, uint32_t
EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function)) /
sizeof(program->global_helper_provider_dispatch_table->function);
if (helper_function_id > EBPF_MAX_GLOBAL_HELPER_FUNCTION) {
void* function_address;
ebpf_result_t return_value;
helper_function_id >>= 16;
if ((program->trampoline_entries == NULL) || (helper_function_id > program->trampoline_entry_count))
return EBPF_INVALID_ARGUMENT;
return_value = ebpf_get_trampoline_function(program->trampoline_table, helper_function_id, &function_address);
if (return_value != EBPF_SUCCESS)
return return_value;
*address = (uint64_t)(program->trampoline_entries + helper_function_id);
*address = (uint64_t)function_address;
} else {
if (helper_function_id > count) {
return EBPF_INVALID_ARGUMENT;

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

@ -12,6 +12,8 @@
#include "ebpf_program.h"
#include "helpers.h"
#define PAGE_SIZE 4096
class _ebpf_core_initializer
{
public:
@ -155,14 +157,21 @@ TEST_CASE("program")
REQUIRE(ebpf_program_associate_maps(program.get(), maps, EBPF_COUNT_OF(maps)) == EBPF_SUCCESS);
REQUIRE(((ebpf_object_t*)map.get())->reference_count == 2);
ebpf_trampoline_entry_t machine_code;
machine_code.load_rax = 0xa148;
machine_code.indirect_address = &machine_code.address;
machine_code.jmp_rax = 0xe0ff;
machine_code.address = (void*)test_function;
ebpf_trampoline_table_t* table = NULL;
ebpf_result_t (*test_function)();
auto provider_function1 = []() { return (ebpf_result_t)TEST_FUNCTION_RETURN; };
ebpf_extension_dispatch_table_t provider_dispatch_table1 = {
0, sizeof(ebpf_extension_dispatch_table_t), provider_function1};
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
REQUIRE(ebpf_update_trampoline_table(table, &provider_dispatch_table1) == EBPF_SUCCESS);
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
// Size of the actual function is unknown, but we know the allocation is on page granularity.
REQUIRE(
ebpf_program_load_machine_code(program.get(), (uint8_t*)&machine_code, sizeof(machine_code)) == EBPF_SUCCESS);
ebpf_program_load_machine_code(program.get(), reinterpret_cast<uint8_t*>(test_function), PAGE_SIZE) ==
EBPF_SUCCESS);
uint32_t result = 0;
ebpf_program_invoke(program.get(), nullptr, &result);
REQUIRE(result == TEST_FUNCTION_RETURN);
@ -174,4 +183,5 @@ TEST_CASE("program")
REQUIRE(address == 0);
REQUIRE(ebpf_program_get_helper_function_address(program.get(), 0xFFFF, &address) == EBPF_INVALID_ARGUMENT);
REQUIRE(address == 0);
ebpf_free_trampoline_table(table);
}

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

@ -124,8 +124,7 @@ ebpf_epoch_initiate()
if (ebpf_is_non_preemptible_work_item_supported()) {
ebpf_get_cpu_count(&_ebpf_epoch_cpu_table_size);
_ebpf_epoch_cpu_table =
ebpf_allocate(_ebpf_epoch_cpu_table_size * sizeof(ebpf_epoch_cpu_entry_t), EBPF_MEMORY_NO_EXECUTE);
_ebpf_epoch_cpu_table = ebpf_allocate(_ebpf_epoch_cpu_table_size * sizeof(ebpf_epoch_cpu_entry_t));
if (!_ebpf_epoch_cpu_table) {
return_value = EBPF_NO_MEMORY;
goto Error;
@ -270,11 +269,11 @@ ebpf_epoch_flush()
}
void*
ebpf_epoch_allocate(size_t size, ebpf_memory_type_t type)
ebpf_epoch_allocate(size_t size)
{
ebpf_epoch_allocation_header_t* header;
size += sizeof(ebpf_epoch_allocation_header_t);
header = (ebpf_epoch_allocation_header_t*)ebpf_allocate(size, type);
header = (ebpf_epoch_allocation_header_t*)ebpf_allocate(size);
if (header)
header++;
@ -409,7 +408,7 @@ _ebpf_flush_worker(void* context)
ebpf_epoch_work_item_t*
ebpf_epoch_allocate_work_item(void* callback_context, void (*callback)(void* context))
{
ebpf_epoch_work_item_t* work_item = ebpf_allocate(sizeof(ebpf_epoch_work_item_t), EBPF_MEMORY_NO_EXECUTE);
ebpf_epoch_work_item_t* work_item = ebpf_allocate(sizeof(ebpf_epoch_work_item_t));
if (!work_item) {
return NULL;
}

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

@ -48,11 +48,10 @@ extern "C"
/**
* @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);
ebpf_epoch_allocate(size_t size);
/**
* @brief Free memory under epoch control.

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

@ -10,7 +10,7 @@ struct _ebpf_hash_table
ebpf_hash_table_compare_result_t (*compare_function)(const uint8_t* key1, const uint8_t* key2);
size_t key_size;
size_t value_size;
void* (*allocate)(size_t size, ebpf_memory_type_t type);
void* (*allocate)(size_t size);
void (*free)(void* memory);
};
@ -42,7 +42,7 @@ static void*
_ebpf_hash_table_allocate(struct _RTL_AVL_TABLE* avl_table, unsigned long byte_size)
{
ebpf_hash_table_t* table = (ebpf_hash_table_t*)avl_table;
return table->allocate(byte_size, EBPF_MEMORY_NO_EXECUTE);
return table->allocate(byte_size);
}
static void
@ -55,7 +55,7 @@ _ebpf_hash_table_free(struct _RTL_AVL_TABLE* avl_table, void* buffer)
ebpf_result_t
ebpf_hash_table_create(
ebpf_hash_table_t** hash_table,
void* (*allocate)(size_t size, ebpf_memory_type_t type),
void* (*allocate)(size_t size),
void (*free)(void* memory),
size_t key_size,
size_t value_size,
@ -65,7 +65,7 @@ ebpf_hash_table_create(
ebpf_hash_table_t* table = NULL;
// allocate
table = ebpf_allocate(sizeof(ebpf_hash_table_t), EBPF_MEMORY_NO_EXECUTE);
table = ebpf_allocate(sizeof(ebpf_hash_table_t));
if (table == NULL) {
retval = EBPF_NO_MEMORY;
goto Done;
@ -134,7 +134,7 @@ ebpf_hash_table_update(ebpf_hash_table_t* hash_table, const uint8_t* key, const
goto Done;
}
temp = ebpf_allocate(temp_size, EBPF_MEMORY_NO_EXECUTE);
temp = ebpf_allocate(temp_size);
if (!temp) {
retval = EBPF_NO_MEMORY;
goto Done;

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

@ -114,7 +114,7 @@ ebpf_duplicate_utf8_string(ebpf_utf8_string_t* destination, const ebpf_utf8_stri
destination->length = 0;
return EBPF_SUCCESS;
} else {
destination->value = ebpf_allocate(source->length, EBPF_MEMORY_NO_EXECUTE);
destination->value = ebpf_allocate(source->length);
if (!destination->value)
return EBPF_NO_MEMORY;
memcpy(destination->value, source->value, source->length);

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

@ -54,7 +54,7 @@ ebpf_result_t
ebpf_pinning_table_allocate(ebpf_pinning_table_t** pinning_table)
{
ebpf_result_t return_value;
*pinning_table = ebpf_allocate(sizeof(ebpf_pinning_table_t), EBPF_MEMORY_NO_EXECUTE);
*pinning_table = ebpf_allocate(sizeof(ebpf_pinning_table_t));
if (*pinning_table == NULL) {
return_value = EBPF_NO_MEMORY;
goto Done;
@ -115,7 +115,7 @@ ebpf_pinning_table_insert(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_s
const ebpf_utf8_string_t* existing_key = name;
ebpf_pinning_entry_t** existing_pinning_entry;
new_pinning_entry = ebpf_allocate(sizeof(ebpf_pinning_entry_t), EBPF_MEMORY_NO_EXECUTE);
new_pinning_entry = ebpf_allocate(sizeof(ebpf_pinning_entry_t));
if (!new_pinning_entry) {
return_value = EBPF_NO_MEMORY;
goto Done;

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

@ -41,12 +41,6 @@ extern "C"
size_t length;
} ebpf_utf8_string_t;
typedef enum _ebpf_memory_type
{
EBPF_MEMORY_NO_EXECUTE = 0,
EBPF_MEMORY_EXECUTE = 1,
} ebpf_memory_type_t;
typedef enum _ebpf_code_integrity_state
{
EBPF_CODE_INTEGRITY_DEFAULT = 0,
@ -72,16 +66,7 @@ extern "C"
uint8_t data[1];
} ebpf_extension_data_t;
#pragma pack(push)
#pragma pack(1)
typedef struct _ebpf_trampoline_entry
{
uint16_t load_rax;
void* indirect_address;
uint16_t jmp_rax;
void* address;
} ebpf_trampoline_entry_t;
#pragma pack(pop)
typedef struct _ebpf_trampoline_table ebpf_trampoline_table_t;
#define EBPF_LOCK_SIZE sizeof(uint64_t)
#define EBPF_LOCK_STATE_SIZE sizeof(uint64_t)
@ -111,11 +96,10 @@ extern "C"
/**
* @brief Allocate memory.
* @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_allocate(size_t size, ebpf_memory_type_t type);
ebpf_allocate(size_t size);
/**
* @brief Free memory.
@ -395,7 +379,7 @@ extern "C"
ebpf_result_t
ebpf_hash_table_create(
ebpf_hash_table_t** hash_table,
void* (*allocate)(size_t size, ebpf_memory_type_t type),
void* (*allocate)(size_t size),
void (*free)(void* memory),
size_t key_size,
size_t value_size,
@ -623,26 +607,52 @@ extern "C"
ebpf_log_function(void* context, const char* format_string, ...);
/**
* @brief Create or update a table of ebpf_trampoline_entry_t with
* trampoline functions to allow for relocation of functions in the
* dispatch table.
* @brief Allocate a new empty trampoline table of entry_count size.
*
* @param[in,out] entry_count Size of the ebpf_trampoline_entry_t table.
* @param[in,out] entries Block of memory that contains the trampoline
* functions on success.
* @param[in] dispatch_table Dispatch table to build trampoline functions for.
* @retval EBPF_SUCCESS ebpf_trampoline_entry_t table successfully
* populated.
* @retval EBPF_ERROR_EXTENSION_FAILED_TO_LOAD Unable to populate
* ebpf_trampoline_entry_t table.
* @param[in] entry_count Maximum number of functions to build trampolines for.
* @param[out] trampoline_table Pointer to memory that holds the trampoline
* table on success.
* @retval EBPF_SUCCESS The operation was successful.
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
* operation.
* @retval EBPF_NOT_SUPPORTED This operation is not supported on this
* platform.
*/
ebpf_result_t
ebpf_build_trampoline_table(
size_t* entry_count, ebpf_trampoline_entry_t** entries, const ebpf_extension_dispatch_table_t* dispatch_table);
ebpf_allocate_trampoline_table(size_t entry_count, ebpf_trampoline_table_t** trampoline_table);
/**
* @brief Free a previously allocated trampoline table.
*
* @param[in] trampoline_table Pointer to trampoline table to free.
*/
void
ebpf_free_trampoline_table(ebpf_trampoline_table_t* trampoline_table);
/**
* @brief Populate the function pointers in a trampoline table.
*
* @param[in] trampoline_table Trampoline table to populate.
* @param[in] dispatch_table Dispatch table to populate from.
* @retval EBPF_SUCCESS The operation was successful.
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
* operation.
*/
ebpf_result_t
ebpf_update_trampoline_table(
ebpf_trampoline_table_t* trampoline_table, const ebpf_extension_dispatch_table_t* dispatch_table);
/**
* @brief Get the address of a trampoline function.
*
* @param[in] trampoline_table Trampoline table to query.
* @param[in] index Index of function to get.
* @param[out] function Pointer to memory that contains the function on success.
* @retval EBPF_SUCCESS The operation was successful.
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
* operation.
* @retval EBPF_INVALID_ARGUMENT An invalid argument was supplied.
*/
ebpf_result_t
ebpf_get_trampoline_function(const ebpf_trampoline_table_t* trampoline_table, size_t index, void** function);
typedef struct _ebpf_program_information ebpf_program_information_t;

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

@ -41,7 +41,7 @@ ebpf_program_information_decode(
goto Done;
}
local_buffer = ebpf_allocate(buffer_size, EBPF_MEMORY_NO_EXECUTE);
local_buffer = ebpf_allocate(buffer_size);
if (!local_buffer) {
return_value = EBPF_NO_MEMORY;
goto Done;
@ -77,7 +77,7 @@ Done:
void* __RPC_USER
MIDL_user_allocate(size_t size)
{
return ebpf_allocate(size, EBPF_MEMORY_NO_EXECUTE);
return ebpf_allocate(size);
}
void __RPC_USER

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

@ -6,42 +6,125 @@
#include "ebpf_platform.h"
#include "ebpf_epoch.h"
#pragma pack(push)
#pragma pack(1)
typedef struct _ebpf_trampoline_entry
{
uint16_t load_rax;
void* indirect_address;
uint16_t jmp_rax;
void* address;
} ebpf_trampoline_entry_t;
#pragma pack(pop)
typedef struct _ebpf_trampoline_table
{
ebpf_memory_descriptor_t* memory_descriptor;
size_t entry_count;
} ebpf_trampoline_table_t;
ebpf_result_t
ebpf_build_trampoline_table(
size_t* entry_count, ebpf_trampoline_entry_t** entries, const ebpf_extension_dispatch_table_t* dispatch_table)
ebpf_allocate_trampoline_table(size_t entry_count, ebpf_trampoline_table_t** trampoline_table)
{
ebpf_result_t return_value;
ebpf_trampoline_table_t* local_trampoline_table = NULL;
local_trampoline_table = ebpf_allocate(sizeof(ebpf_trampoline_table_t));
if (!local_trampoline_table) {
return_value = EBPF_NO_MEMORY;
goto Exit;
}
local_trampoline_table->entry_count = entry_count;
local_trampoline_table->memory_descriptor = ebpf_map_memory(entry_count * sizeof(ebpf_trampoline_entry_t));
if (!local_trampoline_table->memory_descriptor) {
return_value = EBPF_NO_MEMORY;
goto Exit;
}
*trampoline_table = local_trampoline_table;
local_trampoline_table = NULL;
return_value = EBPF_SUCCESS;
Exit:
ebpf_free_trampoline_table(local_trampoline_table);
return return_value;
}
void
ebpf_free_trampoline_table(ebpf_trampoline_table_t* trampoline_table)
{
if (trampoline_table) {
ebpf_unmap_memory(trampoline_table->memory_descriptor);
ebpf_free(trampoline_table);
}
}
ebpf_result_t
ebpf_update_trampoline_table(
ebpf_trampoline_table_t* trampoline_table, const ebpf_extension_dispatch_table_t* dispatch_table)
{
#if defined(_AMD64_)
size_t function_count = (dispatch_table->size - EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function)) /
sizeof(dispatch_table->function[0]);
ebpf_trampoline_entry_t* local_entries = *entries;
size_t local_entry_count = *entry_count;
ebpf_trampoline_entry_t* local_entries;
ebpf_result_t return_value;
// If there is no existing table, allocate a new table.
if (local_entries == NULL) {
local_entry_count = function_count;
local_entries = ebpf_epoch_allocate(local_entry_count * sizeof(ebpf_trampoline_entry_t), EBPF_MEMORY_EXECUTE);
if (local_entries == NULL)
return EBPF_NO_MEMORY;
} else {
// Verify the existing table is the correct size
if (local_entry_count != function_count)
return EBPF_ERROR_EXTENSION_FAILED_TO_LOAD;
if (function_count != trampoline_table->entry_count) {
return_value = EBPF_INVALID_ARGUMENT;
goto Exit;
}
return_value = ebpf_protect_memory(trampoline_table->memory_descriptor, EBPF_PAGE_PROTECT_READ_WRITE);
if (return_value != EBPF_SUCCESS) {
goto Exit;
}
local_entries =
(ebpf_trampoline_entry_t*)ebpf_memory_descriptor_get_base_address(trampoline_table->memory_descriptor);
if (!local_entries) {
return_value = EBPF_NO_MEMORY;
goto Exit;
}
size_t index;
for (index = 0; index < local_entry_count; index++) {
for (index = 0; index < trampoline_table->entry_count; index++) {
local_entries[index].load_rax = 0xa148;
local_entries[index].indirect_address = &local_entries[index].address;
local_entries[index].jmp_rax = 0xe0ff;
local_entries[index].address = (void*)dispatch_table->function[index];
}
*entry_count = local_entry_count;
*entries = local_entries;
return EBPF_SUCCESS;
Exit:
return_value = ebpf_protect_memory(trampoline_table->memory_descriptor, EBPF_PAGE_PROTECT_READ_EXECUTE);
return return_value;
#elif
UNREFERENCED_PARAMETER(entry_count);
UNREFERENCED_PARAMETER(ebpf_trampoline_entry_t);
UNREFERENCED_PARAMETER(trampoline_table);
UNREFERENCED_PARAMETER(dispatch_table);
return EBPF_ERROR_NOT_SUPPORTED;
#endif
}
ebpf_result_t
ebpf_get_trampoline_function(const ebpf_trampoline_table_t* trampoline_table, size_t index, void** function)
{
ebpf_trampoline_entry_t* local_entries;
ebpf_result_t return_value;
if (index >= trampoline_table->entry_count) {
return_value = EBPF_INVALID_ARGUMENT;
goto Exit;
}
local_entries =
(ebpf_trampoline_entry_t*)ebpf_memory_descriptor_get_base_address(trampoline_table->memory_descriptor);
if (!local_entries) {
return_value = EBPF_NO_MEMORY;
goto Exit;
}
*function = &(local_entries[index]);
return_value = EBPF_SUCCESS;
Exit:
return return_value;
}

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

@ -129,7 +129,7 @@ ebpf_extension_load(
NPI_REGISTRATION_INSTANCE* client_registration_instance;
NTSTATUS status;
local_client_context = ebpf_allocate(sizeof(ebpf_extension_client_t), EBPF_MEMORY_NO_EXECUTE);
local_client_context = ebpf_allocate(sizeof(ebpf_extension_client_t));
if (!local_client_context) {
return_value = EBPF_NO_MEMORY;
@ -231,8 +231,8 @@ _ebpf_extension_provider_attach_client(
goto Done;
}
local_provider_binding_context = (ebpf_extension_provider_binding_context*)ebpf_allocate(
sizeof(ebpf_extension_provider_binding_context), EBPF_MEMORY_NO_EXECUTE);
local_provider_binding_context =
(ebpf_extension_provider_binding_context*)ebpf_allocate(sizeof(ebpf_extension_provider_binding_context));
if (!local_provider_binding_context) {
status = STATUS_NOINTERFACE;
@ -303,7 +303,7 @@ ebpf_provider_load(
NPI_REGISTRATION_INSTANCE* provider_registration_instance;
NTSTATUS status;
local_provider_context = ebpf_allocate(sizeof(ebpf_extension_provider_t), EBPF_MEMORY_NO_EXECUTE);
local_provider_context = ebpf_allocate(sizeof(ebpf_extension_provider_t));
if (!local_provider_context) {
return_value = EBPF_NO_MEMORY;

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

@ -31,10 +31,9 @@ ebpf_platform_terminate()
{}
void*
ebpf_allocate(size_t size, ebpf_memory_type_t type)
ebpf_allocate(size_t size)
{
return ExAllocatePool2(
type == EBPF_MEMORY_EXECUTE ? POOL_FLAG_NON_PAGED_EXECUTE : POOL_FLAG_NON_PAGED, size, EBPF_POOL_TAG);
return ExAllocatePool2(POOL_FLAG_NON_PAGED, size, EBPF_POOL_TAG);
}
void
@ -266,7 +265,7 @@ ebpf_allocate_non_preemptible_work_item(
void (*work_item_routine)(void* work_item_context, void* parameter_1),
void* work_item_context)
{
*work_item = ebpf_allocate(sizeof(ebpf_non_preemptible_work_item_t), EBPF_MEMORY_NO_EXECUTE);
*work_item = ebpf_allocate(sizeof(ebpf_non_preemptible_work_item_t));
if (*work_item == NULL) {
return EBPF_NO_MEMORY;
}
@ -318,7 +317,7 @@ ebpf_allocate_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);
*timer_work_item = ebpf_allocate(sizeof(ebpf_timer_work_item_t));
if (*timer_work_item == NULL)
return EBPF_NO_MEMORY;

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

@ -93,7 +93,7 @@ TEST_CASE("epoch_test_single_epoch", "[epoch_test_single_epoch]")
_test_helper test_helper;
REQUIRE(ebpf_epoch_enter() == EBPF_SUCCESS);
void* memory = ebpf_epoch_allocate(10, EBPF_MEMORY_NO_EXECUTE);
void* memory = ebpf_epoch_allocate(10);
ebpf_epoch_free(memory);
ebpf_epoch_exit();
ebpf_epoch_flush();
@ -105,7 +105,7 @@ TEST_CASE("epoch_test_two_threads", "[epoch_test_two_threads]")
auto epoch = []() {
ebpf_epoch_enter();
void* memory = ebpf_epoch_allocate(10, EBPF_MEMORY_NO_EXECUTE);
void* memory = ebpf_epoch_allocate(10);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
ebpf_epoch_free(memory);
@ -194,7 +194,7 @@ TEST_CASE("trampoline_test", "[trampoline_test]")
_test_helper test_helper;
size_t count = 0;
ebpf_trampoline_entry_t* table = NULL;
ebpf_trampoline_table_t* table = NULL;
ebpf_result_t (*test_function)();
auto provider_function1 = []() { return EBPF_SUCCESS; };
auto provider_function2 = []() { return EBPF_OBJECT_ALREADY_EXISTS; };
@ -204,19 +204,18 @@ TEST_CASE("trampoline_test", "[trampoline_test]")
ebpf_extension_dispatch_table_t provider_dispatch_table2 = {
0, sizeof(ebpf_extension_dispatch_table_t), provider_function2};
REQUIRE(ebpf_epoch_initiate() == EBPF_SUCCESS);
REQUIRE(ebpf_build_trampoline_table(&count, &table, &provider_dispatch_table1) == EBPF_SUCCESS);
test_function = reinterpret_cast<decltype(test_function)>(table);
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
REQUIRE(ebpf_update_trampoline_table(table, &provider_dispatch_table1) == EBPF_SUCCESS);
REQUIRE(ebpf_get_trampoline_function(table, 0, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
// Verify that the trampoline function invokes the provider function
REQUIRE(test_function() == EBPF_SUCCESS);
REQUIRE(ebpf_build_trampoline_table(&count, &table, &provider_dispatch_table2) == EBPF_SUCCESS);
REQUIRE(ebpf_update_trampoline_table(table, &provider_dispatch_table2) == EBPF_SUCCESS);
// Verify that the trampoline function now invokes the new provider function
REQUIRE(test_function() == EBPF_OBJECT_ALREADY_EXISTS);
ebpf_epoch_free(table);
ebpf_epoch_terminate();
ebpf_free_trampoline_table(table);
}
TEST_CASE("program_type_info", "[program_type_info]")

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

@ -55,7 +55,7 @@ ebpf_extension_load(
goto Done;
}
local_extension_client = ebpf_allocate(sizeof(ebpf_extension_client_t), EBPF_MEMORY_NO_EXECUTE);
local_extension_client = ebpf_allocate(sizeof(ebpf_extension_client_t));
if (!local_extension_client) {
return_value = EBPF_NO_MEMORY;
goto Done;
@ -180,7 +180,7 @@ ebpf_provider_load(
goto Done;
}
local_extension_provider = ebpf_allocate(sizeof(ebpf_extension_provider_t), EBPF_MEMORY_NO_EXECUTE);
local_extension_provider = ebpf_allocate(sizeof(ebpf_extension_provider_t));
if (!local_extension_provider) {
return_value = EBPF_NO_MEMORY;
goto Done;

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

@ -13,8 +13,6 @@
#include <stdint.h>
#include <vector>
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;
@ -108,29 +106,17 @@ ebpf_get_code_integrity_state(ebpf_code_integrity_state_t* state)
}
void*
ebpf_allocate(size_t size, ebpf_memory_type_t type)
ebpf_allocate(size_t size)
{
void* memory;
if (type == EBPF_MEMORY_EXECUTE) {
memory = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (memory) {
_executable_segments.insert({reinterpret_cast<uint64_t>(memory)});
}
return memory;
} else {
return malloc(size);
}
return calloc(size, 1);
}
void
ebpf_free(void* memory)
{
if (_executable_segments.find(reinterpret_cast<uint64_t>(memory)) != _executable_segments.end()) {
VirtualFree(memory, 0, MEM_RELEASE);
} else {
free(memory);
}
free(memory);
}
struct _ebpf_memory_descriptor
{
void* base;
@ -347,7 +333,7 @@ ebpf_result_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);
*work_item = (ebpf_timer_work_item_t*)ebpf_allocate(sizeof(ebpf_timer_work_item_t));
if (*work_item == NULL)
goto Error;

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

@ -16,8 +16,8 @@
#include <stdlib.h>
#define malloc(X) ebpf_allocate((X), EBPF_MEMORY_NO_EXECUTE)
#define calloc(X, Y) ebpf_allocate((X) * (Y), EBPF_MEMORY_NO_EXECUTE)
#define malloc(X) ebpf_allocate((X))
#define calloc(X, Y) ebpf_allocate((X) * (Y))
#define free(X) ebpf_free(X)
#include <endian.h>

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

@ -705,8 +705,8 @@ _net_ebpf_ext_program_information_encode_xdp()
const uint8_t* buffer = _ebpf_encoded_xdp_program_information_data;
unsigned long buffer_size = sizeof(_ebpf_encoded_xdp_program_information_data);
_ebpf_xdp_program_information_provider_data = (ebpf_extension_data_t*)ebpf_allocate(
EBPF_OFFSET_OF(ebpf_extension_data_t, data) + buffer_size, EBPF_MEMORY_NO_EXECUTE);
_ebpf_xdp_program_information_provider_data =
(ebpf_extension_data_t*)ebpf_allocate(EBPF_OFFSET_OF(ebpf_extension_data_t, data) + buffer_size);
if (_ebpf_xdp_program_information_provider_data == NULL) {
return_value = EBPF_NO_MEMORY;
@ -732,8 +732,8 @@ _net_ebpf_ext_program_information_encode_bind()
const uint8_t* buffer = _ebpf_encoded_bind_program_information_data;
unsigned long buffer_size = sizeof(_ebpf_encoded_bind_program_information_data);
_ebpf_bind_program_information_provider_data = (ebpf_extension_data_t*)ebpf_allocate(
EBPF_OFFSET_OF(ebpf_extension_data_t, data) + buffer_size, EBPF_MEMORY_NO_EXECUTE);
_ebpf_bind_program_information_provider_data =
(ebpf_extension_data_t*)ebpf_allocate(EBPF_OFFSET_OF(ebpf_extension_data_t, data) + buffer_size);
if (_ebpf_bind_program_information_provider_data == NULL) {
return_value = EBPF_NO_MEMORY;