Merged PR 4256572: Update ebpf to use minimally changed ubpf

Update ebpf to use minimally changed ubpf

1) Revert change in ubpf to support dynamic map and helper resolution -> pre-resolve all maps and helpers.
2) Remove jitter code from kernel ubpf lib
This commit is contained in:
Alan Jowett 2021-03-17 22:10:24 +00:00
Родитель b431246e5d
Коммит b35a157c6b
8 изменённых файлов: 147 добавлений и 74 удалений

2
external/ubpf поставляемый

@ -1 +1 @@
Subproject commit c51ac5c3bc5273ec4b10d9db945326b35d44ec25
Subproject commit 6c313139f7c722673f4fec4e62fe4d9567baec6c

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

@ -170,43 +170,12 @@ get_map_descriptor_internal(int map_fd)
return get_map_cache_entry(map_fd).ebpf_map_descriptor;
}
static uint64_t
map_resolver(void* context, uint64_t fd)
{
_ebpf_operation_resolve_map_request request{
sizeof(request), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP, get_map_cache_entry(fd).handle};
_ebpf_operation_resolve_map_reply reply;
invoke_ioctl(context, request, reply);
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP) {
return 0;
}
return reply.address[0];
}
static uint64_t
helper_resolver(void* context, uint32_t helper)
{
_ebpf_operation_resolve_helper_request request{
sizeof(request), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER, helper};
_ebpf_operation_resolve_map_reply reply;
invoke_ioctl(context, request, reply);
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER) {
return 0;
}
return reply.address[0];
}
static uint32_t
resolve_maps_in_byte_code(std::vector<uint8_t>& byte_code)
{
std::vector<size_t> instruction_offsets;
std::vector<uint64_t> map_handles;
ebpf_inst* instructions = reinterpret_cast<ebpf_inst*>(byte_code.data());
ebpf_inst* instruction_end = reinterpret_cast<ebpf_inst*>(byte_code.data() + byte_code.size());
for (size_t index = 0; index < byte_code.size() / sizeof(ebpf_inst); index++) {
@ -225,22 +194,89 @@ resolve_maps_in_byte_code(std::vector<uint8_t>& byte_code)
continue;
}
uint64_t imm =
static_cast<uint64_t>(first_instruction.imm) | (static_cast<uint64_t>(second_instruction.imm) << 32);
instruction_offsets.push_back(index - 1);
map_handles.push_back(imm);
}
std::vector<uint8_t> request_buffer(
offsetof(ebpf_operation_resolve_map_request_t, map_handle) + sizeof(uint64_t) * map_handles.size());
std::vector<uint8_t> reply_buffer(
offsetof(ebpf_operation_resolve_map_reply_t, address) + sizeof(uint64_t) * map_handles.size());
auto request = reinterpret_cast<ebpf_operation_resolve_map_request_t*>(request_buffer.data());
auto reply = reinterpret_cast<ebpf_operation_resolve_map_reply_t*>(reply_buffer.data());
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP;
request->header.length = static_cast<uint16_t>(request_buffer.size());
for (size_t index = 0; index < map_handles.size(); index++) {
request->map_handle[index] = map_handles[index];
}
uint32_t result = invoke_ioctl(device_handle, request_buffer, reply_buffer);
if (result != ERROR_SUCCESS) {
return result;
}
for (size_t index = 0; index < map_handles.size(); index++) {
ebpf_inst& first_instruction = instructions[instruction_offsets[index]];
ebpf_inst& second_instruction = instructions[instruction_offsets[index] + 1];
// Clear LD_MAP flag
first_instruction.src = 0;
// Resolve FD -> map address.
uint64_t imm =
static_cast<uint64_t>(first_instruction.imm) | (static_cast<uint64_t>(second_instruction.imm) << 32);
uint64_t new_imm = map_resolver(device_handle, imm);
if (new_imm == 0) {
return ERROR_INVALID_PARAMETER;
}
// Replace handle with address
uint64_t new_imm = reply->address[index];
first_instruction.imm = static_cast<uint32_t>(new_imm);
second_instruction.imm = static_cast<uint32_t>(new_imm >> 32);
}
return ERROR_SUCCESS;
}
static uint32_t
build_helper_id_to_address_map(std::vector<uint8_t>& byte_code, std::map<uint32_t, uint64_t>& helper_id_to_adddress)
{
ebpf_inst* instructions = reinterpret_cast<ebpf_inst*>(byte_code.data());
for (size_t index = 0; index < byte_code.size() / sizeof(ebpf_inst); index++) {
ebpf_inst& instruction = instructions[index];
if (instruction.opcode != INST_OP_CALL) {
continue;
}
helper_id_to_adddress[instruction.imm] = 0;
}
std::vector<uint8_t> request_buffer(
offsetof(ebpf_operation_resolve_helper_request_t, helper_id) + sizeof(uint32_t) * helper_id_to_adddress.size());
std::vector<uint8_t> reply_buffer(
offsetof(ebpf_operation_resolve_helper_reply_t, address) + sizeof(uint64_t) * helper_id_to_adddress.size());
auto request = reinterpret_cast<ebpf_operation_resolve_helper_request_t*>(request_buffer.data());
auto reply = reinterpret_cast<ebpf_operation_resolve_helper_reply_t*>(reply_buffer.data());
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER;
request->header.length = static_cast<uint16_t>(request_buffer.size());
size_t index = 0;
for (const auto& helper : helper_id_to_adddress) {
request->helper_id[index++] = helper.first;
}
uint32_t result = invoke_ioctl(device_handle, request_buffer, reply_buffer);
if (result != ERROR_SUCCESS) {
return result;
}
index = 0;
for (auto& helper : helper_id_to_adddress) {
helper.second = reply->address[index++];
}
return EBPF_ERROR_SUCCESS;
}
uint32_t
ebpf_api_load_program(
const char* file_name,
@ -306,6 +342,12 @@ ebpf_api_load_program(
std::copy(section_name, section_name + section_name_bytes.size(), section_name_bytes.begin());
if (execution_type == EBPF_EXECUTION_JIT) {
std::map<uint32_t, uint64_t> helper_id_to_adddress;
result = build_helper_id_to_address_map(byte_code, helper_id_to_adddress);
if (result != ERROR_SUCCESS) {
return result;
}
std::vector<uint8_t> machine_code(MAX_CODE_SIZE);
size_t machine_code_size = machine_code.size();
@ -315,8 +357,10 @@ ebpf_api_load_program(
return ERROR_OUTOFMEMORY;
}
if (ubpf_register_helper_resolver(vm, device_handle, helper_resolver) < 0) {
return ERROR_INVALID_PARAMETER;
for (const auto& helper : helper_id_to_adddress) {
if (ubpf_register(vm, helper.first, nullptr, reinterpret_cast<void*>(helper.second)) < 0) {
return ERROR_INVALID_PARAMETER;
}
}
if (ubpf_load(
@ -642,5 +686,6 @@ ebpf_api_program_query_information(
void
ebpf_api_delete_map(ebpf_handle_t handle)
{
CloseHandle(handle);
UNREFERENCED_PARAMETER(handle);
// TODO: Call close handle once the switch to using OB handles
}

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

@ -8,6 +8,7 @@
#include <exception>
#include <string>
#include <vector>
#include <map>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files

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

@ -362,6 +362,20 @@ ebpf_core_protocol_unload_code(_In_ const struct _ebpf_operation_unload_code_req
return _ebpf_core_delete_code_entry(request->handle);
}
static ebpf_error_code_t
ebpf_core_register_helpers(struct ubpf_vm* vm)
{
uint32_t index = 0;
for (index = 0; index < RTL_COUNT_OF(_ebpf_program_helpers); index++) {
if (_ebpf_program_helpers[index] == NULL)
continue;
if (ubpf_register(vm, index, NULL, (void*)_ebpf_program_helpers[index]) < 0)
return EBPF_ERROR_INVALID_PARAMETER;
}
return EBPF_ERROR_SUCCESS;
}
static ebpf_error_code_t
ebpf_core_protocol_load_code(
_In_ const ebpf_operation_load_code_request_t* request,
@ -447,7 +461,11 @@ ebpf_core_protocol_load_code(
// failing.
toggle_bounds_check(code_entry->code_or_vm.vm, false);
ubpf_register_helper_resolver(code_entry->code_or_vm.vm, code_entry, ebpf_core_interpreter_helper_resolver);
retval = ebpf_core_register_helpers(code_entry->code_or_vm.vm);
if (retval != EBPF_ERROR_SUCCESS) {
goto Done;
}
if (ubpf_load(code_entry->code_or_vm.vm, code, (uint32_t)code_length, &error_message) != 0) {
ebpf_free(error_message);
retval = EBPF_ERROR_INVALID_PARAMETER;
@ -474,12 +492,24 @@ ebpf_core_protocol_resolve_helper(
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply,
uint16_t reply_length)
{
UNREFERENCED_PARAMETER(reply_length);
size_t count_of_helpers =
(request->header.length - RTL_OFFSET_OF(ebpf_operation_resolve_helper_request_t, helper_id)) /
sizeof(request->helper_id[0]);
size_t required_reply_length =
RTL_OFFSET_OF(ebpf_operation_resolve_helper_reply_t, address) + count_of_helpers * sizeof(reply->address[0]);
size_t helper_index;
if (request->helper_id[0] >= RTL_COUNT_OF(_ebpf_program_helpers)) {
if (reply_length < required_reply_length) {
return EBPF_ERROR_INVALID_PARAMETER;
}
reply->address[0] = (uint64_t)_ebpf_program_helpers[request->helper_id[0]];
for (helper_index = 0; helper_index < count_of_helpers; helper_index++) {
if (request->helper_id[helper_index] >= RTL_COUNT_OF(_ebpf_program_helpers)) {
return EBPF_ERROR_INVALID_PARAMETER;
}
reply->address[helper_index] = (uint64_t)_ebpf_program_helpers[request->helper_id[helper_index]];
}
reply->header.length = (uint16_t)required_reply_length;
return EBPF_ERROR_SUCCESS;
}
@ -490,16 +520,26 @@ ebpf_core_protocol_resolve_map(
_Inout_ struct _ebpf_operation_resolve_map_reply* reply,
uint16_t reply_length)
{
size_t count_of_maps = (request->header.length - RTL_OFFSET_OF(ebpf_operation_resolve_map_request_t, map_handle)) /
sizeof(request->map_handle[0]);
size_t required_reply_length =
RTL_OFFSET_OF(ebpf_operation_resolve_map_reply_t, address) + count_of_maps * sizeof(reply->address[0]);
size_t map_index;
ebpf_core_map_t* map;
UNREFERENCED_PARAMETER(reply_length);
map = _ebpf_core_find_map_entry(request->map_handle[0]);
if (map) {
reply->address[0] = (uint64_t)map;
return EBPF_ERROR_SUCCESS;
} else {
return EBPF_ERROR_INVALID_HANDLE;
if (reply_length < required_reply_length) {
return EBPF_ERROR_INVALID_PARAMETER;
}
for (map_index = 0; map_index < count_of_maps; map_index++) {
map = _ebpf_core_find_map_entry(request->map_handle[map_index]);
if (!map) {
return EBPF_ERROR_INVALID_HANDLE;
}
reply->address[map_index] = (uint64_t)map;
}
reply->header.length = (uint16_t)required_reply_length;
return EBPF_ERROR_SUCCESS;
}
ebpf_error_code_t

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

@ -18,10 +18,8 @@
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\ebpf.h" />
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\platform.h" />
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\ubpf_int.h" />
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\ubpf_jit_x86_64.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\..\external\ubpf\vm\ubpf_jit_x86_64.c" />
<ClCompile Include="..\..\..\..\..\external\ubpf\vm\ubpf_vm.c" />
<ClCompile Include="platform.c" />
</ItemGroup>
@ -68,7 +66,7 @@
<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)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;$(SolutionDir)\src\ebpf\libs\ubpf\kernel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
@ -76,7 +74,7 @@
<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)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;$(SolutionDir)\src\ebpf\libs\ubpf\kernel;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>%(DisableSpecificWarnings)</DisableSpecificWarnings>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>

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

@ -25,17 +25,11 @@
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\ubpf_int.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\ubpf_jit_x86_64.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\external\ubpf\vm\platform.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\..\external\ubpf\vm\ubpf_jit_x86_64.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\..\external\ubpf\vm\ubpf_vm.c">
<Filter>Source Files</Filter>
</ClCompile>

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

@ -8,16 +8,10 @@
#include <stdlib.h>
void*
ubpf_alloc(size_t size, size_t count)
{
return calloc(size, count);
}
ubpf_alloc(size_t size, size_t count);
void
ubpf_free(void* memory)
{
free(memory);
}
ubpf_free(void* memory);
int
vasprintf(char** target, const char* format, va_list argptr)

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

@ -123,6 +123,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ControlFlowGuard>Guard</ControlFlowGuard>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>