From 125c183bee6f7fc06a8b068333701f10097ab362 Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Fri, 5 Mar 2021 22:47:18 +0000 Subject: [PATCH] Merged PR 4205675: Add option to execute eBPF program via JIT or interpreter Add option to execute eBPF program via JIT or interpreter --- ebpf-demo.sln | 4 +- src/ebpf/dll/ebpfapi.vcxproj | 67 +------- src/ebpf/dll/platform.cpp | 11 +- src/ebpf/include/api.h | 8 +- .../{libs/api => include}/unwind_helper.h | 0 src/ebpf/libs/api/api.cpp | 113 +++++++++---- src/ebpf/libs/api/api.vcxproj | 8 +- src/ebpf/libs/api/platform.h | 8 +- src/ebpf/libs/execution_context/ebpf_core.c | 30 +++- .../kernel/execution_context_kernel.vcxproj | 82 +--------- .../execution_context/user/ebpf_platform.cpp | 9 ++ .../user/execution_context_user.vcxproj | 51 +----- src/ebpf/libs/ubpf/kernel/platform.c | 7 +- src/ebpf/libs/ubpf/kernel/ubpf_kernel.vcxproj | 107 +----------- src/ebpf/libs/ubpf/user/ubpf_user.vcxproj | 54 +------ src/ebpf/sys/EbpfCore.vcxproj | 112 +------------ src/test/end_to_end/end_to_end.cpp | 152 +++++++++++++++--- src/test/end_to_end/end_to_end.vcxproj | 51 +----- src/test/end_to_end/mock.cpp | 9 +- src/test/sample/sample.vcxproj | 79 ++------- src/tools/netsh/ebpfnetsh.rc | 4 + src/tools/netsh/ebpfnetsh.vcxproj | 81 +--------- src/tools/netsh/elf.cpp | 68 ++++---- src/tools/netsh/programs.cpp | 18 ++- src/tools/netsh/tokens.h | 1 + 25 files changed, 369 insertions(+), 765 deletions(-) rename src/ebpf/{libs/api => include}/unwind_helper.h (100%) diff --git a/ebpf-demo.sln b/ebpf-demo.sln index f809fa7e1..53c42ec51 100644 --- a/ebpf-demo.sln +++ b/ebpf-demo.sln @@ -73,8 +73,8 @@ Global {BD587773-916F-365F-82C0-2E8DB12F40A0}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|ARM.ActiveCfg = Release|x64 {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|ARM64.ActiveCfg = Release|x64 - {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|x64.ActiveCfg = Release|x64 - {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|x64.Build.0 = Release|x64 + {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|x64.ActiveCfg = MinSizeRel|x64 + {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|x64.Build.0 = MinSizeRel|x64 {BD587773-916F-365F-82C0-2E8DB12F40A0}.Release|x86.ActiveCfg = Release|x64 {BD587773-916F-365F-82C0-2E8DB12F40A0}.RelWithDebInfo|ARM.ActiveCfg = RelWithDebInfo|x64 {BD587773-916F-365F-82C0-2E8DB12F40A0}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|x64 diff --git a/src/ebpf/dll/ebpfapi.vcxproj b/src/ebpf/dll/ebpfapi.vcxproj index f94bd7357..f6fc8a6c0 100644 --- a/src/ebpf/dll/ebpfapi.vcxproj +++ b/src/ebpf/dll/ebpfapi.vcxproj @@ -27,19 +27,6 @@ EbpfApi - - DynamicLibrary - true - v142 - Unicode - - - DynamicLibrary - false - v142 - true - Unicode - DynamicLibrary true @@ -58,12 +45,6 @@ - - - - - - @@ -71,12 +52,6 @@ - - true - - - false - true EbpfApi @@ -85,44 +60,8 @@ false EbpfApi - $(SolutionDir)..\bin\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ - - - Level3 - true - WIN32;_DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - false - Source.def - - - - - Level3 - true - true - true - WIN32;NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - true - true - false - Source.def - - Level3 @@ -132,6 +71,7 @@ Use pch.h MultiThreadedDebugDLL + $(SolutionDir)src\ebpf\include Windows @@ -152,7 +92,7 @@ true Use pch.h - ..\libs\api;%(AdditionalIncludeDirectories) + $(SolutionDir)src\ebpf\include MultiThreadedDLL @@ -162,6 +102,7 @@ true false Source.def + $(OutDir) diff --git a/src/ebpf/dll/platform.cpp b/src/ebpf/dll/platform.cpp index 9316e83c4..cf68f2e9b 100644 --- a/src/ebpf/dll/platform.cpp +++ b/src/ebpf/dll/platform.cpp @@ -4,11 +4,12 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include "pch.h" #include +#include "api.h" namespace Platform { BOOL DeviceIoControl( - _In_ HANDLE device_handle, + _In_ ebpf_handle_t device_handle, uint32_t io_control_code, _In_reads_bytes_opt_(input_buffer_size) void* input_buffer, uint32_t input_buffer_size, @@ -24,11 +25,11 @@ namespace Platform { input_buffer_size, output_buffer, output_buffer_size, - (LPDWORD)count_of_bytes_returned, + (DWORD*)count_of_bytes_returned, overlapped); } - HANDLE + ebpf_handle_t CreateFileW( _In_z_ PCWSTR file_name, uint32_t desired_access, @@ -36,7 +37,7 @@ namespace Platform { _In_opt_ SECURITY_ATTRIBUTES* security_attributed, uint32_t creation_disposition, uint32_t flags_and_attributed, - _In_opt_ HANDLE template_file) + _In_opt_ ebpf_handle_t template_file) { return ::CreateFileW( file_name, @@ -49,7 +50,7 @@ namespace Platform { } BOOL CloseHandle( - _In_ _Post_ptr_invalid_ HANDLE handle) + _In_ _Post_ptr_invalid_ ebpf_handle_t handle) { return ::CloseHandle(handle); } diff --git a/src/ebpf/include/api.h b/src/ebpf/include/api.h index 2aadcc303..8b31f8c00 100644 --- a/src/ebpf/include/api.h +++ b/src/ebpf/include/api.h @@ -12,11 +12,17 @@ extern "C" { typedef void* ebpf_handle_t; + typedef enum _ebpf_execution_type + { + EBPF_EXECUTION_JIT, + EBPF_EXECUTION_INTERPRET + } ebpf_execution_type_t; + uint32_t ebpf_api_initiate(); void ebpf_api_terminate(); - uint32_t ebpf_api_load_program(const char* file, const char* section_name, ebpf_handle_t* handle, const char** error_message); + uint32_t ebpf_api_load_program(const char* file, const char* section_name, ebpf_execution_type_t execution_type, ebpf_handle_t* handle, const char** error_message); void ebpf_api_free_error_message(const char* error_message); void ebpf_api_unload_program(ebpf_handle_t handle); diff --git a/src/ebpf/libs/api/unwind_helper.h b/src/ebpf/include/unwind_helper.h similarity index 100% rename from src/ebpf/libs/api/unwind_helper.h rename to src/ebpf/include/unwind_helper.h diff --git a/src/ebpf/libs/api/api.cpp b/src/ebpf/libs/api/api.cpp index 4c0b6800f..d208ace10 100644 --- a/src/ebpf/libs/api/api.cpp +++ b/src/ebpf/libs/api/api.cpp @@ -4,7 +4,6 @@ */ #include "pch.h" -#include "platform.h" #include "tlv.h" extern "C" @@ -12,6 +11,7 @@ extern "C" #include "api.h" #include "ubpf.h" } +#include "platform.h" #include "protocol.h" #include "unwind_helper.h" @@ -78,7 +78,7 @@ static uint32_t invoke_ioctl(ebpf_handle_t handle, request_t & request, reply_t auto result = Platform::DeviceIoControl( handle, - (uint32_t)IOCTL_EBPFCTL_METHOD_BUFFERED, + IOCTL_EBPFCTL_METHOD_BUFFERED, request_ptr, request_size, reply_ptr, @@ -224,7 +224,47 @@ static uint64_t helper_resolver(void* context, uint32_t helper) return reply.address[0]; } -uint32_t ebpf_api_load_program(const char* file_name, const char* section_name, ebpf_handle_t* handle, const char** error_message) +static uint32_t resolve_maps_in_byte_code(std::vector& byte_code) +{ + ebpf_inst* instructions = reinterpret_cast(byte_code.data()); + ebpf_inst* instruction_end = reinterpret_cast(byte_code.data() + byte_code.size()); + for (size_t index = 0; index < byte_code.size() / sizeof(ebpf_inst); index++) + { + ebpf_inst& first_instruction = instructions[index]; + ebpf_inst& second_instruction = instructions[index + 1]; + if (first_instruction.opcode != INST_OP_LDDW_IMM) + { + continue; + } + if (&instructions[index + 1] >= instruction_end) + { + return ERROR_INVALID_PARAMETER; + } + index++; + + // Check for LD_MAP flag + if (first_instruction.src != 1) + { + continue; + } + + // Clear LD_MAP flag + first_instruction.src = 0; + + // Resolve FD -> map address. + uint64_t imm = static_cast(first_instruction.imm) | (static_cast(second_instruction.imm) << 32); + uint64_t new_imm = map_resolver(device_handle, imm); + if (new_imm == 0) + { + return ERROR_INVALID_PARAMETER; + } + first_instruction.imm = static_cast(new_imm); + second_instruction.imm = static_cast(new_imm >> 32); + } + return ERROR_SUCCESS; +} + +uint32_t ebpf_api_load_program(const char* file_name, const char* section_name, ebpf_execution_type_t execution_type, ebpf_handle_t* handle, const char** error_message) { std::vector byte_code(MAX_CODE_SIZE); size_t byte_code_size = byte_code.size(); @@ -265,42 +305,55 @@ uint32_t ebpf_api_load_program(const char* file_name, const char* section_name, return ERROR_INVALID_PARAMETER; } - // JIT code. - vm = ubpf_create(); - if (vm == nullptr) - { - return ERROR_OUTOFMEMORY; - } byte_code.resize(byte_code_size); - - if (ubpf_register_map_resolver(vm, device_handle, map_resolver) < 0) + result = resolve_maps_in_byte_code(byte_code); + if (result != ERROR_SUCCESS) { - return ERROR_INVALID_PARAMETER; + return result; } - if (ubpf_register_helper_resolver(vm, device_handle, helper_resolver) < 0) + if (execution_type == EBPF_EXECUTION_JIT) { - return ERROR_INVALID_PARAMETER; - } + // JIT code. + vm = ubpf_create(); + if (vm == nullptr) + { + return ERROR_OUTOFMEMORY; + } - if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), const_cast(error_message)) < 0) + if (ubpf_register_helper_resolver(vm, device_handle, helper_resolver) < 0) + { + return ERROR_INVALID_PARAMETER; + } + + if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), const_cast(error_message)) < 0) + { + return ERROR_INVALID_PARAMETER; + } + + if (ubpf_translate(vm, machine_code.data(), &machine_code_size, const_cast(error_message))) + { + return ERROR_INVALID_PARAMETER; + } + machine_code.resize(machine_code_size); + + request_buffer.resize(machine_code.size() + offsetof(ebpf_operation_load_code_request_t, code)); + auto request = reinterpret_cast(request_buffer.data()); + request->header.id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE; + request->header.length = static_cast(request_buffer.size()); + request->code_type = EBPF_CODE_NATIVE; + std::copy(machine_code.begin(), machine_code.end(), request_buffer.begin() + offsetof(ebpf_operation_load_code_request_t, code)); + } + else { - return ERROR_INVALID_PARAMETER; + request_buffer.resize(byte_code.size() + offsetof(ebpf_operation_load_code_request_t, code)); + auto request = reinterpret_cast(request_buffer.data()); + request->header.id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE; + request->header.length = static_cast(request_buffer.size()); + request->code_type = EBPF_CODE_EBPF; + std::copy(byte_code.begin(), byte_code.end(), request_buffer.begin() + offsetof(ebpf_operation_load_code_request_t, code)); } - if (ubpf_translate(vm, machine_code.data(), &machine_code_size, const_cast(error_message))) - { - return ERROR_INVALID_PARAMETER; - } - machine_code.resize(machine_code_size); - - request_buffer.resize(machine_code.size() + offsetof(ebpf_operation_load_code_request_t, code)); - auto request = reinterpret_cast(request_buffer.data()); - request->header.id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE; - request->header.length = static_cast(request_buffer.size()); - request->code_type = EBPF_CODE_NATIVE; - std::copy(machine_code.begin(), machine_code.end(), request_buffer.begin() + offsetof(ebpf_operation_load_code_request_t, code)); - result = invoke_ioctl(device_handle, request_buffer, reply); if (result != ERROR_SUCCESS) diff --git a/src/ebpf/libs/api/api.vcxproj b/src/ebpf/libs/api/api.vcxproj index d8e1f3c1e..84f5f4ba0 100644 --- a/src/ebpf/libs/api/api.vcxproj +++ b/src/ebpf/libs/api/api.vcxproj @@ -123,7 +123,7 @@ Level3 true - _DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h @@ -143,11 +143,11 @@ true true true - NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h - $(PrevailDir)src;..\..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) + $(SolutionDir)src\ebpf\include;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) stdcpplatest @@ -163,13 +163,13 @@ + true - diff --git a/src/ebpf/libs/api/platform.h b/src/ebpf/libs/api/platform.h index dd067e40d..21abeb14f 100644 --- a/src/ebpf/libs/api/platform.h +++ b/src/ebpf/libs/api/platform.h @@ -8,7 +8,7 @@ namespace Platform { BOOL DeviceIoControl( - _In_ HANDLE device_handle, + _In_ ebpf_handle_t device_handle, uint32_t io_control_code, _In_reads_bytes_opt_(input_buffer_size) void* input_buffer, uint32_t input_buffer_size, @@ -18,7 +18,7 @@ namespace Platform _Inout_opt_ OVERLAPPED* overlapped ); - HANDLE + ebpf_handle_t CreateFileW( _In_ PCWSTR file_name, uint32_t desired_access, @@ -26,11 +26,11 @@ namespace Platform _In_opt_ SECURITY_ATTRIBUTES* security_attributed, uint32_t creation_disposition, uint32_t flags_and_attributed, - _In_opt_ HANDLE template_file + _In_opt_ ebpf_handle_t template_file ); BOOL CloseHandle( - _In_ _Post_ptr_invalid_ HANDLE handle + _In_ _Post_ptr_invalid_ ebpf_handle_t handle ); } diff --git a/src/ebpf/libs/execution_context/ebpf_core.c b/src/ebpf/libs/execution_context/ebpf_core.c index 82dc46db7..6ba32bae2 100644 --- a/src/ebpf/libs/execution_context/ebpf_core.c +++ b/src/ebpf/libs/execution_context/ebpf_core.c @@ -14,6 +14,11 @@ #define RTL_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0])) #define RTL_OFFSET_OF(s, m) (((size_t)&((s*)0)->m)) +#if defined(NTDDI_VERSION) +#define false FALSE +#define true TRUE +#endif + typedef struct _ebpf_core_code_entry { // pointer to code buffer ebpf_code_type_t code_type; @@ -86,7 +91,7 @@ static uint64_t _ebpf_core_insert_code_entry(ebpf_core_code_entry_t* code) break; } } - ebpf_lock_unlock(&_ebpf_core_map_entry_table_lock, &state); + ebpf_lock_unlock(&_ebpf_core_code_entry_table_lock, &state); return handle; } @@ -199,6 +204,7 @@ ebpf_core_initialize() { 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); return EBPF_ERROR_SUCCESS; } @@ -284,13 +290,23 @@ ebpf_core_protocol_load_code( size_t code_size = request->header.length - RTL_OFFSET_OF(ebpf_operation_load_code_request_t, code); size_t allocation_size = 0; ebpf_core_code_entry_t* code = NULL; + ebpf_memory_type_t memory_type; retval = ebpf_safe_size_t_add(code_size, sizeof(ebpf_core_code_entry_t), &allocation_size); if (retval != EBPF_ERROR_SUCCESS) { goto Done; } - code = ebpf_allocate(allocation_size, EBPF_MEMORY_EXECUTE); + if (request->code_type == EBPF_CODE_NATIVE) + { + memory_type = EBPF_MEMORY_EXECUTE; + } + else + { + memory_type = EBPF_MEMORY_NO_EXECUTE; + } + + code = ebpf_allocate(allocation_size, memory_type); if (!code) { retval = EBPF_ERROR_OUT_OF_RESOURCES; @@ -305,7 +321,7 @@ ebpf_core_protocol_load_code( } else { - char* error_message; + char* error_message = NULL; code->code_type = EBPF_CODE_EBPF; code->vm = ubpf_create(); if (!code->vm) @@ -313,9 +329,15 @@ ebpf_core_protocol_load_code( retval = EBPF_ERROR_OUT_OF_RESOURCES; goto Done; } + + // BUG - ubpf implements bounds checking to detect interpreted code accesing memory out of bounds. + // Currently this is flagging valid access checks and failing. + toggle_bounds_check(code->vm, false); + ubpf_register_helper_resolver(code->vm, code, ebpf_core_interpreter_helper_resolver); if (ubpf_load(code->vm, &request->code[0], (uint32_t)code_size, &error_message) != 0) { + ebpf_free(error_message); retval = EBPF_ERROR_INVALID_PARAMETER; goto Done; } @@ -375,7 +397,7 @@ ebpf_error_code_t ebpf_core_invoke_hook( { ebpf_core_code_entry_t* code = NULL; ebpf_hook_function function_pointer; - char* error_message; + char* error_message = NULL; code = _ebpf_core_get_hook_entry(hook_point); if (code) diff --git a/src/ebpf/libs/execution_context/kernel/execution_context_kernel.vcxproj b/src/ebpf/libs/execution_context/kernel/execution_context_kernel.vcxproj index 522215c26..4a3779f9c 100644 --- a/src/ebpf/libs/execution_context/kernel/execution_context_kernel.vcxproj +++ b/src/ebpf/libs/execution_context/kernel/execution_context_kernel.vcxproj @@ -58,22 +58,6 @@ KMDF - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - Windows10 true @@ -91,37 +75,6 @@ Universal Unicode - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - @@ -129,17 +82,6 @@ - - - _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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) @@ -151,28 +93,8 @@ WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) + $(SolutionDir)\src\ebpf\include;$(SolutionDir)\external\ubpf\vm\inc;$(SolutionDir)\external\ubpf\vm;$(SolutionDir)\src\ebpf\libs\execution_context\kernel;%(AdditionalIncludeDirectories) + 4201;4100;%(DisableSpecificWarnings) diff --git a/src/ebpf/libs/execution_context/user/ebpf_platform.cpp b/src/ebpf/libs/execution_context/user/ebpf_platform.cpp index 2ceca2298..b0c05060b 100644 --- a/src/ebpf/libs/execution_context/user/ebpf_platform.cpp +++ b/src/ebpf/libs/execution_context/user/ebpf_platform.cpp @@ -11,6 +11,7 @@ #include "ebpf_core.h" #include "ebpf_platform.h" #include +#include std::set _executable_segments; @@ -58,18 +59,26 @@ ebpf_error_code_t ebpf_safe_size_t_add(size_t augend, size_t addend, size_t* res void ebpf_lock_create(ebpf_lock_t* lock) { + auto mutex = new std::mutex(); + *reinterpret_cast(lock) = mutex; } void ebpf_lock_destroy(ebpf_lock_t* lock) { + auto mutex = *reinterpret_cast(lock); + delete mutex; } void ebpf_lock_lock(ebpf_lock_t* lock, ebpf_lock_state_t* state) { + auto mutex = *reinterpret_cast(lock); + mutex->lock(); } void ebpf_lock_unlock(ebpf_lock_t* lock, ebpf_lock_state_t* state) { + auto mutex = *reinterpret_cast(lock); + mutex->unlock(); } typedef struct _hash_table { diff --git a/src/ebpf/libs/execution_context/user/execution_context_user.vcxproj b/src/ebpf/libs/execution_context/user/execution_context_user.vcxproj index 91d80f18d..d928a50e7 100644 --- a/src/ebpf/libs/execution_context/user/execution_context_user.vcxproj +++ b/src/ebpf/libs/execution_context/user/execution_context_user.vcxproj @@ -26,19 +26,6 @@ 10.0 - - StaticLibrary - true - v142 - Unicode - - - StaticLibrary - false - v142 - true - Unicode - StaticLibrary true @@ -82,40 +69,6 @@ false - - - Level3 - true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - Use - pch.h - - - - - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - Use - pch.h - - - - - true - true - true - - Level3 @@ -143,8 +96,10 @@ true NDEBUG;_LIB;%(PreprocessorDefinitions) true - Use + NotUsing pch.h + $(SolutionDir)\src\ebpf\include;$(SolutionDir)\external\ubpf\vm\inc;$(SolutionDir)\external\ubpf\vm;$(SolutionDir)\src\ebpf\libs\execution_context\user;%(AdditionalIncludeDirectories) + true diff --git a/src/ebpf/libs/ubpf/kernel/platform.c b/src/ebpf/libs/ubpf/kernel/platform.c index 8de7ffba3..802e1d26b 100644 --- a/src/ebpf/libs/ubpf/kernel/platform.c +++ b/src/ebpf/libs/ubpf/kernel/platform.c @@ -11,7 +11,12 @@ void* ubpf_alloc(size_t size, size_t count) { - return ExAllocatePool(POOL_FLAG_NON_PAGED, size * count); + void * memory = ExAllocatePool(POOL_FLAG_NON_PAGED, size * count); + if (memory) + { + memset(memory, 0, size * count); + } + return memory; } void ubpf_free(void* memory) diff --git a/src/ebpf/libs/ubpf/kernel/ubpf_kernel.vcxproj b/src/ebpf/libs/ubpf/kernel/ubpf_kernel.vcxproj index 9f23eb5f0..ae3379a6f 100644 --- a/src/ebpf/libs/ubpf/kernel/ubpf_kernel.vcxproj +++ b/src/ebpf/libs/ubpf/kernel/ubpf_kernel.vcxproj @@ -1,14 +1,6 @@  - - Debug - Win32 - - - Release - Win32 - Debug x64 @@ -17,22 +9,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - @@ -57,22 +33,6 @@ $(LatestTargetPlatformVersion) - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - Windows10 true @@ -90,37 +50,6 @@ Universal Unicode - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - true - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - - - Windows10 - false - WindowsKernelModeDriver10.0 - StaticLibrary - Universal - Unicode - @@ -131,17 +60,6 @@ $(SolutionDir)$(Platform)\$(Configuration)\ - - - _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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) @@ -154,28 +72,9 @@ WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(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) - MultiThreadedDebugDLL - - - - - WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) + $(SolutionDir)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) + %(DisableSpecificWarnings) + false diff --git a/src/ebpf/libs/ubpf/user/ubpf_user.vcxproj b/src/ebpf/libs/ubpf/user/ubpf_user.vcxproj index 9f499fe3b..1ac48d018 100644 --- a/src/ebpf/libs/ubpf/user/ubpf_user.vcxproj +++ b/src/ebpf/libs/ubpf/user/ubpf_user.vcxproj @@ -38,19 +38,6 @@ $(ProjectDir)../../../../external/ubpf/vm - - StaticLibrary - true - v142 - Unicode - - - StaticLibrary - false - v142 - true - Unicode - StaticLibrary true @@ -69,12 +56,6 @@ - - - - - - @@ -94,39 +75,6 @@ false - - - Level3 - true - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - true - $(UbpfDir);$(UbpfDir)/inc - - - - - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - true - Use - pch.h - - - - - true - true - true - - Level3 @@ -154,7 +102,7 @@ true NotUsing pch.h - $(UbpfDir)/inc;$(UbpfDir);%(AdditionalIncludeDirectories) + $(SolutionDir)\external\ubpf\vm;$(SolutionDir)\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) diff --git a/src/ebpf/sys/EbpfCore.vcxproj b/src/ebpf/sys/EbpfCore.vcxproj index d89c690f9..d5948973f 100644 --- a/src/ebpf/sys/EbpfCore.vcxproj +++ b/src/ebpf/sys/EbpfCore.vcxproj @@ -45,23 +45,6 @@ EbpfCore - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - false - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - Windows10 true @@ -80,38 +63,6 @@ Universal false - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - true - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - - - Windows10 - false - WindowsKernelModeDriver10.0 - Driver - KMDF - Universal - @@ -120,37 +71,19 @@ - - DbgengKernelDebugger - - - DbgengKernelDebugger - DbgengKernelDebugger DbgengKernelDebugger - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - - - DbgengKernelDebugger - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SolutionDir)..\api\;$(SolutionDir)EbpfCore\;$(SolutionDir)src\ebpf\libs\api + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SolutionDir)src\ebpf\include %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO @@ -169,7 +102,7 @@ %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SolutionDir)..\api\;$(SolutionDir)..\libs\api\;$(SolutionDir)EbpfCore\;$(SolutionDir)src\ebpf\libs\api;$(SolutionDir)src\ebpf\include + %(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SolutionDir)src\ebpf\include %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO @@ -184,44 +117,6 @@ $(OutDir) - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - %(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\fwpkclnt.lib;$(SDK_LIB_PATH)\uuid.lib - - - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - - - %(AdditionalIncludeDirectories);$(DDK_INC_PATH) - %(PreprocessorDefinitions);BINARY_COMPATIBLE=0;NT;UNICODE;_UNICODE;NDIS60;POOL_NX_OPTIN_AUTO - - - %(AdditionalDependencies);$(DDK_LIB_PATH)\ntoskrnl.lib;$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\fwpkclnt.lib;$(SDK_LIB_PATH)\uuid.lib - - @@ -239,6 +134,9 @@ {26e7ed0b-c128-4d7c-a90e-c246def40ad3} + + {675b59f8-089e-40b5-8388-56254447cfa3} + diff --git a/src/test/end_to_end/end_to_end.cpp b/src/test/end_to_end/end_to_end.cpp index ce156f66d..66870ab94 100644 --- a/src/test/end_to_end/end_to_end.cpp +++ b/src/test/end_to_end/end_to_end.cpp @@ -16,8 +16,10 @@ namespace ebpf #include "../sample/ebpf.h" }; +#include "unwind_helper.h" + static const struct { - ebpf_error_code_t (*protocol_handler)(_In_ const void* input_buffer, void* output_buffer); + ebpf_error_code_t(*protocol_handler)(_In_ const void* input_buffer, void* output_buffer); size_t minimum_request_size; size_t minimum_reply_size; } EbpfProtocolHandlers[] = { @@ -36,7 +38,7 @@ static const struct { { reinterpret_cast(ebpf_core_protocol_query_map_definition), sizeof(struct _ebpf_operation_query_map_definition_request), sizeof(struct _ebpf_operation_query_map_definition_reply) }, }; -HANDLE +ebpf_handle_t GlueCreateFileW( PCWSTR lpFileName, DWORD dwDesiredAccess, @@ -44,15 +46,15 @@ GlueCreateFileW( PSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile - ) + ebpf_handle_t hTemplateFile +) { - return (HANDLE)0x12345678; + return (ebpf_handle_t)0x12345678; } BOOL GlueCloseHandle( - HANDLE hObject + ebpf_handle_t hObject ) { return TRUE; @@ -60,7 +62,7 @@ GlueCloseHandle( BOOL GlueDeviceIoControl( - HANDLE hDevice, + ebpf_handle_t hDevice, DWORD dwIoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, @@ -78,7 +80,7 @@ GlueDeviceIoControl( { goto Fail; } - + if (user_request->length < EbpfProtocolHandlers[request_id].minimum_request_size) { goto Fail; @@ -119,11 +121,11 @@ GlueDeviceIoControl( } goto Fail; } - + return TRUE; Fail: - + return FALSE; } @@ -142,41 +144,53 @@ std::vector prepare_udp_packet(uint16_t udp_length) } #define SAMPLE_PATH "..\\sample\\" -TEST_CASE("droppacket", "[droppacket]") + +TEST_CASE("droppacket-jit", "[droppacket_jit]") { device_io_control_handler = GlueDeviceIoControl; create_file_handler = GlueCreateFileW; close_handle_handler = GlueCloseHandle; - HANDLE program_handle; - const char* error_message; + ebpf_handle_t program_handle; uint32_t result = 0; + const char* error_message = NULL; + bool ec_initialized = false; + bool api_initialized = false; + _unwind_helper on_exit([&] { + ebpf_api_free_error_message(error_message); + if (api_initialized) + ebpf_api_terminate(); + if (ec_initialized) + ebpf_core_terminate(); + }); REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS); + ec_initialized = true; REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS); + api_initialized = true; + + REQUIRE(ebpf_api_load_program(SAMPLE_PATH "droppacket.o", "xdp", EBPF_EXECUTION_JIT, &program_handle, &error_message) == ERROR_SUCCESS); - REQUIRE(ebpf_api_load_program(SAMPLE_PATH "droppacket.o", "xdp", &program_handle, &error_message) == ERROR_SUCCESS); - REQUIRE(ebpf_api_attach_program(program_handle, EBPF_PROGRAM_TYPE_XDP) == ERROR_SUCCESS); auto packet = prepare_udp_packet(0); uint32_t key = 0; uint64_t value = 1000; - REQUIRE(ebpf_api_map_update_element((HANDLE)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(ebpf_api_map_update_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); // Test that we drop the packet and increment the map ebpf::xdp_md_t ctx{ packet.data(), packet.data() + packet.size() }; REQUIRE(ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx, &result) == EBPF_ERROR_SUCCESS); REQUIRE(result == 2); - REQUIRE(ebpf_api_map_lookup_element((HANDLE)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); REQUIRE(value == 1001); - REQUIRE(ebpf_api_map_delete_element((HANDLE)1, sizeof(key), (uint8_t*)&key) == ERROR_SUCCESS); + REQUIRE(ebpf_api_map_delete_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key) == ERROR_SUCCESS); - REQUIRE(ebpf_api_map_lookup_element((HANDLE)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); REQUIRE(value == 0); @@ -186,14 +200,90 @@ TEST_CASE("droppacket", "[droppacket]") REQUIRE(ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx2, &result) == EBPF_ERROR_SUCCESS); REQUIRE(result == 1); - REQUIRE(ebpf_api_map_lookup_element((HANDLE)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(value == 0); +} + +TEST_CASE("droppacket-interpret", "[droppacket_interpret]") +{ + device_io_control_handler = GlueDeviceIoControl; + create_file_handler = GlueCreateFileW; + close_handle_handler = GlueCloseHandle; + + ebpf_handle_t program_handle; + const char* error_message = NULL; + bool ec_initialized = false; + bool api_initialized = false; + _unwind_helper on_exit([&] + { + ebpf_api_free_error_message(error_message); + if (api_initialized) + ebpf_api_terminate(); + if (ec_initialized) + ebpf_core_terminate(); + }); + uint32_t result = 0; + + REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS); + ec_initialized = true; + + REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS); + api_initialized = true; + + REQUIRE(ebpf_api_load_program(SAMPLE_PATH "droppacket.o", "xdp", EBPF_EXECUTION_INTERPRET, &program_handle, &error_message) == ERROR_SUCCESS); + + REQUIRE(ebpf_api_attach_program(program_handle, EBPF_PROGRAM_TYPE_XDP) == ERROR_SUCCESS); + + auto packet = prepare_udp_packet(0); + + uint32_t key = 0; + uint64_t value = 1000; + REQUIRE(ebpf_api_map_update_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + + // Test that we drop the packet and increment the map + ebpf::xdp_md_t ctx{ packet.data(), packet.data() + packet.size() }; + REQUIRE(ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx, &result) == EBPF_ERROR_SUCCESS); + REQUIRE(result == 2); + + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(value == 1001); + + REQUIRE(ebpf_api_map_delete_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key) == ERROR_SUCCESS); + + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); REQUIRE(value == 0); + + packet = prepare_udp_packet(10); + ebpf::xdp_md_t ctx2{ packet.data(), packet.data() + packet.size() }; + + REQUIRE(ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx2, &result) == EBPF_ERROR_SUCCESS); + REQUIRE(result == 1); + + REQUIRE(ebpf_api_map_lookup_element((ebpf_handle_t)1, sizeof(key), (uint8_t*)&key, sizeof(value), (uint8_t*)&value) == ERROR_SUCCESS); + REQUIRE(value == 0); } TEST_CASE("enum section", "[enum sections]") { const char* error_message = nullptr; const tlv_type_length_value_t* section_data = nullptr; + bool ec_initialized = false; + bool api_initialized = false; + _unwind_helper on_exit([&] + { + ebpf_api_free_error_message(error_message); + ebpf_api_elf_free(section_data); + if (api_initialized) + ebpf_api_terminate(); + if (ec_initialized) + ebpf_core_terminate(); + }); + + REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS); + ec_initialized = true; + REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS); + api_initialized = true; + REQUIRE(ebpf_api_elf_enumerate_sections(SAMPLE_PATH "droppacket.o", nullptr, true, §ion_data, &error_message) == 0); for (auto current_section = tlv_child(section_data); current_section != tlv_next(section_data); current_section = tlv_next(current_section)) { @@ -217,18 +307,30 @@ TEST_CASE("enum section", "[enum sections]") { REQUIRE(static_cast(value->type) == tlv_type_t::UINT); } } - ebpf_api_elf_free(section_data); - ebpf_api_free_error_message(error_message); - } TEST_CASE("verify section", "[verify section]") { + const char* error_message = nullptr; const char* report = nullptr; + bool ec_initialized = false; + bool api_initialized = false; + _unwind_helper on_exit([&] { + ebpf_api_free_error_message(error_message); + ebpf_api_free_error_message(report); + if (api_initialized) + ebpf_api_terminate(); + if (ec_initialized) + ebpf_core_terminate(); + }); + + REQUIRE(ebpf_core_initialize() == EBPF_ERROR_SUCCESS); + api_initialized = true; + REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS); + ec_initialized = true; + REQUIRE(ebpf_api_elf_verify_section(SAMPLE_PATH "droppacket.o", "xdp", &report, &error_message) == 0); REQUIRE(report != nullptr); REQUIRE(error_message == nullptr); - ebpf_api_free_error_message(report); - ebpf_api_free_error_message(error_message); } diff --git a/src/test/end_to_end/end_to_end.vcxproj b/src/test/end_to_end/end_to_end.vcxproj index 28125e0a3..9250e4df2 100644 --- a/src/test/end_to_end/end_to_end.vcxproj +++ b/src/test/end_to_end/end_to_end.vcxproj @@ -2,14 +2,6 @@ - - Debug - Win32 - - - Release - Win32 - Debug x64 @@ -27,19 +19,6 @@ 10.0 - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - Application true @@ -83,34 +62,6 @@ false - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - Level3 @@ -133,6 +84,8 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + $(SolutionDir)src\ebpf\include;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) + stdcpp17 Console diff --git a/src/test/end_to_end/mock.cpp b/src/test/end_to_end/mock.cpp index 46174d5d2..818026056 100644 --- a/src/test/end_to_end/mock.cpp +++ b/src/test/end_to_end/mock.cpp @@ -4,6 +4,7 @@ */ #include "mock.h" +#include "api.h" std::function create_file_handler; std::function device_io_control_handler; std::function close_handle_handler; @@ -11,7 +12,7 @@ std::function close_handle_handler; namespace Platform { BOOL DeviceIoControl( - _In_ HANDLE device_handle, + _In_ ebpf_handle_t device_handle, uint32_t io_control_code, _In_reads_bytes_opt_(input_buffer_size) void* input_buffer, uint32_t input_buffer_size, @@ -32,7 +33,7 @@ namespace Platform { overlapped); } - HANDLE + ebpf_handle_t CreateFileW( _In_ PCWSTR file_name, uint32_t desired_access, @@ -40,7 +41,7 @@ namespace Platform { _In_opt_ SECURITY_ATTRIBUTES* security_attributed, uint32_t creation_disposition, uint32_t flags_and_attributed, - _In_opt_ HANDLE template_file + _In_opt_ ebpf_handle_t template_file ) { return create_file_handler( @@ -54,7 +55,7 @@ namespace Platform { } BOOL CloseHandle( - _In_ _Post_ptr_invalid_ HANDLE handle + _In_ _Post_ptr_invalid_ ebpf_handle_t handle ) { return close_handle_handler(handle); diff --git a/src/test/sample/sample.vcxproj b/src/test/sample/sample.vcxproj index 41e6c2a50..ba61ce6a8 100644 --- a/src/test/sample/sample.vcxproj +++ b/src/test/sample/sample.vcxproj @@ -26,19 +26,6 @@ 10.0 - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - Application true @@ -57,12 +44,6 @@ - - - - - - @@ -70,46 +51,12 @@ - - true - - - false - true false - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - Level3 @@ -140,31 +87,27 @@ - true CppCode - clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o - %(Filename).o;%(Outputs) + clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o + %(Filename).o;%(Outputs) - true CppCode - clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o - %(Filename).o;%(Outputs) - true + clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o + %(Filename).o;%(Outputs) + true CppCode - true - clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o - %(Filename).o;%(Outputs) - true + clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o + %(Filename).o;%(Outputs) + true - true CppCode - clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o - %(Filename).o;%(Outputs) - true + clang -target bpf -O2 -Wall -c %(Filename).c -o %(Filename).o + %(Filename).o;%(Outputs) + true diff --git a/src/tools/netsh/ebpfnetsh.rc b/src/tools/netsh/ebpfnetsh.rc index 971b5b029..f76de5be8 100644 --- a/src/tools/netsh/ebpfnetsh.rc +++ b/src/tools/netsh/ebpfnetsh.rc @@ -58,6 +58,7 @@ BEGIN \n [[section=]]\ \n [[type=]xdp]\ \n [[pinned=]yes|no]\ +\n [[execution=]jit|interpret]\ \n\ \nParameters:\ \n\ @@ -74,6 +75,9 @@ BEGIN \n yes: Pin the program.\ \n This is the default value.\ \n no: Do not pin the program.\ +\n execution - One of the following values:\ +\n jit: Convert the program to machine code.\ +\n interpret: Run the program as byte code.\ \n\ \nRemarks: Loads a program (if not already loaded) and pins it if\ \n requested.\ diff --git a/src/tools/netsh/ebpfnetsh.vcxproj b/src/tools/netsh/ebpfnetsh.vcxproj index 2888279d7..28a7e2381 100644 --- a/src/tools/netsh/ebpfnetsh.vcxproj +++ b/src/tools/netsh/ebpfnetsh.vcxproj @@ -1,14 +1,6 @@  - - Debug - Win32 - - - Release - Win32 - Debug x64 @@ -26,19 +18,6 @@ 10.0 - - DynamicLibrary - true - v142 - Unicode - - - DynamicLibrary - false - v142 - true - Unicode - DynamicLibrary true @@ -57,12 +36,6 @@ - - - - - - @@ -70,60 +43,12 @@ - - true - - - false - true false - - - Level3 - true - WIN32;_DEBUG;EBPFNETSH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - $(SolutionDir)..\..\..\external\ebpf-verifier\src;C:\git\dthaler\ebpf-verifier\packages\boost.1.72.0.0\lib\native\include;%(AdditionalIncludeDirectories) - stdcpplatest - - - Windows - true - false - ebpfverifier.lib;netsh.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - $(SolutionDir)..\..\..\external\ebpf-verifier\build\$(Configuration);%(AdditionalLibraryDirectories) - - - - - Level3 - true - true - true - WIN32;NDEBUG;EBPFNETSH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - $(SolutionDir)..\..\..\external\ebpf-verifier\src;C:\git\dthaler\ebpf-verifier\packages\boost.1.72.0.0\lib\native\include;%(AdditionalIncludeDirectories) - stdcpplatest - - - Windows - true - true - true - false - ebpfverifier.lib;netsh.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - $(SolutionDir)..\..\..\external\ebpf-verifier\build\$(Configuration);%(AdditionalLibraryDirectories) - - Level3 @@ -152,7 +77,7 @@ true NDEBUG;EBPFNETSH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true - $(SolutionDir)..\..\..\external\ebpf-verifier\src;$(SolutionDir)src\ebpf\libs\api;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) + $(SolutionDir)src\ebpf\include;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) stdcpplatest @@ -161,10 +86,10 @@ true true false - ebpfverifier.lib;netsh.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + netsh.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - $(SolutionDir)..\..\..\external\ebpf-verifier\build\$(Configuration);$(SolutionDir)..\..\..\src\ebpf\bin\$(Platform)\$(Configuration);$(SolutionDir)src\ebpf\bin\$(Platform)\$(Configuration);$(SolutionDir)external\ebpf-verifier\build\$(Configuration);%(AdditionalLibraryDirectories) + $(OutDir) diff --git a/src/tools/netsh/elf.cpp b/src/tools/netsh/elf.cpp index 4a554b1ec..4587115d2 100644 --- a/src/tools/netsh/elf.cpp +++ b/src/tools/netsh/elf.cpp @@ -76,6 +76,7 @@ DWORD handle_ebpf_show_disassembly( else { std::cout << disassembly << std::endl; + ebpf_api_free_error_message(disassembly); return NO_ERROR; } } @@ -156,50 +157,46 @@ DWORD handle_ebpf_show_sections( { std::cerr << error_message << std::endl; ebpf_api_free_error_message(error_message); + ebpf_api_elf_free(section_data); return ERROR_SUPPRESS_OUTPUT; } - try { + if (level == VL_NORMAL) { + std::cout << "\n"; + std::cout << " Section Type # Maps Size\n"; + std::cout << "==================== ====== ====== ======\n"; + } + for (auto current_section = tlv_child(section_data); current_section != tlv_next(section_data); current_section = tlv_next(current_section)) + { + auto section_name = tlv_child(current_section); + auto type = tlv_next(section_name); + auto map_count = tlv_next(type); + auto program_bytes = tlv_next(map_count); + auto stats_secton = tlv_next(program_bytes); if (level == VL_NORMAL) { - std::cout << "\n"; - std::cout << " Section Type # Maps Size\n"; - std::cout << "==================== ====== ====== ======\n"; + std::cout << std::setw(20) << std::right << tlv_value(section_name) << " " << + std::setw(6) << tlv_value(type) << " " << + std::setw(6) << tlv_value(map_count) << " " << + std::setw(6) << (program_bytes->length - offsetof(tlv_type_length_value_t, value)) / 8 << "\n"; } - for (auto current_section = tlv_child(section_data); current_section != tlv_next(section_data); current_section = tlv_next(current_section)) + else { - auto section_name = tlv_child(current_section); - auto type = tlv_next(section_name); - auto map_count = tlv_next(type); - auto program_bytes = tlv_next(map_count); - auto stats_secton = tlv_next(program_bytes); - if (level == VL_NORMAL) { - std::cout << std::setw(20) << std::right << tlv_value(section_name) << " " << - std::setw(6) << tlv_value(type) << " " << - std::setw(6) << tlv_value(map_count) << " " << - std::setw(6) << (program_bytes->length - offsetof(tlv_type_length_value_t, value)) / 8 << "\n"; - } - else + std::cout << "\n"; + std::cout << "Section : " << tlv_value(section_name) << "\n"; + std::cout << "Type : " << tlv_value(type) << "\n"; + std::cout << "# Maps : " << tlv_value(map_count) << "\n"; + std::cout << "Size : " << program_bytes->length - offsetof(tlv_type_length_value_t, value) / 8 << " instructions\n"; + for (auto stat = tlv_child(stats_secton); stat != tlv_next(current_section); stat = tlv_next(stat)) { - std::cout << "\n"; - std::cout << "Section : " << tlv_value(section_name) << "\n"; - std::cout << "Type : " << tlv_value(type) << "\n"; - std::cout << "# Maps : " << tlv_value(map_count) << "\n"; - std::cout << "Size : " << program_bytes->length - offsetof(tlv_type_length_value_t, value) / 8 << " instructions\n"; - for (auto stat = tlv_child(stats_secton); stat != tlv_next(current_section); stat = tlv_next(stat)) - { - auto key = tlv_child(stat); - auto value = tlv_next(key); - std::cout << std::setw(13) << std::left << tlv_value(key) << ": " << tlv_value(value) << "\n"; - } + auto key = tlv_child(stat); + auto value = tlv_next(key); + std::cout << std::setw(13) << std::left << tlv_value(key) << ": " << tlv_value(value) << "\n"; } } + } - return NO_ERROR; - } - catch (std::runtime_error e) { - std::cerr << "error: " << e.what() << std::endl; - return ERROR_SUPPRESS_OUTPUT; - } + ebpf_api_elf_free(section_data); + return NO_ERROR; } DWORD handle_ebpf_show_verification( @@ -271,5 +268,8 @@ DWORD handle_ebpf_show_verification( { std::cerr << "\nVerification report:\n" << report << std::endl; } + ebpf_api_free_error_message(error_message); + ebpf_api_free_error_message(report); + return ERROR_SUPPRESS_OUTPUT; } } diff --git a/src/tools/netsh/programs.cpp b/src/tools/netsh/programs.cpp index 1a3dfcede..14dbf7f72 100644 --- a/src/tools/netsh/programs.cpp +++ b/src/tools/netsh/programs.cpp @@ -32,6 +32,12 @@ static TOKEN_VALUE _ebpf_program_type_enum[] = { }; +static TOKEN_VALUE _ebpf_execution_type_enum[] = { + { L"jit", EBPF_EXECUTION_JIT }, + { L"interpret", EBPF_EXECUTION_INTERPRET }, + +}; + unsigned long handle_ebpf_add_program( LPCWSTR machine, LPWSTR* argv, @@ -46,6 +52,7 @@ unsigned long handle_ebpf_add_program( {TOKEN_SECTION, NS_REQ_ZERO, FALSE}, {TOKEN_TYPE, NS_REQ_ZERO, FALSE}, {TOKEN_PINNED, NS_REQ_ZERO, FALSE}, + {TOKEN_EXECUTION, NS_REQ_ZERO, FALSE } }; ULONG tag_type[_countof(tags)] = { 0 }; @@ -63,6 +70,7 @@ unsigned long handle_ebpf_add_program( std::string section = ""; // Use the first code section by default. ebpf_program_type_t type = EBPF_PROGRAM_TYPE_XDP; PINNED_CONSTRAINT pinned = PINNED_ANY; + ebpf_execution_type_t execution = EBPF_EXECUTION_JIT; for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) { switch (tag_type[i]) { case 0: // FILENAME @@ -97,6 +105,13 @@ unsigned long handle_ebpf_add_program( status = ERROR_INVALID_PARAMETER; } break; + case 4: // EXECUTION + status = MatchEnumTag(NULL, + argv[current_index + i], + _countof(_ebpf_execution_type_enum), + _ebpf_execution_type_enum, + (PULONG)&execution); + break; default: status = ERROR_INVALID_SYNTAX; break; @@ -115,7 +130,7 @@ unsigned long handle_ebpf_add_program( const char* error_message = nullptr; - status = ebpf_api_load_program(filename.c_str(), section.c_str(), &_program_handle, &error_message); + status = ebpf_api_load_program(filename.c_str(), section.c_str(), execution, &_program_handle, &error_message); if (status != ERROR_SUCCESS) { if (error_message != nullptr) { @@ -123,6 +138,7 @@ unsigned long handle_ebpf_add_program( } else { std::cerr << "error " << status << ": could not load program" << std::endl; } + ebpf_api_free_error_message(error_message); return ERROR_SUPPRESS_OUTPUT; } diff --git a/src/tools/netsh/tokens.h b/src/tools/netsh/tokens.h index 62a97b123..4fe6b4916 100644 --- a/src/tools/netsh/tokens.h +++ b/src/tools/netsh/tokens.h @@ -7,6 +7,7 @@ #define TOKEN_SECTION L"section" #define TOKEN_PINNED L"pinned" #define TOKEN_TYPE L"type" +#define TOKEN_EXECUTION L"execution" typedef enum { VL_NORMAL = 0,