2021-06-10 22:02:00 +03:00
|
|
|
// Copyright (c) Microsoft Corporation
|
|
|
|
// SPDX-License-Identifier: MIT
|
2021-05-06 03:24:09 +03:00
|
|
|
|
|
|
|
#include "ebpf_platform.h"
|
|
|
|
#include "ebpf_epoch.h"
|
|
|
|
|
2021-06-07 23:07:24 +03:00
|
|
|
#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
|
2021-06-10 19:45:23 +03:00
|
|
|
ebpf_allocate_trampoline_table(size_t entry_count, _Outptr_ ebpf_trampoline_table_t** trampoline_table)
|
2021-06-07 23:07:24 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2021-06-10 19:45:23 +03:00
|
|
|
|
2021-06-07 23:07:24 +03:00
|
|
|
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);
|
2021-06-10 19:45:23 +03:00
|
|
|
// Set local_trampoline_table to satisfy the static analyzer.
|
|
|
|
local_trampoline_table = NULL;
|
2021-06-07 23:07:24 +03:00
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-06-10 19:45:23 +03:00
|
|
|
ebpf_free_trampoline_table(_Pre_maybenull_ _Post_invalid_ ebpf_trampoline_table_t* trampoline_table)
|
2021-06-07 23:07:24 +03:00
|
|
|
{
|
|
|
|
if (trampoline_table) {
|
|
|
|
ebpf_unmap_memory(trampoline_table->memory_descriptor);
|
|
|
|
ebpf_free(trampoline_table);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-20 22:38:58 +03:00
|
|
|
ebpf_result_t
|
2021-06-07 23:07:24 +03:00
|
|
|
ebpf_update_trampoline_table(
|
2021-06-10 19:45:23 +03:00
|
|
|
_Inout_ ebpf_trampoline_table_t* trampoline_table, _In_ const ebpf_extension_dispatch_table_t* dispatch_table)
|
2021-05-06 03:24:09 +03:00
|
|
|
{
|
|
|
|
#if defined(_AMD64_)
|
2021-06-07 23:07:24 +03:00
|
|
|
|
2021-05-06 03:24:09 +03:00
|
|
|
size_t function_count = (dispatch_table->size - EBPF_OFFSET_OF(ebpf_extension_dispatch_table_t, function)) /
|
|
|
|
sizeof(dispatch_table->function[0]);
|
2021-06-07 23:07:24 +03:00
|
|
|
ebpf_trampoline_entry_t* local_entries;
|
|
|
|
ebpf_result_t return_value;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2021-05-06 03:24:09 +03:00
|
|
|
|
2021-06-07 23:07:24 +03:00
|
|
|
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;
|
2021-05-06 03:24:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t index;
|
2021-06-07 23:07:24 +03:00
|
|
|
for (index = 0; index < trampoline_table->entry_count; index++) {
|
2021-05-06 03:24:09 +03:00
|
|
|
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];
|
|
|
|
}
|
2021-06-07 23:07:24 +03:00
|
|
|
|
|
|
|
Exit:
|
|
|
|
return_value = ebpf_protect_memory(trampoline_table->memory_descriptor, EBPF_PAGE_PROTECT_READ_EXECUTE);
|
|
|
|
return return_value;
|
2021-05-06 03:24:09 +03:00
|
|
|
#elif
|
2021-06-07 23:07:24 +03:00
|
|
|
UNREFERENCED_PARAMETER(trampoline_table);
|
2021-05-06 03:24:09 +03:00
|
|
|
UNREFERENCED_PARAMETER(dispatch_table);
|
2021-06-10 05:32:57 +03:00
|
|
|
return EBPF_OPERATION_NOT_SUPPORTED;
|
2021-05-06 03:24:09 +03:00
|
|
|
#endif
|
|
|
|
}
|
2021-06-07 23:07:24 +03:00
|
|
|
|
|
|
|
ebpf_result_t
|
2021-06-10 19:45:23 +03:00
|
|
|
ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function)
|
2021-06-07 23:07:24 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|