diff --git a/src/ebpf/api/Source.def b/src/ebpf/api/Source.def new file mode 100644 index 000000000..75be5a4c3 --- /dev/null +++ b/src/ebpf/api/Source.def @@ -0,0 +1,10 @@ +LIBRARY +EXPORTS + EbpfApiInit + EbpfApiTerminate + EbpfLoadProgram + EbpfFreeErrorMessage + EbpfUnloadProgram + EbpfAttachProgram + EbpfDetachProgram + diff --git a/src/ebpf/api/api.h b/src/ebpf/api/api.h deleted file mode 100644 index f582df86e..000000000 --- a/src/ebpf/api/api.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved - * SPDX-License-Identifier: MIT -*/ - -#pragma once - -#if defined(EBPF_API) -#define DLL __declspec(dllexport) -#else -#define DLL __declspec(dllimport) -#endif - -#define EBPF_HOOK_POINT_XDP 1 - -DLL DWORD EbpfApiInit(); - -DLL void EbpfApiTerminate(); - -DLL DWORD EbpfLoadProgram(const char* file, const char* section_name, HANDLE* handle, char ** error_message); -DLL void EbpfFreeErrorMessage(char* error_message); -DLL void EbpfUnloadProgram(HANDLE handle); - -DLL DWORD EbpfAttachProgram(HANDLE handle, DWORD hook_point); -DLL DWORD EbpfDetachProgram(HANDLE handle, DWORD hook_point); diff --git a/src/ebpf/api/dllmain.cpp b/src/ebpf/api/dllmain.cpp index d5082a9b2..addcd0007 100644 --- a/src/ebpf/api/dllmain.cpp +++ b/src/ebpf/api/dllmain.cpp @@ -22,3 +22,57 @@ BOOL APIENTRY DllMain( HMODULE hModule, return TRUE; } + +namespace Platform { + BOOL + DeviceIoControl( + _In_ HANDLE hDevice, + _In_ DWORD dwIoControlCode, + _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer, + _In_ DWORD nInBufferSize, + _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, + _In_ DWORD nOutBufferSize, + _Out_opt_ LPDWORD lpBytesReturned, + _Inout_opt_ LPOVERLAPPED lpOverlapped + ) + { + return ::DeviceIoControl( + hDevice, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesReturned, + lpOverlapped); + } + + HANDLE + CreateFileW( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile + ) + { + return ::CreateFileW( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + } + BOOL + CloseHandle( + _In_ _Post_ptr_invalid_ HANDLE hObject + ) + { + return ::CloseHandle(hObject); + } + +} \ No newline at end of file diff --git a/src/ebpf/api/ebpfapi.sln b/src/ebpf/api/ebpfapi.sln index d9b563634..5238dac29 100644 --- a/src/ebpf/api/ebpfapi.sln +++ b/src/ebpf/api/ebpfapi.sln @@ -3,12 +3,16 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfapi", "ebpfapi.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "EbpfApi.vcxproj", "{75FE223A-3E45-4B0E-A2E8-04285E52E440}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api", "..\libs\api\api.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EbpfJitterDemoLib", "..\libs\EbpfJitterDemoLib\EbpfJitterDemoLib.vcxproj", "{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfverifier", "..\..\..\external\ebpf-verifier\build\ebpfverifier.vcxproj", "{939A079D-A1E8-35D9-950F-11B1894D342E}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "..\libs\api\test\test.vcxproj", "{4C10AC76-384C-4539-B884-38E998749FB2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,14 +25,30 @@ Global RelWithDebInfo|x86 = RelWithDebInfo|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x64.ActiveCfg = Debug|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x64.Build.0 = Debug|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x86.ActiveCfg = Debug|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Debug|x86.Build.0 = Debug|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x64.ActiveCfg = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x64.Build.0 = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x86.ActiveCfg = Release|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.MinSizeRel|x86.Build.0 = Release|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x64.ActiveCfg = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x64.Build.0 = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x86.ActiveCfg = Release|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.Release|x86.Build.0 = Release|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x64.Build.0 = Release|x64 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 + {75FE223A-3E45-4B0E-A2E8-04285E52E440}.RelWithDebInfo|x86.Build.0 = Release|Win32 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.ActiveCfg = Debug|x64 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.Build.0 = Debug|x64 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.ActiveCfg = Debug|Win32 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.Build.0 = Debug|Win32 - {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Release|x64 - {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Release|x64 - {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Release|Win32 - {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Debug|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Debug|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Debug|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Debug|Win32 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.ActiveCfg = Release|x64 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.Build.0 = Release|x64 {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.ActiveCfg = Release|Win32 @@ -41,10 +61,10 @@ Global {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.Build.0 = Debug|x64 {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.ActiveCfg = Debug|Win32 {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.Build.0 = Debug|Win32 - {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Release|x64 - {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Release|x64 - {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Release|Win32 - {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Release|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Debug|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Debug|Win32 {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.ActiveCfg = Release|x64 {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.Build.0 = Release|x64 {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.ActiveCfg = Release|Win32 @@ -65,11 +85,27 @@ Global {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.ActiveCfg = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.Build.0 = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.ActiveCfg = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.Build.0 = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.ActiveCfg = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.Build.0 = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.ActiveCfg = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.Build.0 = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.ActiveCfg = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.Build.0 = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.ActiveCfg = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.Build.0 = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.Build.0 = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9DEA0F2A-7674-46AA-9E15-BC880EF5895D} + SolutionGuid = {24EA473A-CDF1-4A87-9E6C-57149BE1EAC0} EndGlobalSection EndGlobal diff --git a/src/ebpf/api/ebpfapi.vcxproj b/src/ebpf/api/ebpfapi.vcxproj index 133ee0cf3..2e5d5b4d1 100644 --- a/src/ebpf/api/ebpfapi.vcxproj +++ b/src/ebpf/api/ebpfapi.vcxproj @@ -21,10 +21,10 @@ 16.0 Win32Proj - {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68} - ebpfapi + {75fe223a-3e45-4b0e-a2e8-04285e52e440} + EbpfApi 10.0 - $(ProjectDir)../../../external/ebpf-verifier/ + dll @@ -79,9 +79,11 @@ true + EbpfApi false + EbpfApi @@ -96,6 +98,7 @@ Windows true false + Source.def @@ -115,6 +118,7 @@ true true false + Source.def @@ -125,13 +129,12 @@ true Use pch.h - $(PrevailDir)src;..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) - stdcpp17 Windows true false + Source.def @@ -144,8 +147,7 @@ true Use pch.h - $(PrevailDir)src;..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) - stdcpp17 + ..\libs\api;%(AdditionalIncludeDirectories) Windows @@ -153,17 +155,14 @@ true true false + Source.def - - - - Create @@ -171,29 +170,22 @@ Create Create - - NotUsing - {939a079d-a1e8-35d9-950f-11b1894d342e} + + {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68} + {245f0ec7-1ebc-4d68-8b1f-f758ea9196ae} - + - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - \ No newline at end of file diff --git a/src/ebpf/api/ebpfapi.vcxproj.filters b/src/ebpf/api/ebpfapi.vcxproj.filters index e4556dd75..3bc758dad 100644 --- a/src/ebpf/api/ebpfapi.vcxproj.filters +++ b/src/ebpf/api/ebpfapi.vcxproj.filters @@ -21,15 +21,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - @@ -38,14 +29,10 @@ Source Files - - Source Files - - - Source Files - - + + Source Files + \ No newline at end of file diff --git a/src/ebpf/api/framework.h b/src/ebpf/api/framework.h index 6890eb25b..54b83e94f 100644 --- a/src/ebpf/api/framework.h +++ b/src/ebpf/api/framework.h @@ -1,18 +1,5 @@ -/* - * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved - * SPDX-License-Identifier: MIT -*/ - #pragma once -#include -#include -#include -#include - #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files #include -#include - - diff --git a/src/ebpf/api/pch.h b/src/ebpf/api/pch.h index c9343d163..885d5d62e 100644 --- a/src/ebpf/api/pch.h +++ b/src/ebpf/api/pch.h @@ -1,7 +1,8 @@ -/* - * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved - * SPDX-License-Identifier: MIT -*/ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. #ifndef PCH_H #define PCH_H diff --git a/src/ebpf/api/UnwindHelper.h b/src/ebpf/libs/api/UnwindHelper.h similarity index 100% rename from src/ebpf/api/UnwindHelper.h rename to src/ebpf/libs/api/UnwindHelper.h diff --git a/src/ebpf/api/Verifier.cpp b/src/ebpf/libs/api/Verifier.cpp similarity index 82% rename from src/ebpf/api/Verifier.cpp rename to src/ebpf/libs/api/Verifier.cpp index 312f5967f..fa183e5ef 100644 --- a/src/ebpf/api/Verifier.cpp +++ b/src/ebpf/libs/api/Verifier.cpp @@ -22,6 +22,15 @@ int get_file_size(char* filename, size_t* byte_code_size) return result; } +static char * allocate_error_string(const std::string& str) +{ + char* retval; + size_t error_message_length = str.size() + 1; + retval = (char*)malloc(error_message_length); + strcpy_s(retval, error_message_length, str.c_str()); + return retval; // Error; +} + static int analyze(raw_program& raw_prog, char ** error_message) { std::ostringstream oss; @@ -29,15 +38,15 @@ static int analyze(raw_program& raw_prog, char ** error_message) std::variant prog_or_error = unmarshal(raw_prog, platform); if (!std::holds_alternative(prog_or_error)) { + *error_message = allocate_error_string(std::get(prog_or_error)); return 1; // Error; } auto& prog = std::get(prog_or_error); cfg_t cfg = prepare_cfg(prog, raw_prog.info, true); - bool res = run_ebpf_analysis(oss, cfg, raw_prog.info, nullptr); + ebpf_verifier_options_t options{ true, false, true }; + bool res = run_ebpf_analysis(oss, cfg, raw_prog.info, &options); if (!res) { - size_t error_message_length = oss.str().size() + 1; - *error_message = (char*)malloc(error_message_length); - strcpy_s(*error_message, error_message_length, oss.str().c_str()); + *error_message = allocate_error_string(oss.str()); return 1; // Error; } return 0; // Success. diff --git a/src/ebpf/api/Verifier.h b/src/ebpf/libs/api/Verifier.h similarity index 100% rename from src/ebpf/api/Verifier.h rename to src/ebpf/libs/api/Verifier.h diff --git a/src/ebpf/api/api.cpp b/src/ebpf/libs/api/api.cpp similarity index 87% rename from src/ebpf/api/api.cpp rename to src/ebpf/libs/api/api.cpp index 3ebb07db3..d57de881b 100644 --- a/src/ebpf/api/api.cpp +++ b/src/ebpf/libs/api/api.cpp @@ -4,6 +4,7 @@ */ #include "pch.h" +#include "platform.h" #define EBPF_API extern "C" { @@ -14,6 +15,7 @@ extern "C" #include "protocol.h" #include "UnwindHelper.h" +#include #include "Verifier.h" #define MAX_CODE_SIZE (32 * 1024) // 32 KB @@ -66,7 +68,7 @@ static DWORD invoke_ioctl(HANDLE handle, request_t request, reply_t reply) reply_ptr = reply; } - auto result = DeviceIoControl( + auto result = Platform::DeviceIoControl( handle, (DWORD)IOCTL_EBPFCTL_METHOD_BUFFERED, request_ptr, @@ -76,12 +78,17 @@ static DWORD invoke_ioctl(HANDLE handle, request_t request, reply_t reply) &actual_reply_size, nullptr); + if (!result) + { + return GetLastError(); + } + if (actual_reply_size != reply_size) { return ERROR_INVALID_PARAMETER; } - return result; + return ERROR_SUCCESS; } DWORD EbpfApiInit() @@ -93,7 +100,7 @@ DWORD EbpfApiInit() return ERROR_ALREADY_INITIALIZED; } - device_handle = CreateFile(ebpfDeviceName, + device_handle = Platform::CreateFile(ebpfDeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, @@ -113,7 +120,7 @@ void EbpfApiTerminate() { if (device_handle != INVALID_HANDLE_VALUE) { - CloseHandle(device_handle); + Platform::CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE; } } @@ -175,9 +182,23 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL DWORD result; - // Verify code. - if (verify(file_name, section_name, byte_code.data(), &byte_code_size, error_message) != 0) + try { + // Verify code. + if (verify(file_name, section_name, byte_code.data(), &byte_code_size, error_message) != 0) + { + return ERROR_INVALID_PARAMETER; + } + } + catch (std::runtime_error & err) + { + auto message = err.what(); + auto message_length = strlen(message) + 1; + *error_message = reinterpret_cast(calloc(message_length + 1, sizeof(char))); + if (*error_message) + { + strcpy_s(*error_message, message_length, message); + } return ERROR_INVALID_PARAMETER; } @@ -187,11 +208,7 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL { return ERROR_OUTOFMEMORY; } - - if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), error_message) < 0) - { - return ERROR_INVALID_PARAMETER; - } + byte_code.resize(byte_code_size); if (ubpf_register_map_resolver(vm, device_handle, map_resolver) < 0) { @@ -203,6 +220,11 @@ DLL DWORD EbpfLoadProgram(const char* file_name, const char* section_name, HANDL return ERROR_INVALID_PARAMETER; } + if (ubpf_load(vm, byte_code.data(), static_cast(byte_code.size()), error_message) < 0) + { + return ERROR_INVALID_PARAMETER; + } + if (ubpf_translate(vm, machine_code.data(), &machine_code_size, error_message)) { return ERROR_INVALID_PARAMETER; diff --git a/src/ebpf/libs/api/api.h b/src/ebpf/libs/api/api.h new file mode 100644 index 000000000..98446bd1b --- /dev/null +++ b/src/ebpf/libs/api/api.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved + * SPDX-License-Identifier: MIT +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(EBPF_API) +#define DLL __declspec(dllexport) +#else +#define DLL __declspec(dllimport) +#endif + +#define EBPF_HOOK_POINT_XDP 1 + + DLL DWORD EbpfApiInit(); + + DLL void EbpfApiTerminate(); + + DLL DWORD EbpfLoadProgram(const char* file, const char* section_name, HANDLE* handle, char** error_message); + DLL void EbpfFreeErrorMessage(char* error_message); + DLL void EbpfUnloadProgram(HANDLE handle); + + DLL DWORD EbpfAttachProgram(HANDLE handle, DWORD hook_point); + DLL DWORD EbpfDetachProgram(HANDLE handle, DWORD hook_point); + +#ifdef __cplusplus +} +#endif diff --git a/src/ebpf/libs/api/api.vcxproj b/src/ebpf/libs/api/api.vcxproj new file mode 100644 index 000000000..ce967b704 --- /dev/null +++ b/src/ebpf/libs/api/api.vcxproj @@ -0,0 +1,191 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68} + ebpfapi + 10.0 + $(ProjectDir)../../../../external/ebpf-verifier/ + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + StaticLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + $(PrevailDir)src;..\..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) + stdcpp17 + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;EBPFAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + $(PrevailDir)src;..\..\..\..\external\ubpf\vm\inc;%(AdditionalIncludeDirectories) + stdcpp17 + + + Windows + true + true + true + false + + + + + + + + + + + + + + Create + Create + Create + Create + + + NotUsing + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/ebpf/libs/api/ebpfapi.sln b/src/ebpf/libs/api/ebpfapi.sln new file mode 100644 index 000000000..396c2bc03 --- /dev/null +++ b/src/ebpf/libs/api/ebpfapi.sln @@ -0,0 +1,93 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfapi", "ebpfapi.vcxproj", "{C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EbpfJitterDemoLib", "..\EbpfJitterDemoLib\EbpfJitterDemoLib.vcxproj", "{245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ebpfverifier", "..\..\..\..\external\ebpf-verifier\build\ebpfverifier.vcxproj", "{939A079D-A1E8-35D9-950F-11B1894D342E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{4C10AC76-384C-4539-B884-38E998749FB2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + MinSizeRel|x64 = MinSizeRel|x64 + MinSizeRel|x86 = MinSizeRel|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + RelWithDebInfo|x64 = RelWithDebInfo|x64 + RelWithDebInfo|x86 = RelWithDebInfo|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.ActiveCfg = Debug|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x64.Build.0 = Debug|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.ActiveCfg = Debug|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Debug|x86.Build.0 = Debug|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.ActiveCfg = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x64.Build.0 = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.ActiveCfg = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.MinSizeRel|x86.Build.0 = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.ActiveCfg = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x64.Build.0 = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.ActiveCfg = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.Release|x86.Build.0 = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x64.Build.0 = Release|x64 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 + {C8BF60C3-40A9-43AD-891A-8AA34F1C3A68}.RelWithDebInfo|x86.Build.0 = Release|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.ActiveCfg = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x64.Build.0 = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.ActiveCfg = Debug|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Debug|x86.Build.0 = Debug|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.ActiveCfg = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x64.Build.0 = Debug|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.ActiveCfg = Debug|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.MinSizeRel|x86.Build.0 = Debug|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.ActiveCfg = Release|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x64.Build.0 = Release|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.ActiveCfg = Release|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.Release|x86.Build.0 = Release|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x64.Build.0 = Release|x64 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 + {245F0EC7-1EBC-4D68-8B1F-F758EA9196AE}.RelWithDebInfo|x86.Build.0 = Release|Win32 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x64.ActiveCfg = Debug|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x64.Build.0 = Debug|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Debug|x86.ActiveCfg = Debug|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x64.ActiveCfg = Release|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x64.Build.0 = Release|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.Release|x86.ActiveCfg = Release|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 + {939A079D-A1E8-35D9-950F-11B1894D342E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.ActiveCfg = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x64.Build.0 = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.ActiveCfg = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Debug|x86.Build.0 = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.ActiveCfg = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x64.Build.0 = Debug|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.ActiveCfg = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.MinSizeRel|x86.Build.0 = Debug|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.ActiveCfg = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x64.Build.0 = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.ActiveCfg = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.Release|x86.Build.0 = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.ActiveCfg = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x64.Build.0 = Release|x64 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 + {4C10AC76-384C-4539-B884-38E998749FB2}.RelWithDebInfo|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9DEA0F2A-7674-46AA-9E15-BC880EF5895D} + EndGlobalSection +EndGlobal diff --git a/src/ebpf/libs/api/ebpfapi.vcxproj.filters b/src/ebpf/libs/api/ebpfapi.vcxproj.filters new file mode 100644 index 000000000..9b4362409 --- /dev/null +++ b/src/ebpf/libs/api/ebpfapi.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/src/ebpf/libs/api/framework.h b/src/ebpf/libs/api/framework.h new file mode 100644 index 000000000..6890eb25b --- /dev/null +++ b/src/ebpf/libs/api/framework.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved + * SPDX-License-Identifier: MIT +*/ + +#pragma once + +#include +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include +#include + + diff --git a/src/ebpf/api/packages.config b/src/ebpf/libs/api/packages.config similarity index 100% rename from src/ebpf/api/packages.config rename to src/ebpf/libs/api/packages.config diff --git a/src/ebpf/libs/api/pch.cpp b/src/ebpf/libs/api/pch.cpp new file mode 100644 index 000000000..64b7eef6d --- /dev/null +++ b/src/ebpf/libs/api/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/src/ebpf/libs/api/pch.h b/src/ebpf/libs/api/pch.h new file mode 100644 index 000000000..c9343d163 --- /dev/null +++ b/src/ebpf/libs/api/pch.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved + * SPDX-License-Identifier: MIT +*/ + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#include "framework.h" + +#endif //PCH_H diff --git a/src/ebpf/libs/api/platform.h b/src/ebpf/libs/api/platform.h new file mode 100644 index 000000000..72f9224be --- /dev/null +++ b/src/ebpf/libs/api/platform.h @@ -0,0 +1,35 @@ +#pragma once +/* + * Copyright (C) 2020, Microsoft Corporation, All Rights Reserved + * SPDX-License-Identifier: MIT +*/ +namespace Platform +{ + BOOL + DeviceIoControl( + _In_ HANDLE hDevice, + _In_ DWORD dwIoControlCode, + _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer, + _In_ DWORD nInBufferSize, + _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, + _In_ DWORD nOutBufferSize, + _Out_opt_ LPDWORD lpBytesReturned, + _Inout_opt_ LPOVERLAPPED lpOverlapped + ); + + HANDLE + CreateFileW( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile + ); + + BOOL + CloseHandle( + _In_ _Post_ptr_invalid_ HANDLE hObject + ); +} diff --git a/src/ebpf/api/protocol.h b/src/ebpf/libs/api/protocol.h similarity index 100% rename from src/ebpf/api/protocol.h rename to src/ebpf/libs/api/protocol.h diff --git a/src/ebpf/libs/api/test/bpf.c b/src/ebpf/libs/api/test/bpf.c new file mode 100644 index 000000000..2c07eca6d --- /dev/null +++ b/src/ebpf/libs/api/test/bpf.c @@ -0,0 +1,6 @@ +#pragma clang section text="xdp_prog" +int func() +{ + return 42; +} + diff --git a/src/ebpf/libs/api/test/bpf.o b/src/ebpf/libs/api/test/bpf.o new file mode 100644 index 000000000..3595a96b1 Binary files /dev/null and b/src/ebpf/libs/api/test/bpf.o differ diff --git a/src/ebpf/libs/api/test/bpf_call.c b/src/ebpf/libs/api/test/bpf_call.c new file mode 100644 index 000000000..fb7085129 --- /dev/null +++ b/src/ebpf/libs/api/test/bpf_call.c @@ -0,0 +1,21 @@ +#pragma clang section text="xdp_prog" + +typedef int (*bpf_helper)(int a, int b, int c, int d); + +#define ebpf_map_lookup_elem ((bpf_helper)0) +#define ebpf_map_update_elem ((bpf_helper)1) +#define ebpf_map_delete_elem ((bpf_helper)2) +#define ebpf_get_tick_count ((bpf_helper)3) + +typedef struct xdp_md +{ + unsigned char* data; + unsigned char* data_end; + unsigned char* data_meta; +} xdp_md; + +int func(xdp_md * ctx) +{ + return ebpf_get_tick_count(ctx, 0, 0, 0); +} + diff --git a/src/ebpf/libs/api/test/bpf_call.o b/src/ebpf/libs/api/test/bpf_call.o new file mode 100644 index 000000000..eaa3a326c Binary files /dev/null and b/src/ebpf/libs/api/test/bpf_call.o differ diff --git a/src/ebpf/libs/api/test/mock.cpp b/src/ebpf/libs/api/test/mock.cpp new file mode 100644 index 000000000..21243308d --- /dev/null +++ b/src/ebpf/libs/api/test/mock.cpp @@ -0,0 +1,58 @@ +#include "mock.h" +std::function create_file_handler; +std::function device_io_control_handler; +std::function close_handle_handler; + +namespace Platform { + BOOL + DeviceIoControl( + _In_ HANDLE hDevice, + _In_ DWORD dwIoControlCode, + _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer, + _In_ DWORD nInBufferSize, + _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, + _In_ DWORD nOutBufferSize, + _Out_opt_ LPDWORD lpBytesReturned, + _Inout_opt_ LPOVERLAPPED lpOverlapped + ) + { + return device_io_control_handler( + hDevice, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesReturned, + lpOverlapped); + } + + HANDLE + CreateFileW( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile + ) + { + return create_file_handler( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + } + BOOL + CloseHandle( + _In_ _Post_ptr_invalid_ HANDLE hObject + ) + { + return close_handle_handler(hObject); + } + +} \ No newline at end of file diff --git a/src/ebpf/libs/api/test/mock.h b/src/ebpf/libs/api/test/mock.h new file mode 100644 index 000000000..e29105dc3 --- /dev/null +++ b/src/ebpf/libs/api/test/mock.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include + +extern std::function create_file_handler; +extern std::function device_io_control_handler; +extern std::function close_handle_handler; diff --git a/src/ebpf/libs/api/test/packages.config b/src/ebpf/libs/api/test/packages.config new file mode 100644 index 000000000..448cd1e38 --- /dev/null +++ b/src/ebpf/libs/api/test/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/ebpf/libs/api/test/resource.h b/src/ebpf/libs/api/test/resource.h new file mode 100644 index 000000000..d6780c176 --- /dev/null +++ b/src/ebpf/libs/api/test/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by test.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/ebpf/libs/api/test/test.aps b/src/ebpf/libs/api/test/test.aps new file mode 100644 index 000000000..caeafab52 Binary files /dev/null and b/src/ebpf/libs/api/test/test.aps differ diff --git a/src/ebpf/libs/api/test/test.cpp b/src/ebpf/libs/api/test/test.cpp new file mode 100644 index 000000000..a952bc0bd --- /dev/null +++ b/src/ebpf/libs/api/test/test.cpp @@ -0,0 +1,259 @@ +// test.cpp : This file contains the 'main' function. Program execution begins and ends there. +// + +#include +#include +#include +#include +#include +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +#define EBPF_API +#include "../api.h" +#include "mock.h" +#include "../protocol.h" + +uint8_t h = 0; +auto success_create_file_handler = [&](_In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile) -> HANDLE +{ + SetLastError(ERROR_SUCCESS); + return reinterpret_cast(&h); +}; +auto success_close_handle_handler = [&](_In_ HANDLE hObject) -> BOOL +{ + if (hObject != &h) + { + throw std::exception("Test failed - closing wrong handle"); + } + return TRUE; +}; + +std::list> request_messages; +std::list> reply_messages; + +auto success_ioctl = [&](_In_ HANDLE hDevice, + _In_ DWORD dwIoControlCode, + _In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer, + _In_ DWORD nInBufferSize, + _Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, + _In_ DWORD nOutBufferSize, + _Out_opt_ LPDWORD lpBytesReturned, + _Inout_opt_ LPOVERLAPPED lpOverlapped + ) -> BOOL +{ + if (hDevice != &h) + { + throw std::exception("Test failed - using wrong handle"); + } + + if (reply_messages.empty()) + { + throw std::exception("Test failed - no reply message queue"); + } + + auto in_begin = reinterpret_cast(lpInBuffer); + auto in_end = in_begin + nInBufferSize; + auto out_begin = reinterpret_cast(lpOutBuffer); + auto out_end = out_begin + nOutBufferSize; + + std::vector request; + std::vector& reply = reply_messages.front(); + if (reply.size() > nOutBufferSize) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + *lpBytesReturned = static_cast(reply.size()); + + request.resize(nInBufferSize); + std::copy(in_begin, in_end, request.begin()); + std::copy(reply.begin(), reply.end(), out_begin); + + reply_messages.pop_front(); + request_messages.emplace_back(std::move(request)); + + return TRUE; +}; + +void push_back_reply_message(EbpfOpHeader* header) +{ + std::vector reply(header->length); + + std::copy(reinterpret_cast(header), reinterpret_cast(header) + header->length, reply.begin()); + reply_messages.emplace_back(std::move(reply)); +} + +template +request_message_t* front_request_message() +{ + auto message = reinterpret_cast(request_messages.front().data()); + size_t expected_size = 0; + EbpfOperation expected_id = (EbpfOperation)-1; + if constexpr (std::is_same::value) { + expected_size = sizeof(EbpfOpEvidenceRequest); + expected_id = EbpfOperation::evidence; + } + else if constexpr (std::is_same::value) { + expected_size = sizeof(EbpfOpResolveHelperRequest); + expected_id = EbpfOperation::resolve_helper; + } + else if constexpr (std::is_same::value) { + expected_size = sizeof(EbpfOpResolveMapRequest); + expected_id = EbpfOperation::resolve_map; + } + else if constexpr (std::is_same::value) { + expected_id = EbpfOperation::load_code; + } + else if constexpr (std::is_same::value) { + expected_size = sizeof(EbpfOpAttachDetachRequest); + switch (message->header.id) { + case EbpfOperation::attach: + case EbpfOperation::detach: + break; + default: + REQUIRE(message->header.id == EbpfOperation::attach); + break; + } + } + if (expected_id != (EbpfOperation)-1) + REQUIRE(expected_id == message->header.id); + + if (expected_size > 0) + REQUIRE(expected_size == message->header.length); + return message; +} + +TEST_CASE("Open failed", "[open_fail]") { + create_file_handler = [](_In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile) -> HANDLE { + SetLastError(ERROR_FILE_NOT_FOUND); + return INVALID_HANDLE_VALUE; + }; + + close_handle_handler = [](_In_ HANDLE hObject) -> BOOL { + throw std::exception("Test failed - closing handle not opened"); + }; + + REQUIRE(EbpfApiInit() == ERROR_FILE_NOT_FOUND); + EbpfApiTerminate(); +} + +TEST_CASE("Open success", "[open_success]") { + create_file_handler = success_create_file_handler; + close_handle_handler = success_close_handle_handler; + + REQUIRE(EbpfApiInit() == ERROR_SUCCESS); + EbpfApiTerminate(); +} + +TEST_CASE("Load program fail - file not found", "[load_fail_not_found]") { + create_file_handler = success_create_file_handler; + close_handle_handler = success_close_handle_handler; + + HANDLE handle; + char* error_message = nullptr; + const char* fake_file_name = "not_a_real_file.elf"; + + REQUIRE(EbpfApiInit() == ERROR_SUCCESS); + + REQUIRE(EbpfLoadProgram(fake_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER); + REQUIRE_THAT(error_message, Catch::Matchers::Contains(fake_file_name)); + EbpfFreeErrorMessage(error_message); + EbpfApiTerminate(); +} + +TEST_CASE("Load program fail - malformed", "[load_fail_bad_file]") { + create_file_handler = success_create_file_handler; + close_handle_handler = success_close_handle_handler; + + char temp_file_name[MAX_PATH]; + REQUIRE(GetTempFileNameA(".", "bad_elf", 0, temp_file_name) != 0); + + HANDLE handle; + char* error_message = nullptr; + + std::fstream out_file(temp_file_name, std::ios_base::out | std::ios_base::trunc); + std::default_random_engine generator; + std::uniform_int_distribution distribution(0, 255); + + for (size_t i = 0; i < 4096; i++) + { + out_file.put(static_cast(distribution(generator))); + } + out_file.flush(); + out_file.close(); + + REQUIRE(EbpfApiInit() == ERROR_SUCCESS); + + REQUIRE(EbpfLoadProgram(temp_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER); + REQUIRE_THAT(error_message, Catch::Matchers::Contains(temp_file_name)); + EbpfFreeErrorMessage(error_message); + EbpfApiTerminate(); + + DeleteFileA(temp_file_name); +} + +TEST_CASE("Load program success", "[load_success]") { + create_file_handler = success_create_file_handler; + close_handle_handler = success_close_handle_handler; + device_io_control_handler = success_ioctl; + + HANDLE handle; + char* error_message = nullptr; + + EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast(&h) }; + push_back_reply_message(&load_reply.header); + + REQUIRE(EbpfApiInit() == ERROR_SUCCESS); + + REQUIRE(EbpfLoadProgram("bpf.o", "xdp_prog", &handle, &error_message) == ERROR_SUCCESS); + + auto load_request = front_request_message(); + + request_messages.clear(); + + EbpfFreeErrorMessage(error_message); + EbpfApiTerminate(); +} + +TEST_CASE("Load program success - resolve helper", "[load_success - resolve helper]") { + create_file_handler = success_create_file_handler; + close_handle_handler = success_close_handle_handler; + device_io_control_handler = success_ioctl; + + HANDLE handle; + char* error_message = nullptr; + + EbpfOpResolveHelperReply helper_reply{ sizeof(EbpfOpResolveHelperReply), EbpfOperation::resolve_helper, reinterpret_cast(&GetTickCount) }; + push_back_reply_message(&helper_reply.header); + + EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast(&h) }; + push_back_reply_message(&load_reply.header); + + REQUIRE(EbpfApiInit() == ERROR_SUCCESS); + + REQUIRE(EbpfLoadProgram("bpf_call.o", "xdp_prog", &handle, &error_message) == 0); + + auto resolve_request = front_request_message(); + REQUIRE(resolve_request->helper_id[0] == 3); + request_messages.pop_front(); + + auto load_request = front_request_message(); + request_messages.pop_front(); + + EbpfFreeErrorMessage(error_message); + EbpfApiTerminate(); +} \ No newline at end of file diff --git a/src/ebpf/libs/api/test/test.rc b/src/ebpf/libs/api/test/test.rc new file mode 100644 index 000000000..3b3fdcbfd --- /dev/null +++ b/src/ebpf/libs/api/test/test.rc @@ -0,0 +1,60 @@ +// Microsoft Visual C++ generated resource script. +// + +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/ebpf/libs/api/test/test.vcxproj b/src/ebpf/libs/api/test/test.vcxproj new file mode 100644 index 000000000..93f11c2fd --- /dev/null +++ b/src/ebpf/libs/api/test/test.vcxproj @@ -0,0 +1,177 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {4c10ac76-384c-4539-b884-38e998749fb2} + test + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + 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 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + + + + + + {939a079d-a1e8-35d9-950f-11b1894d342e} + + + {245f0ec7-1ebc-4d68-8b1f-f758ea9196ae} + + + {c8bf60c3-40a9-43ad-891a-8aa34f1c3a68} + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/ebpf/libs/api/test/test.vcxproj.filters b/src/ebpf/libs/api/test/test.vcxproj.filters new file mode 100644 index 000000000..f330d705c --- /dev/null +++ b/src/ebpf/libs/api/test/test.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file