Merged PR 4114187: Update code to match coding conventions

Update code to match coding conventions
This commit is contained in:
Alan Jowett 2021-02-16 17:06:14 +00:00
Родитель 93d9783890
Коммит 3a73e0f548
43 изменённых файлов: 1139 добавлений и 1152 удалений

2
external/ebpf-verifier поставляемый

@ -1 +1 @@
Subproject commit a511c412472aeac1e2b4f7bf1e8eefa8a065bd22
Subproject commit b40e16861ed6bd1410ddb9057903b9b905e56d55

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

@ -1,13 +1,13 @@
LIBRARY
EXPORTS
EbpfApiInit
EbpfApiTerminate
EbpfApiLoadProgram
EbpfApiFreeErrorMessage
EbpfApiUnloadProgram
EbpfApiAttachProgram
EbpfApiDetachProgram
EbpfApiMapLookupElement
EbpfApiMapUpdateElement
EbpfApiMapDeleteElement
EbpfApiDeleteMap
ebpf_api_initiate
ebpf_api_terminate
ebpf_api_load_program
ebpf_api_free_error_message
ebpf_api_unload_program
ebpf_api_attach_program
ebpf_api_detach_program
ebpf_api_map_lookup_element
ebpf_api_map_update_element
ebpf_api_map_delete_element
ebpf_api_delete_map

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">

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

@ -1,179 +0,0 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#include <iostream>
#include <fstream>
#include <random>
#include <vector>
#include <list>
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
typedef uint32_t NTSTATUS;
#define STATUS_SUCCESS 0
#include "protocol.h"
extern "C"
{
#include "../ebpf_core.h"
}
TEST_CASE("EbpfCoreInitialize", "EbpfCoreInitialize") {
REQUIRE(EbpfCoreInitialize() == STATUS_SUCCESS);
EbpfCoreTerminate();
}
TEST_CASE("LoadAttachDetachUnload", "AttachDetach") {
REQUIRE(EbpfCoreInitialize() == STATUS_SUCCESS);
std::vector<uint8_t> buffer(1024);
auto load_request = reinterpret_cast<EbpfOpLoadRequest*>(buffer.data());
EbpfOpLoadReply load_reply;
load_request->header.length = buffer.size();
load_request->header.id = EbpfOperation::load_code;
REQUIRE(EbpfCoreProtocolLoadCode(load_request, &load_reply) == STATUS_SUCCESS);
EbpfOpAttachDetachRequest attach_request{ sizeof(attach_request), EbpfOperation::attach, load_reply.handle, ebpf_hook_xdp };
REQUIRE(EbpfCoreProtocolAttachCode(&attach_request, nullptr) == STATUS_SUCCESS);
EbpfOpAttachDetachRequest detach_request{ sizeof(detach_request), EbpfOperation::detach, load_reply.handle, ebpf_hook_xdp };
REQUIRE(EbpfCoreProtocolDetachCode(&detach_request, nullptr) == STATUS_SUCCESS);
EbpfOpUnloadRequest unload_request{ sizeof(unload_request), EbpfOperation::unload_code, load_reply.handle };
REQUIRE(EbpfCoreProtocolUnloadCode(&unload_request, nullptr) == STATUS_SUCCESS);
EbpfCoreTerminate();
}
TEST_CASE("ResolveHelper", "ResolveHelper") {
EbpfOpResolveHelperRequest request{ sizeof(EbpfOpResolveHelperRequest), EbpfOperation::resolve_helper };
EbpfOpResolveHelperReply reply;
for (ebpf_helper_function helper_id = ebpf_lookup_element; helper_id <= ebpf_delete_element; helper_id = static_cast<ebpf_helper_function>(helper_id + 1))
{
reply.address[0] = 0;
request.helper_id[0] = helper_id;
REQUIRE(EbpfCoreProtocolResolveHelper(&request, &reply) == STATUS_SUCCESS);
REQUIRE(reply.address[0] != 0);
}
}
TEST_CASE("MapTests", "MapTests") {
REQUIRE(EbpfCoreInitialize() == STATUS_SUCCESS);
EbpfOpCreateMapRequest create_request{ sizeof(EbpfOpCreateMapRequest), EbpfOperation::create_map, 2, sizeof(uint32_t), sizeof(uint64_t), 10 };
EbpfOpCreateMapReply create_reply;
REQUIRE(EbpfCoreProtocolCreateMap(&create_request, &create_reply) == STATUS_SUCCESS);
REQUIRE(create_reply.handle != 0);
for (uint32_t i = 0; i < 10; i++)
{
std::vector<uint8_t> request_buffer;
std::vector<uint8_t> reply_buffer;
request_buffer.resize(sizeof(EpfOpMapUpdateElementRequest) - 1 + create_request.key_size + create_request.value_size);
auto update_request = reinterpret_cast<EpfOpMapUpdateElementRequest*>(request_buffer.data());
update_request->header.length = request_buffer.size();
update_request->header.id = EbpfOperation::map_update_element;
update_request->handle = create_reply.handle;
auto key = reinterpret_cast<uint32_t*>(update_request->data);
*key = i;
auto value = reinterpret_cast<uint64_t*>(key + 1);
*value = 0x1234567890abcdef;
REQUIRE(EbpfCoreProtocolMapUpdateElement(update_request, nullptr) == ERROR_SUCCESS);
request_buffer.resize(sizeof(EbpfOpMapLookupElementRequest) - 1 + create_request.key_size);
reply_buffer.resize(sizeof(EbpfOpMapLookupElementReply) - 1 + create_request.value_size);
auto lookup_request = reinterpret_cast<EbpfOpMapLookupElementRequest*>(request_buffer.data());
auto lookup_reply = reinterpret_cast<EbpfOpMapLookupElementReply*>(reply_buffer.data());
lookup_request->header.length = request_buffer.size();
lookup_request->header.id = EbpfOperation::map_lookup_element;
lookup_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(lookup_request->key);
*key = i;
lookup_reply->header.length = reply_buffer.size();
REQUIRE(EbpfCoreProtocolMapLookupElement(lookup_request, lookup_reply) == STATUS_SUCCESS);
value = reinterpret_cast<uint64_t*>(lookup_reply->value);
REQUIRE(*value == 0x1234567890abcdef);
request_buffer.resize(sizeof(EbpfOpMapDeleteElementRequest) - 1 + create_request.key_size);
auto delete_request = reinterpret_cast<EbpfOpMapDeleteElementRequest*>(request_buffer.data());
delete_request->header.length = request_buffer.size();
delete_request->header.id = EbpfOperation::map_update_element;
delete_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(delete_request->key);
*key = i;
REQUIRE(EbpfCoreProtocolMapDeleteElement(delete_request, nullptr) == ERROR_SUCCESS);
request_buffer.resize(sizeof(EbpfOpMapLookupElementRequest) - 1 + create_request.key_size);
reply_buffer.resize(sizeof(EbpfOpMapLookupElementReply) - 1 + create_request.value_size);
lookup_request = reinterpret_cast<EbpfOpMapLookupElementRequest*>(request_buffer.data());
lookup_reply = reinterpret_cast<EbpfOpMapLookupElementReply*>(reply_buffer.data());
lookup_request->header.length = request_buffer.size();
lookup_request->header.id = EbpfOperation::map_lookup_element;
lookup_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(lookup_request->key);
*key = i;
lookup_reply->header.length = reply_buffer.size();
REQUIRE(EbpfCoreProtocolMapLookupElement(lookup_request, lookup_reply) == STATUS_SUCCESS);
value = reinterpret_cast<uint64_t*>(lookup_reply->value);
REQUIRE(*value == 0);
}
EbpfCoreTerminate();
}
TEST_CASE("HelperTests", "HelperTests") {
REQUIRE(EbpfCoreInitialize() == STATUS_SUCCESS);
EbpfOpCreateMapRequest create_request{ sizeof(EbpfOpCreateMapRequest), EbpfOperation::create_map, 2, sizeof(uint32_t), sizeof(uint64_t), 10 };
EbpfOpCreateMapReply create_reply;
REQUIRE(EbpfCoreProtocolCreateMap(&create_request, &create_reply) == STATUS_SUCCESS);
REQUIRE(create_reply.handle != 0);
EbpfOpResolveMapRequest resolve_request{ sizeof(EbpfOpResolveMapRequest), EbpfOperation::resolve_map, create_reply.handle };
EbpfOpResolveMapReply resolve_reply{ sizeof(EbpfOpResolveHelperReply) };
REQUIRE(EbpfCoreProtocolResolveMap(&resolve_request, &resolve_reply) == STATUS_SUCCESS);
REQUIRE(resolve_reply.address[0] != 0);
auto map = resolve_reply.address[0];
EbpfOpResolveHelperRequest request{ sizeof(EbpfOpResolveHelperRequest), EbpfOperation::resolve_helper };
EbpfOpResolveHelperReply reply;
std::vector<uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t)> helper_functions(5);
for (ebpf_helper_function id = ebpf_lookup_element; id < ebpf_invalid; id = static_cast<ebpf_helper_function>(id + 1))
{
reply.address[0] = 0;
request.helper_id[0] = id;
REQUIRE(EbpfCoreProtocolResolveHelper(&request, &reply) == STATUS_SUCCESS);
REQUIRE(reply.address[0] != 0);
helper_functions[id] = reinterpret_cast<uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t)>(reply.address[0]);
}
for (uint64_t i = 0; i < 10; i++)
{
uint64_t key = i;
uint64_t value = 0x123456789abcdef;
helper_functions[ebpf_update_element](map, reinterpret_cast<uint64_t>(&key), reinterpret_cast<uint64_t>(&value), 0);
auto element_address = helper_functions[ebpf_lookup_element](map, reinterpret_cast<uint64_t>(&key), 0, 0);
REQUIRE(*reinterpret_cast<uint64_t*>(element_address) == 0x123456789abcdef);
helper_functions[ebpf_delete_element](map, reinterpret_cast<uint64_t>(&key), 0, 0);
element_address = helper_functions[ebpf_lookup_element](map, reinterpret_cast<uint64_t>(&key), 0, 0);
REQUIRE(*reinterpret_cast<uint64_t*>(element_address) == 0);
}
EbpfCoreTerminate();
}

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\..\packages\CatchOrg.Catch.2.2.0\build\native\CatchOrg.Catch.props" Condition="Exists('..\..\..\..\..\packages\CatchOrg.Catch.2.2.0\build\native\CatchOrg.Catch.props')" />
<ItemGroup Label="ProjectConfigurations">
@ -121,7 +121,7 @@
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DDK_INC_PATH);$(SolutionDir)src\ebpf\libs\api;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -149,7 +149,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_core.c" />
<ClCompile Include="EbpfCoreTest.cpp" />
<ClCompile Include="ebpf_core_test.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

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

@ -15,10 +15,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="EbpfCoreTest.cpp">
<ClCompile Include="..\ebpf_core.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_core.c">
<ClCompile Include="ebpf_core_test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

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

@ -0,0 +1,197 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#include <iostream>
#include <fstream>
#include <random>
#include <vector>
#include <list>
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
typedef uint32_t NTSTATUS;
#define STATUS_SUCCESS 0
#include "protocol.h"
extern "C"
{
#include "../ebpf_core.h"
}
TEST_CASE("ebpf_core_initialize", "ebpf_core_initialize") {
REQUIRE(ebpf_core_initialize() == STATUS_SUCCESS);
ebpf_core_terminate();
}
TEST_CASE("LoadAttachDetachUnload", "AttachDetach") {
REQUIRE(ebpf_core_initialize() == STATUS_SUCCESS);
std::vector<uint8_t> buffer(1024);
auto load_request = reinterpret_cast<_ebpf_operation_load_code_request*>(buffer.data());
_ebpf_operation_load_code_reply load_reply;
load_request->header.length = buffer.size();
load_request->header.id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE;
REQUIRE(ebpf_core_protocol_load_code(load_request, &load_reply) == STATUS_SUCCESS);
_ebpf_operation_attach_detach_request attach_request{ sizeof(attach_request), ebpf_operation_id_t::EBPF_OPERATION_ATTACH_CODE, load_reply.handle, EBPF_HOOK_XDP };
REQUIRE(ebpf_core_protocol_attach_code(&attach_request, nullptr) == STATUS_SUCCESS);
_ebpf_operation_attach_detach_request detach_request{ sizeof(detach_request), ebpf_operation_id_t::EBPF_OPERATION_DETACH_CODE, load_reply.handle, EBPF_HOOK_XDP };
REQUIRE(ebpf_core_protocol_detach_code(&detach_request, nullptr) == STATUS_SUCCESS);
_ebpf_operation_unload_code_request unload_request{ sizeof(unload_request), ebpf_operation_id_t::EBPF_OPERATION_UNLOAD_CODE, load_reply.handle };
REQUIRE(ebpf_core_protocol_unload_code(&unload_request, nullptr) == STATUS_SUCCESS);
ebpf_core_terminate();
}
TEST_CASE("ResolveHelper", "ResolveHelper") {
_ebpf_operation_resolve_helper_request request{ sizeof(_ebpf_operation_resolve_helper_request), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER };
_ebpf_operation_resolve_helper_reply reply;
for (ebpf_helper_function_t helper_id = EBPF_LOOKUP_ELEMENT; helper_id <= ebpf_delete_element; helper_id = static_cast<ebpf_helper_function_t>(helper_id + 1))
{
reply.address[0] = 0;
request.helper_id[0] = helper_id;
REQUIRE(ebpf_core_protocol_resolve_helper(&request, &reply) == STATUS_SUCCESS);
REQUIRE(reply.address[0] != 0);
}
}
TEST_CASE("MapTests", "MapTests") {
REQUIRE(ebpf_core_initialize() == STATUS_SUCCESS);
_ebpf_operation_create_map_request create_request{
sizeof(_ebpf_operation_create_map_request),
ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP,
{
sizeof(ebpf_map_definition_t),
2,
sizeof(uint32_t),
sizeof(uint64_t),
10
}};
_ebpf_operation_create_map_reply create_reply;
REQUIRE(ebpf_core_protocol_create_map(&create_request, &create_reply) == STATUS_SUCCESS);
REQUIRE(create_reply.handle != 0);
for (uint32_t i = 0; i < 10; i++)
{
std::vector<uint8_t> request_buffer;
std::vector<uint8_t> reply_buffer;
request_buffer.resize(sizeof(_ebpf_operation_map_update_element_request) - 1 + create_request.ebpf_map_definition.key_size + create_request.ebpf_map_definition.value_size);
auto update_request = reinterpret_cast<_ebpf_operation_map_update_element_request*>(request_buffer.data());
update_request->header.length = request_buffer.size();
update_request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_UPDATE_ELEMENT;
update_request->handle = create_reply.handle;
auto key = reinterpret_cast<uint32_t*>(update_request->data);
*key = i;
auto value = reinterpret_cast<uint64_t*>(key + 1);
*value = 0x1234567890abcdef;
REQUIRE(ebpf_core_protocol_map_update_element(update_request, nullptr) == ERROR_SUCCESS);
request_buffer.resize(sizeof(_ebpf_operation_map_lookup_element_request) - 1 + create_request.ebpf_map_definition.key_size);
reply_buffer.resize(sizeof(_ebpf_operation_map_lookup_element_reply) - 1 + create_request.ebpf_map_definition.value_size);
auto lookup_request = reinterpret_cast<_ebpf_operation_map_lookup_element_request*>(request_buffer.data());
auto lookup_reply = reinterpret_cast<_ebpf_operation_map_lookup_element_reply*>(reply_buffer.data());
lookup_request->header.length = request_buffer.size();
lookup_request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT;
lookup_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(lookup_request->key);
*key = i;
lookup_reply->header.length = reply_buffer.size();
REQUIRE(ebpf_core_protocol_map_lookup_element(lookup_request, lookup_reply) == STATUS_SUCCESS);
value = reinterpret_cast<uint64_t*>(lookup_reply->value);
REQUIRE(*value == 0x1234567890abcdef);
request_buffer.resize(sizeof(_ebpf_operation_map_delete_element_request) - 1 + create_request.ebpf_map_definition.key_size);
auto delete_request = reinterpret_cast<_ebpf_operation_map_delete_element_request*>(request_buffer.data());
delete_request->header.length = request_buffer.size();
delete_request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_UPDATE_ELEMENT;
delete_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(delete_request->key);
*key = i;
REQUIRE(ebpf_core_protocol_map_delete_element(delete_request, nullptr) == ERROR_SUCCESS);
request_buffer.resize(sizeof(_ebpf_operation_map_lookup_element_request) - 1 + create_request.ebpf_map_definition.key_size);
reply_buffer.resize(sizeof(_ebpf_operation_map_lookup_element_reply) - 1 + create_request.ebpf_map_definition.value_size);
lookup_request = reinterpret_cast<_ebpf_operation_map_lookup_element_request*>(request_buffer.data());
lookup_reply = reinterpret_cast<_ebpf_operation_map_lookup_element_reply*>(reply_buffer.data());
lookup_request->header.length = request_buffer.size();
lookup_request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT;
lookup_request->handle = create_reply.handle;
key = reinterpret_cast<uint32_t*>(lookup_request->key);
*key = i;
lookup_reply->header.length = reply_buffer.size();
REQUIRE(ebpf_core_protocol_map_lookup_element(lookup_request, lookup_reply) == STATUS_SUCCESS);
value = reinterpret_cast<uint64_t*>(lookup_reply->value);
REQUIRE(*value == 0);
}
ebpf_core_terminate();
}
TEST_CASE("HelperTests", "HelperTests") {
REQUIRE(ebpf_core_initialize() == STATUS_SUCCESS);
_ebpf_operation_create_map_request create_request{
sizeof(_ebpf_operation_create_map_request),
ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP,
{
sizeof(ebpf_map_definition_t),
2,
sizeof(uint32_t),
sizeof(uint64_t),
10
} };
_ebpf_operation_create_map_reply create_reply;
REQUIRE(ebpf_core_protocol_create_map(&create_request, &create_reply) == STATUS_SUCCESS);
REQUIRE(create_reply.handle != 0);
_ebpf_operation_resolve_map_request resolve_request{ sizeof(_ebpf_operation_resolve_map_request), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP, create_reply.handle };
_ebpf_operation_resolve_map_reply resolve_reply{ sizeof(_ebpf_operation_resolve_map_reply) };
REQUIRE(ebpf_core_protocol_resolve_map(&resolve_request, &resolve_reply) == STATUS_SUCCESS);
REQUIRE(resolve_reply.address[0] != 0);
auto map = resolve_reply.address[0];
_ebpf_operation_resolve_helper_request request{ sizeof(_ebpf_operation_resolve_helper_request), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER };
_ebpf_operation_resolve_helper_reply reply;
std::vector<uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t)> helper_functions(5);
for (ebpf_helper_function_t id = EBPF_LOOKUP_ELEMENT; id < EBPF_INVALID; id = static_cast<ebpf_helper_function_t>(id + 1))
{
reply.address[0] = 0;
request.helper_id[0] = id;
REQUIRE(ebpf_core_protocol_resolve_helper(&request, &reply) == STATUS_SUCCESS);
REQUIRE(reply.address[0] != 0);
helper_functions[id] = reinterpret_cast<uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t)>(reply.address[0]);
}
for (uint64_t i = 0; i < 10; i++)
{
uint64_t key = i;
uint64_t value = 0x123456789abcdef;
helper_functions[EBPF_UPDATE_ELEMENT](map, reinterpret_cast<uint64_t>(&key), reinterpret_cast<uint64_t>(&value), 0);
auto element_address = helper_functions[EBPF_LOOKUP_ELEMENT](map, reinterpret_cast<uint64_t>(&key), 0, 0);
REQUIRE(*reinterpret_cast<uint64_t*>(element_address) == 0x123456789abcdef);
helper_functions[ebpf_delete_element](map, reinterpret_cast<uint64_t>(&key), 0, 0);
element_address = helper_functions[EBPF_LOOKUP_ELEMENT](map, reinterpret_cast<uint64_t>(&key), 0, 0);
REQUIRE(*reinterpret_cast<uint64_t*>(element_address) == 0);
}
ebpf_core_terminate();
}

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CatchOrg.Catch" version="2.2.0" targetFramework="native" />
<package identifier="CatchOrg.Catch" version="2.2.0" targetFramework="native" />
</packages>

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

@ -16,146 +16,160 @@
DWORD gError = 0;
static DWORD _count_of_seh_raised = 0;
LIST_ENTRY gUserCodeList;
KSPIN_LOCK gUserCodeLock;
_Requires_lock_held_(_ebpf_core_code_entry_list_lock)
static LIST_ENTRY _ebpf_core_code_entry_list;
static KSPIN_LOCK _ebpf_core_code_entry_list_lock;
_Requires_lock_held_(_ebpf_core_map_entry_list_lock)
static LIST_ENTRY _ebpf_core_map_entry_list;
static KSPIN_LOCK _ebpf_core_map_entry_list_lock;
// TODO: Switch this to use real object manager handles
UINT64 gHandle = 0;
LIST_ENTRY gMapList;
KSPIN_LOCK gMapLock;
static UINT64 _next_pseudo_handle = 0;
typedef struct {
typedef struct _ebpf_core_code_entry {
LIST_ENTRY entry;
// pointer to code buffer
uint8_t* code;
// handle required for attach/detach/unload
// handle returned to user mode application
uint64_t handle;
ebpf_hook_point hook_point;
} UserCodeEntry;
ebpf_hook_point_t hook_point;
} ebpf_core_code_entry_t;
typedef struct EbpfCoreMap_
{
uint32_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
typedef struct _ebpf_core_map {
struct _ebpf_map_definition ebpf_map_definition;
uint8_t* data;
} EbpfCoreMap;
} ebpf_core_map_t;
typedef struct {
typedef struct _ebpf_core_map_entry {
LIST_ENTRY entry;
EbpfCoreMap map;
ebpf_core_map_t map;
uint64_t handle;
} EbpfCoreMapEntry;
// Externs
extern LIST_ENTRY gUserCodeList;
extern KSPIN_LOCK gUserCodeLock;
extern LIST_ENTRY gMapList;
extern KSPIN_LOCK gMapLock;
} ebpf_core_map_entry_t;
typedef enum
{
ebpfPoolTag = 'fpbe'
} EBPF_POOL_TAG;
void* EbpfCoreMapLookupElement(EbpfCoreMap* map, uint32_t* key);
void EbpfCoreMapUpdateElement(EbpfCoreMap* map, uint32_t* key, uint8_t* data);
void EbpfCoreMapDeleteElement(EbpfCoreMap* map, uint32_t* key);
static void* _ebpf_core_map_lookup_element(ebpf_core_map_t* map, uint32_t* key);
static void _ebpf_core_map_update_element(ebpf_core_map_t* map, uint32_t* key, uint8_t* data);
static void _ebpf_core_map_delete_element(ebpf_core_map_t* map, uint32_t* key);
void * EbpfProgramHelpers[] =
static const void * _ebpf_program_helpers[] =
{
NULL,
(void*)&EbpfCoreMapLookupElement,
(void*)&EbpfCoreMapUpdateElement,
(void*)&EbpfCoreMapDeleteElement
(void*)&_ebpf_core_map_lookup_element,
(void*)&_ebpf_core_map_update_element,
(void*)&_ebpf_core_map_delete_element
};
_Requires_exclusive_lock_held_(gMapLock)
EbpfCoreMapEntry* EbpfCoreFindMapEntry(uint64_t handle)
_Requires_exclusive_lock_held_(_ebpf_core_map_entry_list_lock)
static ebpf_core_map_entry_t* _ebpf_core_find_map_entry(uint64_t handle)
{
// TODO: Switch this to use real object manager handles
LIST_ENTRY* listEntry = gMapList.Flink;
while (listEntry != &gMapList)
LIST_ENTRY* list_entry = _ebpf_core_map_entry_list.Flink;
while (list_entry != &_ebpf_core_map_entry_list)
{
EbpfCoreMapEntry* map = CONTAINING_RECORD(listEntry, EbpfCoreMapEntry, entry);
ebpf_core_map_entry_t* map = CONTAINING_RECORD(list_entry, ebpf_core_map_entry_t, entry);
if (handle == map->handle)
return map;
listEntry = listEntry->Flink;
list_entry = list_entry->Flink;
}
return NULL;
}
_Requires_exclusive_lock_held_(gUserCodeLock)
UserCodeEntry* EbpfCoreFindUserCode(uint64_t handle)
_Requires_exclusive_lock_held_(_ebpf_core_code_entry_list_lock)
ebpf_core_code_entry_t* _ebpf_core_find_user_code(uint64_t handle)
{
// TODO: Switch this to use real object manager handles
LIST_ENTRY* listEntry = gUserCodeList.Flink;
while (listEntry != &gUserCodeList)
LIST_ENTRY* list_entry = _ebpf_core_code_entry_list.Flink;
while (list_entry != &_ebpf_core_code_entry_list)
{
UserCodeEntry* code = CONTAINING_RECORD(listEntry, UserCodeEntry, entry);
ebpf_core_code_entry_t* code = CONTAINING_RECORD(list_entry, ebpf_core_code_entry_t, entry);
if (handle == code->handle)
return code;
listEntry = listEntry->Flink;
list_entry = list_entry->Flink;
}
return NULL;
}
NTSTATUS
EbpfCoreInitialize()
ebpf_core_initialize()
{
KeInitializeSpinLock(&gUserCodeLock);
InitializeListHead(&gUserCodeList);
KeInitializeSpinLock(&_ebpf_core_code_entry_list_lock);
InitializeListHead(&_ebpf_core_code_entry_list);
KeInitializeSpinLock(&gMapLock);
InitializeListHead(&gMapList);
KeInitializeSpinLock(&_ebpf_core_map_entry_list_lock);
InitializeListHead(&_ebpf_core_map_entry_list);
return STATUS_SUCCESS;
}
void
EbpfCoreTerminate()
ebpf_core_terminate()
{
KIRQL old_irql;
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
LIST_ENTRY* list_entry = _ebpf_core_code_entry_list.Flink;
while (list_entry != &_ebpf_core_code_entry_list)
{
ebpf_core_code_entry_t* code = CONTAINING_RECORD(list_entry, ebpf_core_code_entry_t, entry);
list_entry = list_entry->Flink;
RemoveEntryList(&code->entry);
ExFreePool(code);
}
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
list_entry = _ebpf_core_map_entry_list.Flink;
while (list_entry != &_ebpf_core_map_entry_list)
{
ebpf_core_map_entry_t* map = CONTAINING_RECORD(list_entry, ebpf_core_map_entry_t, entry);
list_entry = list_entry->Flink;
RemoveEntryList(&map->entry);
ExFreePool(map);
}
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
}
NTSTATUS
EbpfCoreProtocolAttachCode(
_In_ struct EbpfOpAttachDetachRequest* request,
ebpf_core_protocol_attach_code(
_In_ struct _ebpf_operation_attach_detach_request* request,
_Inout_ void* reply
)
{
NTSTATUS status = STATUS_INVALID_HANDLE;
KIRQL irql;
UserCodeEntry* code = NULL;
KIRQL old_irql;
ebpf_core_code_entry_t* code = NULL;
UNREFERENCED_PARAMETER(reply);
if (request->hook != ebpf_hook_xdp)
if (request->hook != EBPF_HOOK_XDP)
{
status = STATUS_NOT_SUPPORTED;
goto Done;
}
// TODO: Switch this to use real object manager handles
KeAcquireSpinLock(&gUserCodeLock, &irql);
code = EbpfCoreFindUserCode(request->handle);
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
code = _ebpf_core_find_user_code(request->handle);
if (code)
{
code->hook_point = request->hook;
status = STATUS_SUCCESS;
}
KeReleaseSpinLock(&gUserCodeLock, irql);
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: AttachCodeToHook 0x%llx handle\n", request->handle));
@ -164,30 +178,30 @@ Done:
}
NTSTATUS
EbpfCoreProtocolDetachCode(
_In_ struct EbpfOpAttachDetachRequest* request,
ebpf_core_protocol_detach_code(
_In_ struct _ebpf_operation_attach_detach_request* request,
_Inout_ void* reply
)
{
NTSTATUS status = STATUS_INVALID_HANDLE;
KIRQL irql;
UserCodeEntry* code = NULL;
KIRQL old_irql;
ebpf_core_code_entry_t* code = NULL;
UNREFERENCED_PARAMETER(reply);
if (request->hook != ebpf_hook_xdp)
if (request->hook != EBPF_HOOK_XDP)
{
status = STATUS_NOT_SUPPORTED;
}
// TODO: Switch this to use real object manager handles
KeAcquireSpinLock(&gUserCodeLock, &irql);
code = EbpfCoreFindUserCode(request->handle);
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
code = _ebpf_core_find_user_code(request->handle);
if (code)
{
code->hook_point = ebpf_hook_none;
code->hook_point = EBPF_HOOK_NONE;
status = STATUS_SUCCESS;
}
KeReleaseSpinLock(&gUserCodeLock, irql);
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: DetachCodeFromHook 0x%llx handle\n", request->handle));
@ -195,18 +209,18 @@ EbpfCoreProtocolDetachCode(
}
NTSTATUS
EbpfCoreProtocolUnloadCode(
_In_ struct EbpfOpUnloadRequest* request,
ebpf_core_protocol_unload_code(
_In_ struct _ebpf_operation_unload_code_request* request,
_Inout_ void* reply)
{
NTSTATUS status = STATUS_INVALID_HANDLE;
KIRQL irql;
UserCodeEntry* code = NULL;
KIRQL old_irql;
ebpf_core_code_entry_t* code = NULL;
UNREFERENCED_PARAMETER(reply);
KeAcquireSpinLock(&gUserCodeLock, &irql);
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
code = EbpfCoreFindUserCode(request->handle);
code = _ebpf_core_find_user_code(request->handle);
if (code)
{
RemoveEntryList(&code->entry);
@ -215,7 +229,7 @@ EbpfCoreProtocolUnloadCode(
status = STATUS_SUCCESS;
}
KeReleaseSpinLock(&gUserCodeLock, irql);
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
if (status != STATUS_SUCCESS)
{
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "EbpfCore: UnloadCode: failed to find handle 0x%llx\n", request->handle));
@ -224,21 +238,21 @@ EbpfCoreProtocolUnloadCode(
}
NTSTATUS
EbpfCoreProtocolLoadCode(
_In_ struct EbpfOpLoadRequest* inputRequest,
_Inout_ struct EbpfOpLoadReply* loadReply)
ebpf_core_protocol_load_code(
_In_ struct _ebpf_operation_load_code_request* request,
_Inout_ struct _ebpf_operation_load_code_reply* reply)
{
NTSTATUS status = STATUS_SUCCESS;
PVOID buffer = NULL;
UINT16 codeSize = 0;
KIRQL irql;
UserCodeEntry* code = NULL;
KIRQL old_irql;
ebpf_core_code_entry_t* code = NULL;
// allocate
codeSize = inputRequest->header.length;
codeSize = request->header.length;
buffer = ExAllocatePool2(
POOL_FLAG_NON_PAGED_EXECUTE,
codeSize + sizeof(UserCodeEntry),
codeSize + sizeof(ebpf_core_code_entry_t),
ebpfPoolTag
);
if (buffer == NULL) {
@ -248,19 +262,19 @@ EbpfCoreProtocolLoadCode(
// copy and hang on to user code
code = buffer;
buffer = (uint8_t*)buffer + sizeof(UserCodeEntry);
RtlCopyMemory(buffer, (PUCHAR)inputRequest->machine_code, codeSize);
buffer = (uint8_t*)buffer + sizeof(ebpf_core_code_entry_t);
RtlCopyMemory(buffer, (PUCHAR)request->machine_code, codeSize);
code->code = buffer;
// TODO: Switch this to use real object manager handles
code->handle = (0xffff | gHandle++);
code->handle = (0xffff | _next_pseudo_handle++);
KeAcquireSpinLock(&gUserCodeLock, &irql);
InsertTailList(&gUserCodeList, &code->entry);
KeReleaseSpinLock(&gUserCodeLock, irql);
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
InsertTailList(&_ebpf_core_code_entry_list, &code->entry);
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
// construct the response
loadReply->handle = code->handle;
reply->handle = code->handle;
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: AllocateAndLoadCode code: 0x%llp handle: 0x%llx\n", code, code->handle));
Done:
@ -271,111 +285,111 @@ Done:
return status;
}
NTSTATUS EbpfCoreProtocolResolveHelper(
_In_ struct EbpfOpResolveHelperRequest* request,
_Out_ struct EbpfOpResolveHelperReply* reply)
NTSTATUS ebpf_core_protocol_resolve_helper(
_In_ struct _ebpf_operation_resolve_helper_request* request,
_Out_ struct _ebpf_operation_resolve_helper_reply* reply)
{
if (request->helper_id[0] >= ebpf_invalid)
if (request->helper_id[0] >= EBPF_INVALID)
{
return STATUS_INVALID_PARAMETER;
}
reply->address[0] = (uint64_t)EbpfProgramHelpers[request->helper_id[0]];
reply->address[0] = (uint64_t)_ebpf_program_helpers[request->helper_id[0]];
return STATUS_SUCCESS;;
}
NTSTATUS EbpfCoreProtocolResolveMap(
_In_ struct EbpfOpResolveMapRequest* request,
_Out_ struct EbpfOpResolveMapReply* reply)
NTSTATUS ebpf_core_protocol_resolve_map(
_In_ struct _ebpf_operation_resolve_map_request* request,
_Out_ struct _ebpf_operation_resolve_map_reply* reply)
{
NTSTATUS status = STATUS_NOT_FOUND;
KIRQL irql;
EbpfCoreMapEntry* map = NULL;
KIRQL old_irql;
ebpf_core_map_entry_t* map = NULL;
KeAcquireSpinLock(&gMapLock, &irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
map = EbpfCoreFindMapEntry(request->map_id[0]);
map = _ebpf_core_find_map_entry(request->map_handle[0]);
if (map)
{
status = STATUS_SUCCESS;
reply->address[0] = (uint64_t)&map->map;
}
KeReleaseSpinLock(&gMapLock, irql);
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: EbpfCoreProtocolResolveMap 0x%llx handle\n", request->map_id[0]));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ebpf_core_protocol_resolve_map 0x%llx handle\n", request->map_handle[0]));
return status;
}
xdp_action
EbpfCoreInvokeXdpHook(
xdp_action_t
ebpf_core_invoke_xdp_hook(
_In_ void* buffer,
_In_ uint32_t buffer_length)
{
KIRQL irql;
UserCodeEntry* code = NULL;
XDP_HOOK funcPtr;
xdp_action result = XDP_PASS;
KIRQL old_irql;
ebpf_core_code_entry_t* code = NULL;
xdp_hook_function function_pointer;
xdp_action_t result = XDP_PASS;
BOOLEAN found = FALSE;
xdp_md ctx = { 0 };
xdp_md_t ctx = { 0 };
ctx.data = (UINT64)buffer;
ctx.data_end = (UINT64)buffer_length;
KeAcquireSpinLock(&gUserCodeLock, &irql);
KeAcquireSpinLock(&_ebpf_core_code_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
LIST_ENTRY* listEntry = gUserCodeList.Flink;
while (listEntry != &gUserCodeList)
LIST_ENTRY* list_entry = _ebpf_core_code_entry_list.Flink;
while (list_entry != &_ebpf_core_code_entry_list)
{
code = CONTAINING_RECORD(listEntry, UserCodeEntry, entry);
if (code->hook_point == ebpf_hook_xdp)
code = CONTAINING_RECORD(list_entry, ebpf_core_code_entry_t, entry);
if (code->hook_point == EBPF_HOOK_XDP)
{
// find the first one and run.
found = TRUE;
break;
}
listEntry = listEntry->Flink;
list_entry = list_entry->Flink;
}
if (found)
{
funcPtr = (XDP_HOOK)code->code;
function_pointer = (xdp_hook_function)code->code;
__try {
result = (*funcPtr)(&ctx);
result = (*function_pointer)(&ctx);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
gError++;
_count_of_seh_raised++;
}
}
KeReleaseSpinLock(&gUserCodeLock, irql);
KeReleaseSpinLock(&_ebpf_core_code_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ExecuteCode. gError %d\n", gError));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ExecuteCode. _count_of_seh_raised %d\n", _count_of_seh_raised));
return (xdp_action)result;
return (xdp_action_t)result;
}
NTSTATUS EbpfCoreProtocolCreateMap(
_In_ struct EbpfOpCreateMapRequest* request,
_Inout_ struct EbpfOpCreateMapReply* reply)
NTSTATUS ebpf_core_protocol_create_map(
_In_ struct _ebpf_operation_create_map_request* request,
_Inout_ struct _ebpf_operation_create_map_reply* reply)
{
NTSTATUS status = STATUS_SUCCESS;
SIZE_T map_entry_size = sizeof(EbpfCoreMapEntry);
SIZE_T map_entry_size = sizeof(ebpf_core_map_entry_t);
SIZE_T map_data_size = 0;
KIRQL irql;
EbpfCoreMapEntry* map = NULL;
KIRQL old_irql;
ebpf_core_map_entry_t* map = NULL;
// TODO: Add support for other map types
if (request->type != ebpf_map_array)
if (request->ebpf_map_definition.type != EBPF_MAP_ARRAY)
{
status = STATUS_NOT_IMPLEMENTED;
goto Done;
}
status = RtlSizeTMult(request->max_entries, request->value_size, &map_data_size);
status = RtlSizeTMult(request->ebpf_map_definition.max_entries, request->ebpf_map_definition.value_size, &map_data_size);
if (status != STATUS_SUCCESS)
{
goto Done;
@ -399,42 +413,39 @@ NTSTATUS EbpfCoreProtocolCreateMap(
}
memset(map, 0, map_entry_size);
map->map.key_size = request->key_size;
map->map.type = request->type;
map->map.max_entries = request->max_entries;
map->map.value_size = request->value_size;
map->map.ebpf_map_definition = request->ebpf_map_definition;
map->map.data = (uint8_t*)(map + 1);
// TODO: Switch this to use real object manager handles
map->handle = (0xffff | gHandle++);
map->handle = (0xffff | _next_pseudo_handle++);
KeAcquireSpinLock(&gMapLock, &irql);
InsertTailList(&gMapList, &map->entry);
KeReleaseSpinLock(&gMapLock, irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
InsertTailList(&_ebpf_core_map_entry_list, &map->entry);
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
// construct the response
reply->handle = map->handle;
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: EbpfCoreProtocolCreateMap map: 0x%llp handle: 0x%llx\n", map, map->handle));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ebpf_core_protocol_create_map map: 0x%llp handle: 0x%llx\n", map, map->handle));
Done:
if (!NT_SUCCESS(status))
{
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "EbpfCore: EbpfCoreProtocolCreateMap code failed %d\n", status));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "EbpfCore: ebpf_core_protocol_create_map code failed %d\n", status));
}
return status;
}
NTSTATUS EbpfCoreProtocolMapLookupElement(
_In_ struct EbpfOpMapLookupElementRequest* request,
_Inout_ struct EbpfOpMapLookupElementReply* reply)
NTSTATUS ebpf_core_protocol_map_lookup_element(
_In_ struct _ebpf_operation_map_lookup_element_request* request,
_Inout_ struct _ebpf_operation_map_lookup_element_reply* reply)
{
NTSTATUS status = STATUS_NOT_FOUND;
KIRQL irql;
EbpfCoreMapEntry* map = NULL;
KIRQL old_irql;
ebpf_core_map_entry_t* map = NULL;
uint32_t key;
SIZE_T value_offset = 0;
if (request->header.length < sizeof(struct EbpfOpMapLookupElementRequest) - 1 + sizeof(uint32_t))
if (request->header.length < sizeof(struct _ebpf_operation_map_lookup_element_request) - 1 + sizeof(uint32_t))
{
status = STATUS_INVALID_PARAMETER;
goto Done;
@ -442,142 +453,142 @@ NTSTATUS EbpfCoreProtocolMapLookupElement(
key = *(uint32_t*)request->key;
KeAcquireSpinLock(&gMapLock, &irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
map = EbpfCoreFindMapEntry(request->handle);
map = _ebpf_core_find_map_entry(request->handle);
if (map)
{
// Compute offset into data.
status = RtlSizeTMult(key, map->map.value_size, &value_offset);
status = key < map->map.max_entries ? status : STATUS_INVALID_PARAMETER;
status = (reply->header.length - sizeof(struct EbpfOpMapLookupElementReply) + 1) == (map->map.value_size) ? status : STATUS_INVALID_PARAMETER;
status = RtlSizeTMult(key, map->map.ebpf_map_definition.value_size, &value_offset);
status = key < map->map.ebpf_map_definition.max_entries ? status : STATUS_INVALID_PARAMETER;
status = (reply->header.length - sizeof(struct _ebpf_operation_map_lookup_element_reply) + 1) == (map->map.ebpf_map_definition.value_size) ? status : STATUS_INVALID_PARAMETER;
if (status == STATUS_SUCCESS)
{
memcpy(reply->value, map->map.data + value_offset, map->map.value_size);
memcpy(reply->value, map->map.data + value_offset, map->map.ebpf_map_definition.value_size);
}
}
KeReleaseSpinLock(&gMapLock, irql);
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: EbpfCoreProtocolMapLookupElement 0x%llx handle\n", request->handle));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ebpf_core_protocol_map_lookup_element 0x%llx handle\n", request->handle));
Done:
return status;
}
NTSTATUS EbpfCoreProtocolMapUpdateElement(
_In_ struct EpfOpMapUpdateElementRequest* request,
NTSTATUS ebpf_core_protocol_map_update_element(
_In_ struct _ebpf_operation_map_update_element_request* request,
_Inout_ void* reply)
{
NTSTATUS status = STATUS_NOT_FOUND;
KIRQL irql;
EbpfCoreMapEntry* map = NULL;
KIRQL old_irql;
ebpf_core_map_entry_t* map = NULL;
uint32_t key;
SIZE_T value_offset = 0;
UNREFERENCED_PARAMETER(reply);
KeAcquireSpinLock(&gMapLock, &irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
map = EbpfCoreFindMapEntry(request->handle);
map = _ebpf_core_find_map_entry(request->handle);
if (map)
{
// Is the request big enough to contain both key + value?
status = (request->header.length - sizeof(struct EpfOpMapUpdateElementRequest) + 1) == ((size_t)map->map.key_size + (size_t)map->map.value_size) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
status = (request->header.length - sizeof(struct _ebpf_operation_map_update_element_request) + 1) == ((size_t)map->map.ebpf_map_definition.key_size + (size_t)map->map.ebpf_map_definition.value_size) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
// If success, then extract key
key = (status == STATUS_SUCCESS) ? *(uint32_t*)request->data : 0;
// If success, check if key is in range
status = (status == STATUS_SUCCESS) ? key < map->map.max_entries ? status : STATUS_INVALID_PARAMETER : status;
status = (status == STATUS_SUCCESS) ? key < map->map.ebpf_map_definition.max_entries ? status : STATUS_INVALID_PARAMETER : status;
// If success, then compute value offset
status = (status == STATUS_SUCCESS) ? RtlSizeTMult(key, map->map.value_size, &value_offset) : status;
status = (status == STATUS_SUCCESS) ? RtlSizeTMult(key, map->map.ebpf_map_definition.value_size, &value_offset) : status;
if (status == STATUS_SUCCESS)
{
memcpy(map->map.data + value_offset, request->data + sizeof(uint32_t), map->map.value_size);
memcpy(map->map.data + value_offset, request->data + sizeof(uint32_t), map->map.ebpf_map_definition.value_size);
}
}
KeReleaseSpinLock(&gMapLock, irql);
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: EbpfCoreProtocolMapLookupElement 0x%llx handle\n", request->handle));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ebpf_core_protocol_map_lookup_element 0x%llx handle\n", request->handle));
return status;
}
NTSTATUS EbpfCoreProtocolMapDeleteElement(
_In_ struct EbpfOpMapDeleteElementRequest* request,
NTSTATUS ebpf_core_protocol_map_delete_element(
_In_ struct _ebpf_operation_map_delete_element_request* request,
_Inout_ void* reply)
{
NTSTATUS status = STATUS_NOT_FOUND;
KIRQL irql;
EbpfCoreMapEntry* map = NULL;
KIRQL old_irql;
ebpf_core_map_entry_t* map = NULL;
uint32_t key;
SIZE_T value_offset = 0;
UNREFERENCED_PARAMETER(reply);
KeAcquireSpinLock(&gMapLock, &irql);
KeAcquireSpinLock(&_ebpf_core_map_entry_list_lock, &old_irql);
// TODO: Switch this to use real object manager handles
map = EbpfCoreFindMapEntry(request->handle);
map = _ebpf_core_find_map_entry(request->handle);
if (map)
{
// Is the request big enough to contain both key + value?
status = (request->header.length - sizeof(struct EpfOpMapUpdateElementRequest) + 1) == map->map.key_size ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
status = (request->header.length - sizeof(struct _ebpf_operation_map_update_element_request) + 1) == map->map.ebpf_map_definition.key_size ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
// If success, then extract key
key = (status == STATUS_SUCCESS) ? *(uint32_t*)request->key : 0;
// If success, check if key is in range
status = (status == STATUS_SUCCESS) ? key < map->map.max_entries ? status : STATUS_INVALID_PARAMETER : status;
status = (status == STATUS_SUCCESS) ? key < map->map.ebpf_map_definition.max_entries ? status : STATUS_INVALID_PARAMETER : status;
// If success, then compute value offset
status = (status == STATUS_SUCCESS) ? RtlSizeTMult(key, map->map.value_size, &value_offset) : status;
status = (status == STATUS_SUCCESS) ? RtlSizeTMult(key, map->map.ebpf_map_definition.value_size, &value_offset) : status;
if (status == STATUS_SUCCESS)
{
memset(map->map.data + value_offset, 0, map->map.value_size);
memset(map->map.data + value_offset, 0, map->map.ebpf_map_definition.value_size);
}
}
KeReleaseSpinLock(&gMapLock, irql);
KeReleaseSpinLock(&_ebpf_core_map_entry_list_lock, old_irql);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: EbpfCoreProtocolMapLookupElement 0x%llx handle\n", request->handle));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: ebpf_core_protocol_map_lookup_element 0x%llx handle\n", request->handle));
return status;
}
// EBPF helper functions
void* EbpfCoreMapLookupElement(EbpfCoreMap* map, uint32_t* key)
void* _ebpf_core_map_lookup_element(ebpf_core_map_t* map, uint32_t* key)
{
if (!map || !key)
return NULL;
if (*key > map->max_entries)
if (*key > map->ebpf_map_definition.max_entries)
return NULL;
return &map->data[*key * map->value_size];
return &map->data[*key * map->ebpf_map_definition.value_size];
}
void EbpfCoreMapUpdateElement(EbpfCoreMap* map, uint32_t* key, uint8_t* data)
void _ebpf_core_map_update_element(ebpf_core_map_t* map, uint32_t* key, uint8_t* data)
{
if (!map || !key)
return;
if (*key > map->max_entries)
if (*key > map->ebpf_map_definition.max_entries)
return;
uint8_t* entry = &map->data[*key * map->value_size];
memcpy(entry, data, map->value_size);
uint8_t* entry = &map->data[*key * map->ebpf_map_definition.value_size];
memcpy(entry, data, map->ebpf_map_definition.value_size);
}
void EbpfCoreMapDeleteElement(EbpfCoreMap* map, uint32_t* key)
void _ebpf_core_map_delete_element(ebpf_core_map_t* map, uint32_t* key)
{
if (!map || !key)
return;
if (*key > map->max_entries)
if (*key > map->ebpf_map_definition.max_entries)
return;
uint8_t* entry = &map->data[*key * map->value_size];
memset(entry, 0, map->value_size);
uint8_t* entry = &map->data[*key * map->ebpf_map_definition.value_size];
memset(entry, 0, map->ebpf_map_definition.value_size);
}

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

@ -7,91 +7,97 @@
// XDP like hook
typedef struct xdp_md_ {
typedef struct _xdp_md {
UINT64 data; /* 0 8 */
UINT64 data_end; /* 8 8 */
UINT64 data_meta; /* 16 8 */
/* size: 12, cachelines: 1, members: 3 */
/* last cacheline: 12 bytes */
} xdp_md;
} xdp_md_t;
typedef DWORD(__stdcall* XDP_HOOK) (PVOID);
typedef DWORD(__stdcall* xdp_hook_function) (PVOID);
typedef enum xdp_action_
typedef enum _xdp_action
{
XDP_PASS = 1,
XDP_DROP = 2
} xdp_action;
} xdp_action_t;
typedef enum ebpf_map_type_
typedef enum _ebpf_map_type
{
ebpf_map_array = 2
} ebpf_map_type;
EBPF_MAP_ARRAY = 2
} ebpf_map_type_t;
typedef enum ebpf_helper_function_
typedef enum _ebpf_helper_function
{
ebpf_lookup_element = 1,
ebpf_update_element = 2,
EBPF_LOOKUP_ELEMENT = 1,
EBPF_UPDATE_ELEMENT = 2,
ebpf_delete_element = 3,
ebpf_invalid
} ebpf_helper_function;
EBPF_INVALID
} ebpf_helper_function_t;
typedef enum ebpf_hook_point_
typedef enum _ebpf_hook_point
{
ebpf_hook_none = 0,
ebpf_hook_xdp = 1
} ebpf_hook_point;
EBPF_HOOK_NONE = 0,
EBPF_HOOK_XDP = 1
} ebpf_hook_point_t;
NTSTATUS EbpfCoreInitialize();
void EbpfCoreTerminate();
NTSTATUS ebpf_core_initialize();
void ebpf_core_terminate();
NTSTATUS
EbpfCoreProtocolAttachCode(
_In_ struct EbpfOpAttachDetachRequest* request,
ebpf_core_protocol_attach_code(
_In_ struct _ebpf_operation_attach_detach_request* request,
_Inout_ void* reply);
NTSTATUS
EbpfCoreProtocolDetachCode(
_In_ struct EbpfOpAttachDetachRequest* request,
ebpf_core_protocol_detach_code(
_In_ struct _ebpf_operation_attach_detach_request* request,
_Inout_ void* reply);
NTSTATUS
EbpfCoreProtocolUnloadCode(
_In_ struct EbpfOpUnloadRequest* request,
ebpf_core_protocol_unload_code(
_In_ struct _ebpf_operation_unload_code_request* request,
_Inout_ void* reply);
NTSTATUS
EbpfCoreProtocolLoadCode(
_In_ struct EbpfOpLoadRequest* inputRequest,
_Inout_ struct EbpfOpLoadReply* loadReply);
ebpf_core_protocol_load_code(
_In_ struct _ebpf_operation_load_code_request* inputRequest,
_Inout_ struct _ebpf_operation_load_code_reply* loadReply);
NTSTATUS EbpfCoreProtocolResolveHelper(
_In_ struct EbpfOpResolveHelperRequest* request,
_Out_ struct EbpfOpResolveHelperReply* reply);
NTSTATUS
ebpf_core_protocol_resolve_helper(
_In_ struct _ebpf_operation_resolve_helper_request* request,
_Out_ struct _ebpf_operation_resolve_helper_reply* reply);
NTSTATUS EbpfCoreProtocolResolveMap(
_In_ struct EbpfOpResolveMapRequest* request,
_Out_ struct EbpfOpResolveMapReply* reply);
NTSTATUS
ebpf_core_protocol_resolve_map(
_In_ struct _ebpf_operation_resolve_map_request* request,
_Out_ struct _ebpf_operation_resolve_map_reply* reply);
NTSTATUS EbpfCoreProtocolCreateMap(
_In_ struct EbpfOpCreateMapRequest* request,
_Inout_ struct EbpfOpCreateMapReply* reply);
NTSTATUS
ebpf_core_protocol_create_map(
_In_ struct _ebpf_operation_create_map_request* request,
_Inout_ struct _ebpf_operation_create_map_reply* reply);
NTSTATUS EbpfCoreProtocolMapLookupElement(
_In_ struct EbpfOpMapLookupElementRequest* request,
_Inout_ struct EbpfOpMapLookupElementReply* reply);
NTSTATUS
ebpf_core_protocol_map_lookup_element(
_In_ struct _ebpf_operation_map_lookup_element_request* request,
_Inout_ struct _ebpf_operation_map_lookup_element_reply* reply);
NTSTATUS EbpfCoreProtocolMapUpdateElement(
_In_ struct EpfOpMapUpdateElementRequest* request,
NTSTATUS
ebpf_core_protocol_map_update_element(
_In_ struct _ebpf_operation_map_update_element_request* request,
_Inout_ void* reply);
NTSTATUS EbpfCoreProtocolMapDeleteElement(
_In_ struct EbpfOpMapDeleteElementRequest* request,
NTSTATUS
ebpf_core_protocol_map_delete_element(
_In_ struct _ebpf_operation_map_delete_element_request* request,
_Inout_ void* reply);
xdp_action
EbpfCoreInvokeXdpHook(
xdp_action_t
ebpf_core_invoke_xdp_hook(
_In_ void* buffer,
_In_ uint32_t buffer_length
);

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

@ -36,8 +36,8 @@ Environment:
// Driver global variables
DEVICE_OBJECT* gWdmDevice;
BOOLEAN gDriverUnloading = FALSE;
static DEVICE_OBJECT* _wdm_device_object;
static BOOLEAN _driver_unloading_flag = FALSE;
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_UNLOAD EvtDriverUnload;
@ -54,8 +54,8 @@ typedef DWORD(WINAPI* FUNCTION_TYPE2) (PVOID, PVOID);
//
// Constants
//
PCWSTR EbpfDeviceName = L"\\Device\\EbpfIoDevice";
PCWSTR EbpfSymbolicDeviceName = L"\\GLOBAL??\\EbpfIoDevice";
static const wchar_t EBPF_DEVICE_NAME[] = L"\\Device\\EbpfIoDevice";
static const wchar_t EBPF_SYMBOLIC_DEVICE_NAME[] = L"\\GLOBAL??\\EbpfIoDevice";
#ifndef CTL_CODE
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
@ -72,13 +72,13 @@ PCWSTR EbpfSymbolicDeviceName = L"\\GLOBAL??\\EbpfIoDevice";
//
// Pre-Declarations
//
VOID
static VOID
EbpfCoreEvtIoDeviceControl(
_In_ WDFQUEUE queue,
_In_ WDFREQUEST request,
_In_ size_t outputBufferLength,
_In_ size_t inputBufferLength,
_In_ ULONG ioControlCode
_In_ size_t output_buffer_length,
_In_ size_t input_buffer_length,
_In_ ULONG io_control_code
);
_Function_class_(EVT_WDF_DRIVER_UNLOAD)
@ -86,52 +86,52 @@ _IRQL_requires_same_
_IRQL_requires_max_(PASSIVE_LEVEL)
void
EvtDriverUnload(
_In_ WDFDRIVER driverObject
_In_ WDFDRIVER driver_object
)
{
UNREFERENCED_PARAMETER(driverObject);
UNREFERENCED_PARAMETER(driver_object);
gDriverUnloading = TRUE;
_driver_unloading_flag = TRUE;
EbpfHookUnregisterCallouts();
ebpf_hook_unregister_callouts();
EbpfCoreTerminate();
ebpf_core_terminate();
}
//
// Create a basic WDF driver, set up the device object
// for a callout driver and setup the ioctl surface
//
NTSTATUS
static NTSTATUS
EbpfCoreInitDriverObjects(
_Inout_ DRIVER_OBJECT* driverObject,
_In_ const UNICODE_STRING* registryPath,
_Out_ WDFDRIVER* pDriver,
_Out_ WDFDEVICE* pDevice
_Inout_ DRIVER_OBJECT* driver_object,
_In_ const UNICODE_STRING* registry_path,
_Out_ WDFDRIVER* driver,
_Out_ WDFDEVICE* device
)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
PWDFDEVICE_INIT pInit = NULL;
WDF_IO_QUEUE_CONFIG ioQueueConfig;
UNICODE_STRING ebpfDeviceName;
UNICODE_STRING ebpfSymDeviceName;
BOOLEAN deviceCreated = FALSE;
WDF_DRIVER_CONFIG driver_configuration;
PWDFDEVICE_INIT device_initialize = NULL;
WDF_IO_QUEUE_CONFIG io_queue_configuration;
UNICODE_STRING ebpf_device_name;
UNICODE_STRING ebpf_symbolic_device_name;
BOOLEAN device_create_flag = FALSE;
WDF_DRIVER_CONFIG_INIT(
&config,
&driver_configuration,
WDF_NO_EVENT_CALLBACK
);
config.DriverInitFlags |= WdfDriverInitNonPnpDriver;
config.EvtDriverUnload = EvtDriverUnload;
driver_configuration.DriverInitFlags |= WdfDriverInitNonPnpDriver;
driver_configuration.EvtDriverUnload = EvtDriverUnload;
status = WdfDriverCreate(
driverObject,
registryPath,
driver_object,
registry_path,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
pDriver
&driver_configuration,
driver
);
if (!NT_SUCCESS(status))
@ -139,60 +139,60 @@ EbpfCoreInitDriverObjects(
goto Exit;
}
pInit = WdfControlDeviceInitAllocate(
*pDriver,
device_initialize = WdfControlDeviceInitAllocate(
*driver,
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL // only kernel/system and admins
);
if (!pInit)
if (!device_initialize)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
WdfDeviceInitSetDeviceType(
pInit,
device_initialize,
FILE_DEVICE_NETWORK
);
WdfDeviceInitSetCharacteristics(
pInit,
device_initialize,
FILE_DEVICE_SECURE_OPEN,
FALSE
);
WdfDeviceInitSetCharacteristics(
pInit,
device_initialize,
FILE_AUTOGENERATED_DEVICE_NAME,
TRUE
);
RtlInitUnicodeString(&ebpfDeviceName, EbpfDeviceName);
RtlInitUnicodeString(&ebpf_device_name, EBPF_DEVICE_NAME);
WdfDeviceInitAssignName(
pInit,
&ebpfDeviceName);
device_initialize,
&ebpf_device_name);
status = WdfDeviceCreate(
&pInit,
&device_initialize,
WDF_NO_OBJECT_ATTRIBUTES,
pDevice
device
);
if (!NT_SUCCESS(status))
{
// do not free if any other call
// after WdfDeviceCreate fails.
WdfDeviceInitFree(pInit);
pInit = NULL;
WdfDeviceInitFree(device_initialize);
device_initialize = NULL;
goto Exit;
}
deviceCreated = TRUE;
device_create_flag = TRUE;
// create symbolic link for control object for um
RtlInitUnicodeString(&ebpfSymDeviceName, EbpfSymbolicDeviceName);
RtlInitUnicodeString(&ebpf_symbolic_device_name, EBPF_SYMBOLIC_DEVICE_NAME);
status = WdfDeviceCreateSymbolicLink(
*pDevice,
&ebpfSymDeviceName);
*device,
&ebpf_symbolic_device_name);
if (!NT_SUCCESS(status))
{
@ -200,14 +200,14 @@ EbpfCoreInitDriverObjects(
}
// parallel default queue
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&io_queue_configuration,
WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoDeviceControl = EbpfCoreEvtIoDeviceControl;
io_queue_configuration.EvtIoDeviceControl = EbpfCoreEvtIoDeviceControl;
status = WdfIoQueueCreate(
*pDevice,
&ioQueueConfig,
*device,
&io_queue_configuration,
WDF_NO_OBJECT_ATTRIBUTES,
WDF_NO_HANDLE // pointer to default queue
);
@ -215,97 +215,83 @@ EbpfCoreInitDriverObjects(
{
goto Exit;
}
status = EbpfCoreInitialize();
status = ebpf_core_initialize();
if (!NT_SUCCESS(status))
{
goto Exit;
}
WdfControlFinishInitializing(*pDevice);
WdfControlFinishInitializing(*device);
Exit:
if (!NT_SUCCESS(status))
{
if (deviceCreated && pDevice != NULL)
if (device_create_flag && device != NULL)
{
//
// Release the reference on the newly created object, since
// we couldn't initialize it.
//
WdfObjectDelete(*pDevice);
WdfObjectDelete(*device);
}
}
return status;
}
// Dummy drop function
int DropPacket(unsigned int protocol)
{
if (protocol == IPPROTO_UDP)
{
return 0;
}
else
{
return 1;
}
}
const struct {
NTSTATUS(*protocol_handler)(_In_ void* inputBuffer, void* outputBuffer);
static const struct {
NTSTATUS(*protocol_handler)(_In_ void* input_buffer, void* output_buffer);
SIZE_T minimum_request_size;
BOOL has_output;
SIZE_T minimum_reply_size;
} EbpfProtocolHandlers[] = {
{ NULL, sizeof(struct EbpfOpEvidenceRequest) }, //evidence
{ EbpfCoreProtocolResolveHelper, sizeof(struct EbpfOpResolveHelperRequest), TRUE },
{ EbpfCoreProtocolResolveMap, sizeof(struct EbpfOpResolveMapRequest), TRUE },
{ EbpfCoreProtocolLoadCode, sizeof(struct EbpfOpLoadRequest), TRUE },
{ EbpfCoreProtocolUnloadCode, sizeof(struct EbpfOpUnloadRequest), FALSE },
{ EbpfCoreProtocolAttachCode, sizeof(struct EbpfOpAttachDetachRequest), FALSE },
{ EbpfCoreProtocolDetachCode, sizeof(struct EbpfOpAttachDetachRequest), FALSE },
{ EbpfCoreProtocolCreateMap, sizeof(struct EbpfOpCreateMapRequest), TRUE },
{ EbpfCoreProtocolMapLookupElement, sizeof(struct EbpfOpMapLookupElementRequest), TRUE },
{ EbpfCoreProtocolMapUpdateElement, sizeof(struct EpfOpMapUpdateElementRequest), FALSE },
{ EbpfCoreProtocolMapDeleteElement, sizeof(struct EbpfOpMapDeleteElementRequest), FALSE }
{ NULL, sizeof(struct _ebpf_operation_eidence_request) }, //EBPF_OPERATION_EVIDENCE
{ ebpf_core_protocol_resolve_helper, sizeof(struct _ebpf_operation_resolve_helper_request), sizeof(struct _ebpf_operation_resolve_helper_reply) },
{ ebpf_core_protocol_resolve_map, sizeof(struct _ebpf_operation_resolve_map_request), sizeof(struct _ebpf_operation_resolve_map_reply) },
{ ebpf_core_protocol_load_code, sizeof(struct _ebpf_operation_load_code_request), sizeof(struct _ebpf_operation_load_code_reply) },
{ ebpf_core_protocol_unload_code, sizeof(struct _ebpf_operation_unload_code_request), 0 },
{ ebpf_core_protocol_attach_code, sizeof(struct _ebpf_operation_attach_detach_request), 0 },
{ ebpf_core_protocol_detach_code, sizeof(struct _ebpf_operation_attach_detach_request), 0 },
{ ebpf_core_protocol_create_map, sizeof(struct _ebpf_operation_create_map_request), sizeof(struct _ebpf_operation_create_map_request) },
{ ebpf_core_protocol_map_lookup_element, sizeof(struct _ebpf_operation_map_lookup_element_request), sizeof(struct _ebpf_operation_map_lookup_element_reply) },
{ ebpf_core_protocol_map_update_element, sizeof(struct _ebpf_operation_map_update_element_request), 0 },
{ ebpf_core_protocol_map_delete_element, sizeof(struct _ebpf_operation_map_delete_element_request), 0 }
};
VOID
static VOID
EbpfCoreEvtIoDeviceControl(
_In_ WDFQUEUE queue,
_In_ WDFREQUEST request,
_In_ size_t outputBufferLength,
_In_ size_t inputBufferLength,
_In_ ULONG ioControlCode
_In_ size_t output_buffer_length,
_In_ size_t input_buffer_length,
_In_ ULONG io_control_code
)
{
NTSTATUS status = STATUS_SUCCESS;
WDFDEVICE device;
void* inputBuffer = NULL;
void* outputBuffer = NULL;
size_t actualInputLength;
size_t actualOutputLength;
struct EbpfOpHeader* inputRequest = NULL;
struct EbpfOpHeader* outputRequest = NULL;
void* input_buffer = NULL;
void* output_buffer = NULL;
size_t actual_input_length;
size_t actual_output_length;
struct _ebpf_operation_header* user_request = NULL;
struct _ebpf_operation_header* user_reply = NULL;
UNREFERENCED_PARAMETER(outputBufferLength);
UNREFERENCED_PARAMETER(inputBufferLength);
UNREFERENCED_PARAMETER(output_buffer_length);
UNREFERENCED_PARAMETER(input_buffer_length);
device = WdfIoQueueGetDevice(queue);
switch (ioControlCode)
switch (io_control_code)
{
case IOCTL_EBPFCTL_METHOD_BUFFERED:
// Verify that length of the input buffer supplied to the request object
// is not zero
if (inputBufferLength != 0)
if (input_buffer_length != 0)
{
// Retrieve the input buffer associated with the request object
status = WdfRequestRetrieveInputBuffer(
request, // Request object
inputBufferLength, // Length of input buffer
&inputBuffer, // Pointer to buffer
&actualInputLength // Length of buffer
input_buffer_length, // Length of input buffer
&input_buffer, // Pointer to buffer
&actual_input_length // Length of buffer
);
if (!NT_SUCCESS(status))
@ -314,68 +300,74 @@ EbpfCoreEvtIoDeviceControl(
goto Done;
}
if (inputBuffer == NULL)
if (input_buffer == NULL)
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (inputBuffer != NULL)
if (input_buffer != NULL)
{
status = EbpfHookRegisterCallouts(gWdmDevice);
status = ebpf_hook_register_callouts(_wdm_device_object);
// non fatal for now while testing
inputRequest = inputBuffer;
if (actualInputLength < sizeof(struct EbpfOpHeader))
user_request = input_buffer;
if (actual_input_length < sizeof(struct _ebpf_operation_header))
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (inputRequest->id >= sizeof(EbpfProtocolHandlers) / sizeof(EbpfProtocolHandlers[0]))
if (user_request->id >= sizeof(EbpfProtocolHandlers) / sizeof(EbpfProtocolHandlers[0]))
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (inputRequest->length < EbpfProtocolHandlers[inputRequest->id].minimum_request_size)
if (user_request->length < EbpfProtocolHandlers[user_request->id].minimum_request_size)
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (!EbpfProtocolHandlers[inputRequest->id].protocol_handler)
if (!EbpfProtocolHandlers[user_request->id].protocol_handler)
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
if (EbpfProtocolHandlers[inputRequest->id].has_output)
if (EbpfProtocolHandlers[user_request->id].minimum_reply_size > 0)
{
// Retrieve output buffer associated with the request object
status = WdfRequestRetrieveOutputBuffer(
request,
outputBufferLength,
&outputBuffer,
&actualOutputLength
output_buffer_length,
&output_buffer,
&actual_output_length
);
if (!NT_SUCCESS(status))
{
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: Output buffer failure %d\n", status));
goto Done;
}
if (outputBuffer == NULL)
if (output_buffer == NULL)
{
status = STATUS_INVALID_PARAMETER;
goto Done;
}
outputRequest->id = inputRequest->id;
outputRequest->length = (uint16_t)actualOutputLength;
if (actual_output_length < EbpfProtocolHandlers[user_request->id].minimum_reply_size)
{
status = STATUS_BUFFER_TOO_SMALL;
goto Done;
}
user_reply = output_buffer;
user_reply->id = user_request->id;
user_reply->length = (uint16_t)actual_output_length;
}
status = EbpfProtocolHandlers[inputRequest->id].protocol_handler(inputBuffer, outputBuffer);
status = EbpfProtocolHandlers[user_request->id].protocol_handler(user_request, user_reply);
goto Done;
}
}
@ -390,14 +382,14 @@ EbpfCoreEvtIoDeviceControl(
}
Done:
WdfRequestCompleteWithInformation(request, status, outputBufferLength);
WdfRequestCompleteWithInformation(request, status, output_buffer_length);
return;
}
NTSTATUS
DriverEntry(
_In_ DRIVER_OBJECT* driverObject,
_In_ UNICODE_STRING* registryPath
_In_ DRIVER_OBJECT* driver_object,
_In_ UNICODE_STRING* registry_path
)
{
NTSTATUS status;
@ -410,8 +402,8 @@ DriverEntry(
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: DriverEntry\n"));
status = EbpfCoreInitDriverObjects(
driverObject,
registryPath,
driver_object,
registry_path,
&driver,
&device
);
@ -421,9 +413,9 @@ DriverEntry(
goto Exit;
}
gWdmDevice = WdfDeviceWdmGetDeviceObject(device);
_wdm_device_object = WdfDeviceWdmGetDeviceObject(device);
EbpfHookRegisterCallouts(gWdmDevice);
ebpf_hook_register_callouts(_wdm_device_object);
// ignore status. at boot, registration can fail.
// we will try to re-register during prog load.
@ -431,7 +423,7 @@ Exit:
if (!NT_SUCCESS(status))
{
EbpfHookUnregisterCallouts();
ebpf_hook_unregister_callouts();
}
return status;

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

@ -56,31 +56,31 @@ DEFINE_GUID(
);
// Callout globals
HANDLE gEngineHandle;
UINT32 gL2CalloutId;
static HANDLE _fwp_engine_handle;
static UINT32 _fwp_layer_2_callout_id;
NTSTATUS
EbpfHookAddFilter(
_In_ const PWSTR filterName,
_In_ const PWSTR filterDesc,
_In_ FWP_DIRECTION direction,
_In_ const GUID* layerKey,
_In_ const GUID* calloutKey
_In_ const PWSTR filter_name,
_In_ const PWSTR filter_description,
_In_ FWP_DIRECTION filter_direction,
_In_ const GUID* fwpm_layer_key,
_In_ const GUID* fwpm_callout_key
)
{
UNREFERENCED_PARAMETER(direction);
UNREFERENCED_PARAMETER(filter_direction);
NTSTATUS status = STATUS_SUCCESS;
FWPM_FILTER filter = { 0 };
FWPM_FILTER_CONDITION filterConditions[3] = { 0 };
UINT conditionIndex;
filter.layerKey = *layerKey;
filter.displayData.name = (wchar_t*)filterName;
filter.displayData.description = (wchar_t*)filterDesc;
filter.layerKey = *fwpm_layer_key;
filter.displayData.name = (wchar_t*)filter_name;
filter.displayData.description = (wchar_t*)filter_description;
filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
filter.action.calloutKey = *calloutKey;
filter.action.calloutKey = *fwpm_callout_key;
filter.filterCondition = filterConditions;
filter.subLayerKey = EBPF_HOOK_SUBLAYER;
filter.weight.type = FWP_EMPTY; // auto-weight.
@ -98,7 +98,7 @@ EbpfHookAddFilter(
filter.numFilterConditions = conditionIndex;
status = FwpmFilterAdd(
gEngineHandle,
_fwp_engine_handle,
&filter,
NULL,
NULL);
@ -109,10 +109,10 @@ EbpfHookAddFilter(
NTSTATUS
EbpfHookRegisterL2Callout(
_In_ const GUID* layerKey,
_In_ const GUID* calloutKey,
_Inout_ void* deviceObject,
_Out_ UINT32* calloutId
_In_ const GUID* fwpm_layer_key,
_In_ const GUID* fwpm_callout_key,
_Inout_ void* device_object,
_Out_ UINT32* fwpm_callout_id
)
/* ++
@ -130,16 +130,16 @@ EbpfHookRegisterL2Callout(
BOOLEAN calloutRegistered = FALSE;
sCallout.calloutKey = *calloutKey;
sCallout.classifyFn = EbpfHookL2Classify;
sCallout.notifyFn = EbpfHookL2Notify;
sCallout.flowDeleteFn = EbpfHookL2FlowDelete;
sCallout.calloutKey = *fwpm_callout_key;
sCallout.classifyFn = ebpf_hook_layer_2_classify;
sCallout.notifyFn = ebpf_hook_layer_2_notify;
sCallout.flowDeleteFn = ebpf_hook_layer_2_flow_delete;
sCallout.flags = 0;
status = FwpsCalloutRegister(
deviceObject,
device_object,
&sCallout,
calloutId
fwpm_callout_id
);
if (!NT_SUCCESS(status))
{
@ -150,12 +150,12 @@ EbpfHookRegisterL2Callout(
displayData.name = L"L2 XDP Callout";
displayData.description = L"L2 callout driver for eBPF at XDP-like layer";
mCallout.calloutKey = *calloutKey;
mCallout.calloutKey = *fwpm_callout_key;
mCallout.displayData = displayData;
mCallout.applicableLayer = *layerKey;
mCallout.applicableLayer = *fwpm_layer_key;
status = FwpmCalloutAdd(
gEngineHandle,
_fwp_engine_handle,
&mCallout,
NULL,
NULL
@ -170,8 +170,8 @@ EbpfHookRegisterL2Callout(
L"L2 filter (Inbound)",
L"L2 filter inbound",
FWP_DIRECTION_INBOUND,
layerKey,
calloutKey
fwpm_layer_key,
fwpm_callout_key
);
if (!NT_SUCCESS(status))
@ -185,8 +185,8 @@ Exit:
{
if (calloutRegistered)
{
FwpsCalloutUnregisterById(*calloutId);
*calloutId = 0;
FwpsCalloutUnregisterById(*fwpm_callout_id);
*fwpm_callout_id = 0;
}
}
@ -194,8 +194,8 @@ Exit:
}
NTSTATUS
EbpfHookRegisterCallouts(
_Inout_ void* deviceObject
ebpf_hook_register_callouts(
_Inout_ void* device_object
)
/* ++
@ -214,7 +214,7 @@ EbpfHookRegisterCallouts(
FWPM_SESSION session = { 0 };
if (gEngineHandle != NULL)
if (_fwp_engine_handle != NULL)
{
// already registered
goto Exit;
@ -227,7 +227,7 @@ EbpfHookRegisterCallouts(
RPC_C_AUTHN_WINNT,
NULL,
&session,
&gEngineHandle
&_fwp_engine_handle
);
if (!NT_SUCCESS(status))
{
@ -235,7 +235,7 @@ EbpfHookRegisterCallouts(
}
engineOpened = TRUE;
status = FwpmTransactionBegin(gEngineHandle, 0);
status = FwpmTransactionBegin(_fwp_engine_handle, 0);
if (!NT_SUCCESS(status))
{
goto Exit;
@ -251,7 +251,7 @@ EbpfHookRegisterCallouts(
ebpfHookL2SubLayer.flags = 0;
ebpfHookL2SubLayer.weight = FWP_EMPTY; // auto-weight.;
status = FwpmSubLayerAdd(gEngineHandle, &ebpfHookL2SubLayer, NULL);
status = FwpmSubLayerAdd(_fwp_engine_handle, &ebpfHookL2SubLayer, NULL);
if (!NT_SUCCESS(status))
{
goto Exit;
@ -260,15 +260,15 @@ EbpfHookRegisterCallouts(
status = EbpfHookRegisterL2Callout(
&FWPM_LAYER_INBOUND_MAC_FRAME_ETHERNET,
&EBPF_HOOK_L2_CALLOUT,
deviceObject,
&gL2CalloutId
device_object,
&_fwp_layer_2_callout_id
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = FwpmTransactionCommit(gEngineHandle);
status = FwpmTransactionCommit(_fwp_engine_handle);
if (!NT_SUCCESS(status))
{
goto Exit;
@ -281,13 +281,13 @@ Exit:
{
if (inTransaction)
{
FwpmTransactionAbort(gEngineHandle);
_Analysis_assume_lock_not_held_(gEngineHandle); // Potential leak if "FwpmTransactionAbort" fails
FwpmTransactionAbort(_fwp_engine_handle);
_Analysis_assume_lock_not_held_(_fwp_engine_handle); // Potential leak if "FwpmTransactionAbort" fails
}
if (engineOpened)
{
FwpmEngineClose(gEngineHandle);
gEngineHandle = NULL;
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
}
}
@ -295,26 +295,26 @@ Exit:
}
void
EbpfHookUnregisterCallouts(void)
ebpf_hook_unregister_callouts(void)
{
if (gEngineHandle != NULL)
if (_fwp_engine_handle != NULL)
{
FwpmEngineClose(gEngineHandle);
gEngineHandle = NULL;
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
FwpsCalloutUnregisterById(gL2CalloutId);
FwpsCalloutUnregisterById(_fwp_layer_2_callout_id);
}
}
void
EbpfHookL2Classify(
_In_ const FWPS_INCOMING_VALUES* inFixedValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
_Inout_opt_ void* layerData,
_In_opt_ const void* classifyContext,
ebpf_hook_layer_2_classify(
_In_ const FWPS_INCOMING_VALUES* incoming_fixed_values,
_In_ const FWPS_INCOMING_METADATA_VALUES* incoming_metadata_values,
_Inout_opt_ void* layer_data,
_In_opt_ const void* classify_context,
_In_ const FWPS_FILTER* filter,
_In_ UINT64 flowContext,
_Inout_ FWPS_CLASSIFY_OUT* classifyOut
_In_ UINT64 flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output
)
/* ++
@ -323,14 +323,14 @@ EbpfHookL2Classify(
-- */
{
FWP_ACTION_TYPE action = FWP_ACTION_PERMIT;
UNREFERENCED_PARAMETER(inFixedValues);
UNREFERENCED_PARAMETER(inMetaValues);
UNREFERENCED_PARAMETER(classifyContext);
UNREFERENCED_PARAMETER(incoming_fixed_values);
UNREFERENCED_PARAMETER(incoming_metadata_values);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flowContext);
NET_BUFFER_LIST* nbl = (NET_BUFFER_LIST*)layerData;
NET_BUFFER* netBuffer = NULL;
BYTE* mdlAddr;
UNREFERENCED_PARAMETER(flow_context);
NET_BUFFER_LIST* nbl = (NET_BUFFER_LIST*)layer_data;
NET_BUFFER* net_buffer = NULL;
BYTE* packet_buffer;
UINT32 result = 0;
if (nbl == NULL)
@ -339,25 +339,25 @@ EbpfHookL2Classify(
goto done;
}
netBuffer = NET_BUFFER_LIST_FIRST_NB(nbl);
if (netBuffer == NULL)
net_buffer = NET_BUFFER_LIST_FIRST_NB(nbl);
if (net_buffer == NULL)
{
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "netbuffer not present\n"));
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "net_buffer not present\n"));
// nothing to do
goto done;
}
mdlAddr =
packet_buffer =
NdisGetDataBuffer(
netBuffer,
netBuffer->DataLength,
net_buffer,
net_buffer->DataLength,
NULL,
sizeof(UINT16),
0);
// execute code at hook.
result = EbpfCoreInvokeXdpHook(mdlAddr, netBuffer->DataLength);
result = ebpf_core_invoke_xdp_hook(packet_buffer, net_buffer->DataLength);
switch (result)
{
case XDP_PASS:
@ -369,29 +369,29 @@ EbpfHookL2Classify(
}
done:
classifyOut->actionType = action;
classify_output->actionType = action;
return;
}
NTSTATUS
EbpfHookL2Notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE notifyType,
_In_ const GUID* filterKey,
ebpf_hook_layer_2_notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID* filter_key,
_Inout_ const FWPS_FILTER* filter
)
{
UNREFERENCED_PARAMETER(notifyType);
UNREFERENCED_PARAMETER(filterKey);
UNREFERENCED_PARAMETER(callout_notification_type);
UNREFERENCED_PARAMETER(filter_key);
UNREFERENCED_PARAMETER(filter);
return STATUS_SUCCESS;
}
void
EbpfHookL2FlowDelete(
_In_ UINT16 layerId,
_In_ UINT32 calloutId,
_In_ UINT64 flowContext
ebpf_hook_layer_2_flow_delete(
_In_ UINT16 layer_id,
_In_ UINT32 fwpm_callout_id,
_In_ UINT64 flow_context
)
/* ++
@ -399,8 +399,8 @@ EbpfHookL2FlowDelete(
-- */
{
UNREFERENCED_PARAMETER(layerId);
UNREFERENCED_PARAMETER(calloutId);
UNREFERENCED_PARAMETER(flowContext);
UNREFERENCED_PARAMETER(layer_id);
UNREFERENCED_PARAMETER(fwpm_callout_id);
UNREFERENCED_PARAMETER(flow_context);
return;
}

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

@ -16,48 +16,40 @@ Environment:
--*/
#ifndef _EBPF_L2HOOK_H_
#define _EBPF_L2HOOK_H_
#pragma once
#include "types.h"
extern UINT32 gL2CalloutId;
extern BOOLEAN gDriverUnloading;
//
// Shared function prototypes
//
NTSTATUS
EbpfHookRegisterCallouts(
_Inout_ void* deviceObject
ebpf_hook_register_callouts(
_Inout_ void* device_object
);
void
EbpfHookUnregisterCallouts(void);
ebpf_hook_unregister_callouts(void);
void
EbpfHookL2Classify(
_In_ const FWPS_INCOMING_VALUES* inFixedValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
_Inout_opt_ void* layerData,
_In_opt_ const void* classifyContext,
_In_ const FWPS_FILTER* filter,
_In_ UINT64 flowContext,
_Inout_ FWPS_CLASSIFY_OUT* classifyOut
);
ebpf_hook_layer_2_classify(
_In_ const FWPS_INCOMING_VALUES* incoming_fixed_values,
_In_ const FWPS_INCOMING_METADATA_VALUES* incoming_metadata_values,
_Inout_opt_ void* layer_data,
_In_opt_ const void* classify_context,
_In_ const FWPS_FILTER* filter,
_In_ UINT64 flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output);
void
EbpfHookL2FlowDelete(
_In_ UINT16 layerId,
_In_ UINT32 calloutId,
_In_ UINT64 flowContext
);
ebpf_hook_layer_2_flow_delete(
_In_ UINT16 layer_id,
_In_ UINT32 fwpm_callout_id,
_In_ UINT64 flow_context);
NTSTATUS
EbpfHookL2Notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE notifyType,
_In_ const GUID* filterKey,
_Inout_ const FWPS_FILTER* filter
);
ebpf_hook_layer_2_notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID* filter_key,
_Inout_ const FWPS_FILTER* filter);
#endif // _EBPF_L2HOOK_H_

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

@ -24,23 +24,23 @@ int main(
_In_reads_(argc) PCHAR argv[]
)
{
HANDLE deviceHandle = INVALID_HANDLE_VALUE;
HANDLE device_handle = INVALID_HANDLE_VALUE;
DWORD error = NO_ERROR;
LPCWSTR ebpfDeviceName = L"\\\\.\\EbpfIoDevice";
ULONG bytesReturned;
void* inputBuffer = NULL;
struct EbpfOpHeader* header = NULL;
LPCWSTR ebpf_device_name = L"\\\\.\\EbpfIoDevice";
ULONG bytes_returned;
void* input_buffer = NULL;
struct _ebpf_operation_header* header = NULL;
int action = 0;
UINT64 inputHandle;
DWORD inputBufferLength;
struct EbpfOpLoadRequest* loadRequest;
struct EbpfOpLoadReply outputBuffer = { 0 };
DWORD outputBufferLength = sizeof(struct EbpfOpLoadReply);
UINT64 input_handle;
DWORD input_bufferLength;
struct _ebpf_operation_load_code_request* load_request;
struct _ebpf_operation_load_code_reply output_buffer = { 0 };
DWORD output_buffer_length = sizeof(struct _ebpf_operation_load_code_reply);
UINT64 handle = 0;
if (argc < 2)
{
printf("usage: ebpftool.exe <load(0)/attach(1)/unload(2)> <handle>\n");
printf("usage: ebpftool.exe <load(0)/EBPF_OPERATION_ATTACH_CODE(1)/unload(2)> <handle>\n");
return;
}
@ -49,13 +49,13 @@ int main(
{
if (argc < 3)
{
printf("handle required for attach and unload.\n");
printf("handle required for EBPF_OPERATION_ATTACH_CODE and unload.\n");
return;
}
inputHandle = atoi(argv[2]);
input_handle = atoi(argv[2]);
}
deviceHandle = CreateFile(ebpfDeviceName,
device_handle = CreateFile(ebpf_device_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
@ -63,7 +63,7 @@ int main(
FILE_ATTRIBUTE_NORMAL,
NULL);
if (deviceHandle == INVALID_HANDLE_VALUE)
if (device_handle == INVALID_HANDLE_VALUE)
{
error = GetLastError();
printf("Error: CreatFile Failed : %d\n", error);
@ -117,10 +117,10 @@ Disassembly of section :
0xb8, 0x01, 00, 00, 00,
0xc3
};
inputBufferLength = sizeof(code) + sizeof(struct EbpfOpLoadRequest);
input_bufferLength = sizeof(code) + sizeof(struct _ebpf_operation_load_code_request);
inputBuffer = malloc(inputBufferLength);
if (inputBuffer == NULL)
input_buffer = malloc(input_bufferLength);
if (input_buffer == NULL)
{
error = ERROR_OUTOFMEMORY;
goto Exit;
@ -128,20 +128,20 @@ Disassembly of section :
if (action == 0) //load
{
loadRequest = inputBuffer;
loadRequest->header.id = load_code;
loadRequest->header.length = inputBufferLength;
RtlCopyMemory(&loadRequest->machine_code, code, sizeof(code));
load_request = input_buffer;
load_request->header.id = EBPF_OPERATION_LOAD_CODE;
load_request->header.length = input_bufferLength;
RtlCopyMemory(&load_request->machine_code, code, sizeof(code));
error = DeviceIoControl(
deviceHandle,
device_handle,
(DWORD)IOCTL_EBPFCTL_METHOD_BUFFERED,
inputBuffer,
(DWORD)inputBufferLength,
&outputBuffer,
outputBufferLength,
&bytesReturned,
input_buffer,
(DWORD)input_bufferLength,
&output_buffer,
output_buffer_length,
&bytes_returned,
NULL);
if (!error)
{
@ -150,27 +150,27 @@ Disassembly of section :
goto Exit;
}
handle = outputBuffer.handle;
handle = output_buffer.handle;
printf("Load succeeded. Program handle %lld\n", handle);
}
else if (action == 1) // attach
else if (action == 1) // EBPF_OPERATION_ATTACH_CODE
{
// attach.
header = (struct EbpfOpHeader*)inputBuffer;
header->id = attach;
struct EbpfOpAttachDetachRequest* attachRequest = inputBuffer;
attachRequest->handle = inputHandle;
// EBPF_OPERATION_ATTACH_CODE.
header = (struct _ebpf_operation_header*)input_buffer;
header->id = EBPF_OPERATION_ATTACH_CODE;
struct _ebpf_operation_attach_detach_request* attachRequest = input_buffer;
attachRequest->handle = input_handle;
attachRequest->hook = 1;
error = DeviceIoControl(
deviceHandle,
device_handle,
(DWORD)IOCTL_EBPFCTL_METHOD_BUFFERED,
inputBuffer,
(DWORD)inputBufferLength,
&outputBuffer,
outputBufferLength,
&bytesReturned,
input_buffer,
(DWORD)input_bufferLength,
&output_buffer,
output_buffer_length,
&bytes_returned,
NULL);
if (!error)
{
@ -183,19 +183,19 @@ Disassembly of section :
}
else if (action == 2) // unload
{
header = (struct EbpfOpHeader*)inputBuffer;
struct EbpfOpUnloadRequest* unloadRequest = inputBuffer;
header->id = unload_code;
unloadRequest->handle = inputHandle;
header = (struct _ebpf_operation_header*)input_buffer;
struct _ebpf_operation_unload_code_request* unloadRequest = input_buffer;
header->id = EBPF_OPERATION_UNLOAD_CODE;
unloadRequest->handle = input_handle;
error = DeviceIoControl(
deviceHandle,
device_handle,
(DWORD)IOCTL_EBPFCTL_METHOD_BUFFERED,
inputBuffer,
(DWORD)inputBufferLength,
&outputBuffer,
outputBufferLength,
&bytesReturned,
input_buffer,
(DWORD)input_bufferLength,
&output_buffer,
output_buffer_length,
&bytes_returned,
NULL);
if (!error)
{
@ -207,14 +207,11 @@ Disassembly of section :
printf("Unload succeeded\n");
}
Exit:
if (inputBuffer != NULL)
{
free(inputBuffer);
}
free(input_buffer);
if (deviceHandle != INVALID_HANDLE_VALUE)
if (device_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(deviceHandle);
CloseHandle(device_handle);
}
return error;

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">

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

@ -13,15 +13,15 @@
#pragma clang section data="maps"
struct bpf_map_def port_map = {
.size = sizeof(struct bpf_map_def),
.type = 2,
.key_size = sizeof(__u32),
.value_size = sizeof(__u32),
.max_entries = 1,
.map_flags = 0
.max_entries = 1
};
#pragma clang section text="xdp"
int DropPacket(xdp_md* ctx)
int DropPacket(xdp_md_t* ctx)
{
IPV4_HEADER* iphdr = (IPV4_HEADER*)ctx->data;
UDP_HEADER* udphdr = (UDP_HEADER*)(iphdr + 1);

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

@ -13,12 +13,12 @@ __u16 ntohs(__u16 us)
return us << 8 | us >> 8;
}
typedef struct xdp_md_
typedef struct _xdp_md
{
void* data;
void* data_end;
__u64 data_meta;
} xdp_md;
} xdp_md_t;
typedef struct _IPV4_HEADER {
union {
@ -62,13 +62,11 @@ typedef struct UDP_HEADER_ {
} UDP_HEADER;
struct bpf_map_def {
__u32 size;
__u32 type;
__u32 key_size;
__u32 value_size;
__u32 max_entries;
__u32 map_flags;
__u32 inner_map_idx;
__u32 numa_node;
};
typedef void* (*ebpf_map_lookup_elem_t)(void * map, void* key);
#define ebpf_map_lookup_elem ((ebpf_map_lookup_elem_t)1)

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">

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

@ -1,22 +0,0 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <functional>
class UnwindHelper
{
public:
UnwindHelper(std::function<void()> unwind) : unwind(unwind)
{
}
~UnwindHelper()
{
unwind();
}
private:
std::function<void()> unwind;
};

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

@ -5,6 +5,7 @@
#include "ebpf_verifier.hpp"
#include "windows/windows_platform.hpp"
#include "platform.hpp"
#include "Verifier.h"
#include <sstream>
#include <iostream>
@ -51,7 +52,8 @@ static int analyze(raw_program& raw_prog, char ** error_message)
}
auto& prog = std::get<InstructionSeq>(prog_or_error);
cfg_t cfg = prepare_cfg(prog, raw_prog.info, true);
ebpf_verifier_options_t options{ true, false, true };
ebpf_verifier_options_t options = ebpf_verifier_default_options;
options.print_failures = true;
bool res = run_ebpf_analysis(oss, cfg, raw_prog.info, &options);
if (!res) {
*error_message = allocate_error_string(oss.str());
@ -64,7 +66,7 @@ int verify(const char* filename, const char* sectionname, uint8_t* byte_code, si
{
const ebpf_platform_t* platform = &g_ebpf_platform_windows;
auto raw_progs = read_elf(filename, sectionname, reinterpret_cast<MapFd*>(map_create_function), nullptr, platform);
auto raw_progs = read_elf(filename, sectionname, map_create_function, nullptr, platform);
if (raw_progs.size() != 1) {
return 1; // Error
}

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

@ -1,12 +1,7 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef int (*map_create_fp)(uint32_t map_type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, uint32_t options);
int get_file_size(char* filename, size_t* byte_code_size);
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, map_create_fp map_creat_function, char** error_message);
int verify_byte_code(const char* path, const char* section_name, const uint8_t* byte_code, size_t byte_code_size, char** error_message);
#ifdef __cplusplus
}
#endif
#include "config.hpp"
typedef int (*map_create_fp)(uint32_t map_type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, ebpf_verifier_options_t options);
int get_file_size(char* filename, size_t* byte_code_size);
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, map_create_fp map_creat_function, char** error_message);
int verify_byte_code(const char* path, const char* section_name, const uint8_t* byte_code, size_t byte_code_size, char** error_message);

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

@ -13,10 +13,10 @@ extern "C"
}
#include "protocol.h"
#include "UnwindHelper.h"
#include "unwind_helper.h"
#include "Verifier.h"
#include <stdexcept>
#include "Verifier.h"
#define MAX_CODE_SIZE (32 * 1024) // 32 KB
@ -91,7 +91,7 @@ static DWORD invoke_ioctl(HANDLE handle, request_t request, reply_t reply)
return ERROR_SUCCESS;
}
DWORD EbpfApiInit()
DLL DWORD ebpf_api_initiate()
{
LPCWSTR ebpfDeviceName = L"\\\\.\\EbpfIoDevice";
@ -116,7 +116,7 @@ DWORD EbpfApiInit()
return 0;
}
void EbpfApiTerminate()
DLL void ebpf_api_terminate()
{
if (device_handle != INVALID_HANDLE_VALUE)
{
@ -125,23 +125,25 @@ void EbpfApiTerminate()
}
}
static int create_map_function(uint32_t type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, uint32_t map_flags)
static int create_map_function(uint32_t type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, ebpf_verifier_options_t options)
{
EbpfOpCreateMapRequest request{
sizeof(EbpfOpCreateMapRequest),
EbpfOperation::create_map,
type,
key_size,
value_size,
max_entries,
0,
_ebpf_operation_create_map_request request{
sizeof(_ebpf_operation_create_map_request),
ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP,
{
sizeof(struct _ebpf_map_definition),
type,
key_size,
value_size,
max_entries
}
};
EbpfOpCreateMapReply reply{};
_ebpf_operation_create_map_reply reply{};
auto retval = invoke_ioctl(device_handle, &request, &reply);
if (reply.header.id != EbpfOperation::create_map)
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP)
{
return -1;
}
@ -158,16 +160,16 @@ static int create_map_function(uint32_t type, uint32_t key_size, uint32_t value_
static uint64_t map_resolver(void* context, uint64_t fd)
{
EbpfOpResolveMapRequest request{
_ebpf_operation_resolve_map_request request{
sizeof(request),
EbpfOperation::resolve_map,
ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP,
fd };
EbpfOpResolveMapReply reply;
_ebpf_operation_resolve_map_reply reply;
invoke_ioctl(context, &request, &reply);
if (reply.header.id != EbpfOperation::resolve_map)
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP)
{
return 0;
}
@ -175,18 +177,18 @@ EbpfOpResolveMapRequest request{
return reply.address[0];
}
uint64_t helper_resolver(void* context, uint32_t helper)
static uint64_t helper_resolver(void* context, uint32_t helper)
{
EbpfOpResolveHelperRequest request{
_ebpf_operation_resolve_helper_request request{
sizeof(request),
EbpfOperation::resolve_helper,
ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER,
helper };
EbpfOpResolveMapReply reply;
_ebpf_operation_resolve_map_reply reply;
invoke_ioctl(context, &request, &reply);
if (reply.header.id != EbpfOperation::resolve_helper)
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER)
{
return 0;
}
@ -194,16 +196,16 @@ uint64_t helper_resolver(void* context, uint32_t helper)
return reply.address[0];
}
DLL DWORD EbpfApiLoadProgram(const char* file_name, const char* section_name, HANDLE* handle, char** error_message)
DLL DWORD ebpf_api_load_program(const char* file_name, const char* section_name, HANDLE* handle, char** error_message)
{
std::vector<uint8_t> byte_code(MAX_CODE_SIZE);
size_t byte_code_size = byte_code.size();
std::vector<uint8_t> machine_code(MAX_CODE_SIZE);
size_t machine_code_size = machine_code.size();
std::vector<uint8_t> request_buffer;
EbpfOpLoadReply reply;
_ebpf_operation_load_code_reply reply;
struct ubpf_vm* vm = nullptr;
UnwindHelper unwind([&]
_unwind_helper unwind([&]
{
if (vm)
{
@ -262,11 +264,11 @@ DLL DWORD EbpfApiLoadProgram(const char* file_name, const char* section_name, HA
}
machine_code.resize(machine_code_size);
request_buffer.resize(machine_code.size() + sizeof(EbpfOpHeader));
auto header = reinterpret_cast<EbpfOpHeader*>(request_buffer.data());
header->id = EbpfOperation::load_code;
request_buffer.resize(machine_code.size() + sizeof(_ebpf_operation_header));
auto header = reinterpret_cast<_ebpf_operation_header*>(request_buffer.data());
header->id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE;
header->length = static_cast<uint16_t>(request_buffer.size());
std::copy(machine_code.begin(), machine_code.end(), request_buffer.begin() + sizeof(EbpfOpHeader));
std::copy(machine_code.begin(), machine_code.end(), request_buffer.begin() + sizeof(_ebpf_operation_header));
result = invoke_ioctl(device_handle, request_buffer, &reply);
@ -275,7 +277,7 @@ DLL DWORD EbpfApiLoadProgram(const char* file_name, const char* section_name, HA
return result;
}
if (reply.header.id != EbpfOperation::load_code)
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE)
{
return ERROR_INVALID_PARAMETER;
}
@ -285,53 +287,53 @@ DLL DWORD EbpfApiLoadProgram(const char* file_name, const char* section_name, HA
return result;
}
DLL void EbpfApiFreeErrorMessage(char* error_message)
DLL void ebpf_api_free_error_message(char* error_message)
{
return free(error_message);
}
DLL void EbpfApiUnloadProgram(HANDLE handle)
DLL void ebpf_api_unload_program(HANDLE handle)
{
CloseHandle(handle);
return;
}
DLL DWORD EbpfApiAttachProgram(HANDLE handle, DWORD hook_point)
DLL DWORD ebpf_api_attach_program(HANDLE handle, DWORD hook_point)
{
EbpfOpAttachDetachRequest request{
_ebpf_operation_attach_detach_request request{
sizeof(request),
EbpfOperation::attach,
ebpf_operation_id_t::EBPF_OPERATION_ATTACH_CODE,
reinterpret_cast<uint64_t>(handle),
hook_point };
return invoke_ioctl(device_handle, &request, nullptr);
}
DLL DWORD EbpfApiDetachProgram(HANDLE handle, DWORD hook_point)
DLL DWORD ebpf_api_detach_program(HANDLE handle, DWORD hook_point)
{
EbpfOpAttachDetachRequest request{
_ebpf_operation_attach_detach_request request{
sizeof(request),
EbpfOperation::detach,
ebpf_operation_id_t::EBPF_OPERATION_DETACH_CODE,
reinterpret_cast<uint64_t>(handle),
hook_point };
return invoke_ioctl(device_handle, &request, nullptr);
}
DLL DWORD EbpfApiMapLookupElement(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value)
DLL DWORD ebpf_api_map_lookup_element(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value)
{
std::vector<uint8_t> request_buffer(sizeof(EbpfOpMapLookupElementRequest) + key_size - 1);
std::vector<uint8_t> reply_buffer(sizeof(EbpfOpMapLookupElementReply) + value_size - 1);
auto request = reinterpret_cast<EbpfOpMapLookupElementRequest*>(request_buffer.data());
auto reply = reinterpret_cast<EbpfOpMapLookupElementReply*>(reply_buffer.data());
std::vector<uint8_t> request_buffer(sizeof(_ebpf_operation_map_lookup_element_request) + key_size - 1);
std::vector<uint8_t> reply_buffer(sizeof(_ebpf_operation_map_lookup_element_reply) + value_size - 1);
auto request = reinterpret_cast<_ebpf_operation_map_lookup_element_request*>(request_buffer.data());
auto reply = reinterpret_cast<_ebpf_operation_map_lookup_element_reply*>(reply_buffer.data());
request->header.length = request_buffer.size();
request->header.id = EbpfOperation::map_lookup_element;
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT;
std::copy(key, key + key_size, request->key);
auto retval = invoke_ioctl(device_handle, request_buffer, reply_buffer);
if (reply->header.id != EbpfOperation::map_lookup_element)
if (reply->header.id != ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT)
{
return ERROR_INVALID_PARAMETER;
}
@ -344,32 +346,32 @@ DLL DWORD EbpfApiMapLookupElement(HANDLE handle, DWORD key_size, unsigned char*
}
DLL DWORD EbpfApiMapUpdateElement(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value)
DLL DWORD ebpf_api_map_update_element(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value)
{
std::vector<uint8_t> request_buffer(sizeof(EpfOpMapUpdateElementRequest) - 1 + key_size + value_size);
auto request = reinterpret_cast<EpfOpMapUpdateElementRequest*>(request_buffer.data());
std::vector<uint8_t> request_buffer(sizeof(_ebpf_operation_map_update_element_request) - 1 + key_size + value_size);
auto request = reinterpret_cast<_ebpf_operation_map_update_element_request*>(request_buffer.data());
request->header.length = request_buffer.size();
request->header.id = EbpfOperation::map_lookup_element;
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT;
std::copy(key, key + key_size, request->data);
std::copy(value, value + value_size, request->data + key_size);
return invoke_ioctl(device_handle, request_buffer, nullptr);
}
DLL DWORD EbpfApiMapDeleteElement(HANDLE handle, DWORD key_size, unsigned char* key)
DLL DWORD ebpf_api_map_delete_element(HANDLE handle, DWORD key_size, unsigned char* key)
{
std::vector<uint8_t> request_buffer(sizeof(EbpfOpMapDeleteElementRequest) - 1 + key_size);
auto request = reinterpret_cast<EbpfOpMapDeleteElementRequest*>(request_buffer.data());
std::vector<uint8_t> request_buffer(sizeof(_ebpf_operation_map_delete_element_request) - 1 + key_size);
auto request = reinterpret_cast<_ebpf_operation_map_delete_element_request*>(request_buffer.data());
request->header.length = request_buffer.size();
request->header.id = EbpfOperation::map_delete_element;
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_DELETE_ELEMENT;
std::copy(key, key + key_size, request->key);
return invoke_ioctl(device_handle, request_buffer, nullptr);
}
DLL void EbpfApiDeleteMap(HANDLE handle)
DLL void ebpf_api_delete_map(HANDLE handle)
{
CloseHandle(handle);
}

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

@ -17,21 +17,21 @@ extern "C" {
#define EBPF_HOOK_POINT_XDP 1
DLL DWORD EbpfApiInit();
DLL DWORD ebpf_api_initiate();
DLL void EbpfApiTerminate();
DLL void ebpf_api_terminate();
DLL DWORD EbpfApiLoadProgram(const char* file, const char* section_name, HANDLE* handle, char** error_message);
DLL void EbpfApiFreeErrorMessage(char* error_message);
DLL void EbpfApiUnloadProgram(HANDLE handle);
DLL DWORD ebpf_api_load_program(const char* file, const char* section_name, HANDLE* handle, char** error_message);
DLL void ebpf_api_free_error_message(char* error_message);
DLL void ebpf_api_unload_program(HANDLE handle);
DLL DWORD EbpfApiAttachProgram(HANDLE handle, DWORD hook_point);
DLL DWORD EbpfApiDetachProgram(HANDLE handle, DWORD hook_point);
DLL DWORD ebpf_api_attach_program(HANDLE handle, DWORD hook_point);
DLL DWORD ebpf_api_detach_program(HANDLE handle, DWORD hook_point);
DLL DWORD EbpfApiMapLookupElement(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value);
DLL DWORD EbpfApiMapUpdateElement(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value);
DLL DWORD EbpfApiMapDeleteElement(HANDLE handle, DWORD key_size, unsigned char* key);
DLL void EbpfApiDeleteMap(HANDLE handle);
DLL DWORD ebpf_api_map_lookup_element(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value);
DLL DWORD ebpf_api_map_update_element(HANDLE handle, DWORD key_size, unsigned char* key, DWORD value_size, unsigned char* value);
DLL DWORD ebpf_api_map_delete_element(HANDLE handle, DWORD key_size, unsigned char* key);
DLL void ebpf_api_delete_map(HANDLE handle);
#ifdef __cplusplus
}

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -166,7 +166,7 @@
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="protocol.h" />
<ClInclude Include="UnwindHelper.h" />
<ClInclude Include="unwind_helper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="api.cpp" />

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.72.0.0" targetFramework="native" />
<package identifier="boost" version="1.72.0.0" targetFramework="native" />
</packages>

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

@ -4,109 +4,113 @@
*/
#pragma once
typedef enum EbpfOperation_ {
evidence,
resolve_helper,
resolve_map,
load_code,
unload_code,
attach,
detach,
create_map,
map_lookup_element,
map_update_element,
map_delete_element
} EbpfOperation;
typedef enum _ebpf_operation_id {
EBPF_OPERATION_EVIDENCE,
EBPF_OPERATION_RESOLVE_HELPER,
EBPF_OPERATION_RESOLVE_MAP,
EBPF_OPERATION_LOAD_CODE,
EBPF_OPERATION_UNLOAD_CODE,
EBPF_OPERATION_ATTACH_CODE,
EBPF_OPERATION_DETACH_CODE,
EBPF_OPERATION_CREATE_MAP,
EBPF_OPERATION_MAP_LOOKUP_ELEMENT,
EBPF_OPERATION_MAP_UPDATE_ELEMENT,
EBPF_OPERATION_MAP_DELETE_ELEMENT
} ebpf_operation_id_t;
struct EbpfOpHeader {
uint16_t length;
EbpfOperation id;
};
struct EbpfOpEvidenceRequest {
struct EbpfOpHeader header;
uint8_t evidence[1];
};
struct EbpfOpEvidenceReply {
struct EbpfOpHeader header;
uint32_t status;
};
struct EbpfOpResolveHelperRequest {
struct EbpfOpHeader header;
uint32_t helper_id[1];
};
struct EbpfOpResolveHelperReply {
struct EbpfOpHeader header;
uint64_t address[1];
};
struct EbpfOpResolveMapRequest {
struct EbpfOpHeader header;
uint64_t map_id[1];
};
struct EbpfOpResolveMapReply {
struct EbpfOpHeader header;
uint64_t address[1];
};
struct EbpfOpLoadRequest {
struct EbpfOpHeader header;
uint8_t machine_code[1];
};
struct EbpfOpUnloadRequest {
struct EbpfOpHeader header;
uint64_t handle;
};
struct EbpfOpLoadReply {
struct EbpfOpHeader header;
uint64_t handle;
};
struct EbpfOpAttachDetachRequest {
struct EbpfOpHeader header;
uint64_t handle;
uint32_t hook;
};
struct EbpfOpCreateMapRequest {
struct EbpfOpHeader header;
typedef struct _ebpf_map_definition {
uint32_t size;
uint32_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
uint32_t map_flags;
};
} ebpf_map_definition_t;
struct EbpfOpCreateMapReply {
struct EbpfOpHeader header;
typedef struct _ebpf_operation_header {
uint16_t length;
ebpf_operation_id_t id;
} ebpf_operation_header_t;
typedef struct _ebpf_operation_eidence_request {
struct _ebpf_operation_header header;
uint8_t EBPF_OPERATION_EVIDENCE[1];
} ebpf_operation_eidence_request_t;
typedef struct _ebpf_operation_evidence_reply {
struct _ebpf_operation_header header;
uint32_t status;
} ebpf_operation_evidence_reply_t;
typedef struct _ebpf_operation_resolve_helper_request {
struct _ebpf_operation_header header;
uint32_t helper_id[1];
} ebpf_operation_resolve_helper_request_t;
typedef struct _ebpf_operation_resolve_helper_reply {
struct _ebpf_operation_header header;
uint64_t address[1];
} ebpf_operation_resolve_helper_reply_t;
typedef struct _ebpf_operation_resolve_map_request {
struct _ebpf_operation_header header;
uint64_t map_handle[1];
} ebpf_operation_resolve_map_request_t;
typedef struct _ebpf_operation_resolve_map_reply {
struct _ebpf_operation_header header;
uint64_t address[1];
} ebpf_operation_resolve_map_reply_t;
typedef struct _ebpf_operation_load_code_request {
struct _ebpf_operation_header header;
uint8_t machine_code[1];
} ebpf_operation_load_code_request_t;
typedef struct _ebpf_operation_unload_code_request {
struct _ebpf_operation_header header;
uint64_t handle;
};
} ebpf_operation_unload_code_request_t;
struct EbpfOpMapLookupElementRequest {
struct EbpfOpHeader header;
typedef struct _ebpf_operation_load_code_reply {
struct _ebpf_operation_header header;
uint64_t handle;
} ebpf_operation_load_code_reply_t;
typedef struct _ebpf_operation_attach_detach_request {
struct _ebpf_operation_header header;
uint64_t handle;
uint32_t hook;
} ebpf_operation_attach_detach_request_t;
typedef struct _ebpf_operation_create_map_request {
struct _ebpf_operation_header header;
struct _ebpf_map_definition ebpf_map_definition;
} ebpf_operation_create_map_request_t;
typedef struct _ebpf_operation_create_map_reply {
struct _ebpf_operation_header header;
uint64_t handle;
} ebpf_operation_create_map_reply_t;
typedef struct _ebpf_operation_map_lookup_element_request {
struct _ebpf_operation_header header;
uint64_t handle;
uint8_t key[1];
};
} ebpf_operation_map_lookup_element_request;
struct EbpfOpMapLookupElementReply {
struct EbpfOpHeader header;
typedef struct _ebpf_operation_map_lookup_element_reply {
struct _ebpf_operation_header header;
uint8_t value[1];
};
} ebpf_operation_map_lookup_element_reply_t;
struct EpfOpMapUpdateElementRequest {
struct EbpfOpHeader header;
typedef struct _ebpf_operation_map_update_element_request {
struct _ebpf_operation_header header;
uint64_t handle;
uint8_t data[1]; // data is key+value
};
} epf_operation_map_update_element_request_;
struct EbpfOpMapDeleteElementRequest {
struct EbpfOpHeader header;
typedef struct _ebpf_operation_map_delete_element_request {
struct _ebpf_operation_header header;
uint64_t handle;
uint8_t key[1];
};
} ebpf_operation_map_delete_element_request_t;

Двоичные данные
src/ebpf/libs/api/test/droppacket.o

Двоичный файл не отображается.

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CatchOrg.Catch" version="2.2.0" targetFramework="native" />
<package identifier="CatchOrg.Catch" version="2.2.0" targetFramework="native" />
</packages>

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

@ -85,7 +85,7 @@ auto success_ioctl = [&](_In_ HANDLE hDevice,
return TRUE;
};
void push_back_reply_message(EbpfOpHeader* header)
void push_back_reply_message(_ebpf_operation_header* header)
{
std::vector<uint8_t> reply(header->length);
@ -98,51 +98,51 @@ request_message_t* front_request_message()
{
auto message = reinterpret_cast<request_message_t*>(request_messages.front().data());
size_t expected_size = 0;
EbpfOperation expected_id = (EbpfOperation)-1;
if constexpr (std::is_same<request_message_t, EbpfOpEvidenceRequest>::value) {
expected_size = sizeof(EbpfOpEvidenceRequest);
expected_id = EbpfOperation::evidence;
ebpf_operation_id_t expected_id = (ebpf_operation_id_t)-1;
if constexpr (std::is_same<request_message_t, _ebpf_operation_eidence_request>::value) {
expected_size = sizeof(_ebpf_operation_eidence_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_EVIDENCE;
}
else if constexpr (std::is_same<request_message_t, EbpfOpResolveHelperRequest>::value) {
expected_size = sizeof(EbpfOpResolveHelperRequest);
expected_id = EbpfOperation::resolve_helper;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_resolve_helper_request>::value) {
expected_size = sizeof(_ebpf_operation_resolve_helper_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER;
}
else if constexpr (std::is_same<request_message_t, EbpfOpResolveMapRequest>::value) {
expected_size = sizeof(EbpfOpResolveMapRequest);
expected_id = EbpfOperation::resolve_map;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_resolve_map_request>::value) {
expected_size = sizeof(_ebpf_operation_resolve_helper_reply);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP;
}
else if constexpr (std::is_same<request_message_t, EbpfOpLoadRequest>::value) {
expected_id = EbpfOperation::load_code;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_load_code_request>::value) {
expected_id = ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE;
}
else if constexpr (std::is_same<request_message_t, EbpfOpAttachDetachRequest>::value) {
expected_size = sizeof(EbpfOpAttachDetachRequest);
else if constexpr (std::is_same<request_message_t, _ebpf_operation_attach_detach_request>::value) {
expected_size = sizeof(_ebpf_operation_attach_detach_request);
switch (message->header.id) {
case EbpfOperation::attach:
case EbpfOperation::detach:
case ebpf_operation_id_t::EBPF_OPERATION_ATTACH_CODE:
case ebpf_operation_id_t::EBPF_OPERATION_DETACH_CODE:
break;
default:
REQUIRE(message->header.id == EbpfOperation::attach);
REQUIRE(message->header.id == ebpf_operation_id_t::EBPF_OPERATION_ATTACH_CODE);
break;
}
}
else if constexpr (std::is_same<request_message_t, EbpfOpCreateMapRequest>::value) {
expected_size = sizeof(EbpfOpCreateMapRequest);
expected_id = EbpfOperation::create_map;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_create_map_request>::value) {
expected_size = sizeof(_ebpf_operation_create_map_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP;
}
else if constexpr (std::is_same<request_message_t, EbpfOpMapLookupElementRequest>::value) {
expected_size = sizeof(EbpfOpMapLookupElementRequest);
expected_id = EbpfOperation::map_lookup_element;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_map_lookup_element_request>::value) {
expected_size = sizeof(_ebpf_operation_map_lookup_element_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_MAP_LOOKUP_ELEMENT;
}
else if constexpr (std::is_same<request_message_t, EpfOpMapUpdateElementRequest>::value) {
expected_size = sizeof(EpfOpMapUpdateElementRequest);
expected_id = EbpfOperation::map_update_element;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_map_update_element_request>::value) {
expected_size = sizeof(_ebpf_operation_map_update_element_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_MAP_UPDATE_ELEMENT;
}
else if constexpr (std::is_same<request_message_t, EbpfOpMapDeleteElementRequest>::value) {
expected_size = sizeof(EpfOpMapUpdateElementRequest);
expected_id = EbpfOperation::map_update_element;
else if constexpr (std::is_same<request_message_t, _ebpf_operation_map_delete_element_request>::value) {
expected_size = sizeof(_ebpf_operation_map_update_element_request);
expected_id = ebpf_operation_id_t::EBPF_OPERATION_MAP_UPDATE_ELEMENT;
}
if (expected_id != (EbpfOperation)-1)
if (expected_id != (ebpf_operation_id_t)-1)
REQUIRE(expected_id == message->header.id);
if (expected_size > 0)
@ -166,16 +166,16 @@ TEST_CASE("Open failed", "[open_fail]") {
throw std::exception("Test failed - closing handle not opened");
};
REQUIRE(EbpfApiInit() == ERROR_FILE_NOT_FOUND);
EbpfApiTerminate();
REQUIRE(ebpf_api_initiate() == ERROR_FILE_NOT_FOUND);
ebpf_api_terminate();
}
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();
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
ebpf_api_terminate();
}
TEST_CASE("Load program fail - file not found", "[load_fail_not_found]") {
@ -186,12 +186,12 @@ TEST_CASE("Load program fail - file not found", "[load_fail_not_found]") {
char* error_message = nullptr;
const char* fake_file_name = "not_a_real_file.elf";
REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
REQUIRE(EbpfApiLoadProgram(fake_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
REQUIRE(ebpf_api_load_program(fake_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
REQUIRE_THAT(error_message, Catch::Matchers::Contains(fake_file_name));
EbpfApiFreeErrorMessage(error_message);
EbpfApiTerminate();
ebpf_api_free_error_message(error_message);
ebpf_api_terminate();
}
TEST_CASE("Load program fail - malformed", "[load_fail_bad_file]") {
@ -215,12 +215,12 @@ TEST_CASE("Load program fail - malformed", "[load_fail_bad_file]") {
out_file.flush();
out_file.close();
REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
REQUIRE(EbpfApiLoadProgram(temp_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
REQUIRE(ebpf_api_load_program(temp_file_name, "xdp_fake", &handle, &error_message) == ERROR_INVALID_PARAMETER);
REQUIRE_THAT(error_message, Catch::Matchers::Contains(temp_file_name));
EbpfApiFreeErrorMessage(error_message);
EbpfApiTerminate();
ebpf_api_free_error_message(error_message);
ebpf_api_terminate();
DeleteFileA(temp_file_name);
}
@ -233,50 +233,21 @@ TEST_CASE("Load program success", "[load_success]") {
HANDLE handle;
char* error_message = nullptr;
EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast<uint64_t>(&h) };
_ebpf_operation_load_code_reply load_reply{ sizeof(_ebpf_operation_load_code_reply), ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE, reinterpret_cast<uint64_t>(&h) };
push_back_reply_message(&load_reply.header);
REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
REQUIRE(EbpfApiLoadProgram("bpf.o", "xdp_prog", &handle, &error_message) == ERROR_SUCCESS);
REQUIRE(ebpf_api_load_program("bpf.o", "xdp_prog", &handle, &error_message) == ERROR_SUCCESS);
auto load_request = front_request_message<EbpfOpLoadRequest>();
auto load_request = front_request_message<_ebpf_operation_load_code_request>();
request_messages.clear();
EbpfApiFreeErrorMessage(error_message);
EbpfApiTerminate();
ebpf_api_free_error_message(error_message);
ebpf_api_terminate();
}
//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<uint64_t>(&GetTickCount) };
// push_back_reply_message(&helper_reply.header);
//
// EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast<uint64_t>(&h) };
// push_back_reply_message(&load_reply.header);
//
// REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
//
// REQUIRE(EbpfApiLoadProgram("bpf_call.o", "xdp_prog", &handle, &error_message) == 0);
//
// auto resolve_request = front_request_message<EbpfOpResolveHelperRequest>();
// REQUIRE(resolve_request->helper_id[0] == 3);
// request_messages.pop_front();
//
// auto load_request = front_request_message<EbpfOpLoadRequest>();
// request_messages.pop_front();
//
// EbpfApiFreeErrorMessage(error_message);
// EbpfApiTerminate();
//}
unsigned long test_map[1] = { 0 };
void* map_lookup_elem(void* map, void* key)
@ -284,7 +255,7 @@ void* map_lookup_elem(void* map, void* key)
return test_map;
}
TEST_CASE("Load program success - create_map", "[load_success - create map]") {
TEST_CASE("Load program success - EBPF_OPERATION_CREATE_MAP", "[load_success - create map]") {
create_file_handler = success_create_file_handler;
close_handle_handler = success_close_handle_handler;
device_io_control_handler = success_ioctl;
@ -292,46 +263,46 @@ TEST_CASE("Load program success - create_map", "[load_success - create map]") {
HANDLE handle;
char* error_message = nullptr;
EbpfOpCreateMapReply map_create_reply{ sizeof(EbpfOpCreateMapReply), EbpfOperation::create_map, 15 };
_ebpf_operation_create_map_reply map_create_reply{ sizeof(_ebpf_operation_create_map_reply), ebpf_operation_id_t::EBPF_OPERATION_CREATE_MAP, (15) };
push_back_reply_message(&map_create_reply.header);
EbpfOpResolveMapReply map_resolve_reply{ sizeof(EbpfOpResolveMapReply), EbpfOperation::resolve_map, reinterpret_cast<uint64_t>(test_map) };
_ebpf_operation_resolve_map_reply map_resolve_reply{ sizeof(_ebpf_operation_resolve_map_reply), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP, reinterpret_cast<uint64_t>(test_map) };
push_back_reply_message(&map_resolve_reply.header);
EbpfOpResolveHelperReply helper_reply{ sizeof(EbpfOpResolveHelperReply), EbpfOperation::resolve_helper, reinterpret_cast<uint64_t>(map_lookup_elem) };
_ebpf_operation_resolve_helper_reply helper_reply{ sizeof(_ebpf_operation_resolve_helper_reply), ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_HELPER, reinterpret_cast<uint64_t>(map_lookup_elem) };
push_back_reply_message(&helper_reply.header);
EbpfOpLoadReply load_reply{ sizeof(EbpfOpLoadReply), EbpfOperation::load_code, reinterpret_cast<uint64_t>(&h) };
_ebpf_operation_load_code_reply load_reply{ sizeof(_ebpf_operation_load_code_reply), ebpf_operation_id_t::EBPF_OPERATION_LOAD_CODE, reinterpret_cast<uint64_t>(&h) };
push_back_reply_message(&load_reply.header);
REQUIRE(EbpfApiInit() == ERROR_SUCCESS);
REQUIRE(ebpf_api_initiate() == ERROR_SUCCESS);
auto result = EbpfApiLoadProgram("droppacket.o", "xdp", &handle, &error_message);
auto result = ebpf_api_load_program("droppacket.o", "xdp", &handle, &error_message);
if (result)
{
printf("error_message=%s\n", error_message);
}
REQUIRE(result == 0);
auto map_create_request = front_request_message<EbpfOpCreateMapRequest>();
REQUIRE(map_create_request->type == 2);
REQUIRE(map_create_request->key_size == 4);
REQUIRE(map_create_request->value_size == 4);
REQUIRE(map_create_request->max_entries == 1);
REQUIRE(map_create_request->map_flags == 0);
auto map_create_request = front_request_message<_ebpf_operation_create_map_request>();
REQUIRE(map_create_request->ebpf_map_definition.size == sizeof(struct _ebpf_map_definition));
REQUIRE(map_create_request->ebpf_map_definition.type == 2);
REQUIRE(map_create_request->ebpf_map_definition.key_size == 4);
REQUIRE(map_create_request->ebpf_map_definition.value_size == 4);
REQUIRE(map_create_request->ebpf_map_definition.max_entries == 1);
request_messages.pop_front();
auto resolve_map_request = front_request_message<EbpfOpResolveMapRequest>();
REQUIRE(resolve_map_request->map_id[0] == 15);
auto resolve_map_request = front_request_message<_ebpf_operation_resolve_map_request>();
REQUIRE(resolve_map_request->map_handle[0] == 15);
request_messages.pop_front();
auto resolve_request = front_request_message<EbpfOpResolveHelperRequest>();
auto resolve_request = front_request_message<_ebpf_operation_resolve_helper_request>();
REQUIRE(resolve_request->helper_id[0] == 1);
request_messages.pop_front();
auto load_request = front_request_message<EbpfOpLoadRequest>();
auto load_request = front_request_message<_ebpf_operation_load_code_request>();
auto code_size = load_request->header.length - sizeof(EbpfOpHeader);
auto code_size = load_request->header.length - sizeof(_ebpf_operation_header);
auto code_page = VirtualAlloc(NULL, code_size, MEM_COMMIT, PAGE_READWRITE);
REQUIRE(code_page != nullptr);
DWORD oldProtect = 0;
@ -339,20 +310,20 @@ TEST_CASE("Load program success - create_map", "[load_success - create map]") {
VirtualProtect(code_page, code_size, PAGE_EXECUTE_READ, &oldProtect);
request_messages.pop_front();
EbpfApiFreeErrorMessage(error_message);
EbpfApiTerminate();
ebpf_api_free_error_message(error_message);
ebpf_api_terminate();
typedef unsigned long __u64;
typedef unsigned int __u32;
typedef unsigned short __u16;
typedef unsigned char __u8;
typedef struct xdp_md_
typedef struct _xdp_md
{
void* data;
void* data_end;
__u64 data_meta;
} xdp_md;
} xdp_md_t;
typedef struct _IPV4_HEADER {
union {
@ -404,10 +375,10 @@ TEST_CASE("Load program success - create_map", "[load_success - create map]") {
udp->length = 0;
uint64_t (*xdp_hook)(xdp_md* ctx) = reinterpret_cast<decltype(xdp_hook)>(code_page);
uint64_t (*xdp_hook)(xdp_md_t* ctx) = reinterpret_cast<decltype(xdp_hook)>(code_page);
// Test that we drop the packet and increment the map
xdp_md ctx{packet.data(), packet.data() + packet.size()};
xdp_md_t ctx{packet.data(), packet.data() + packet.size()};
REQUIRE(xdp_hook(&ctx) == 2);
REQUIRE(test_map[0] == 1);

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\..\packages\CatchOrg.Catch.2.2.0\build\native\CatchOrg.Catch.props" Condition="Exists('..\..\..\..\..\packages\CatchOrg.Catch.2.2.0\build\native\CatchOrg.Catch.props')" />
<ItemGroup Label="ProjectConfigurations">

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

@ -41,8 +41,6 @@
<ItemGroup>
<CopyFileToFolders Include="bpf_call.o" />
<CopyFileToFolders Include="bpf.o" />
</ItemGroup>
<ItemGroup>
<Object Include="droppacket.o" />
<CopyFileToFolders Include="droppacket.o" />
</ItemGroup>
</Project>

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

@ -0,0 +1,22 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <functional>
class _unwind_helper
{
public:
_unwind_helper(std::function<void()> unwind) : _unwind(unwind)
{
}
~_unwind_helper()
{
_unwind();
}
private:
std::function<void()> _unwind;
};

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -128,6 +128,7 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

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

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -142,7 +142,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dnsflood.cpp" />
<ClCompile Include="dns_flood.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

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

@ -15,7 +15,7 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dnsflood.cpp">
<ClCompile Include="dns_flood.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

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

@ -41,22 +41,22 @@ BOOL WINAPI DllMain(
CMD_ENTRY g_EbpfAddCommandTable[] =
{
CREATE_CMD_ENTRY(EBPF_ADD_PROGRAM, HandleEbpfAddProgram),
CREATE_CMD_ENTRY(EBPF_ADD_PROGRAM, handle_ebpf_add_program),
};
CMD_ENTRY g_EbpfDeleteCommandTable[] =
{
CREATE_CMD_ENTRY(EBPF_DELETE_PROGRAM, HandleEbpfDeleteProgram),
CREATE_CMD_ENTRY(EBPF_DELETE_PROGRAM, handle_ebpf_delete_program),
};
CMD_ENTRY g_EbpfSetCommandTable[] =
{
CREATE_CMD_ENTRY(EBPF_SET_PROGRAM, HandleEbpfSetProgram),
CREATE_CMD_ENTRY(EBPF_SET_PROGRAM, handle_ebpf_set_program),
};
CMD_ENTRY g_EbpfShowCommandTable[] =
{
CREATE_CMD_ENTRY(EBPF_SHOW_DISASSEMBLY, HandleEbpfShowDisassembly),
CREATE_CMD_ENTRY(EBPF_SHOW_PROGRAMS, HandleEbpfShowPrograms),
CREATE_CMD_ENTRY(EBPF_SHOW_SECTIONS, HandleEbpfShowSections),
CREATE_CMD_ENTRY(EBPF_SHOW_VERIFICATION, HandleEbpfShowVerification),
CREATE_CMD_ENTRY(EBPF_SHOW_DISASSEMBLY, handle_ebpf_show_disassembly),
CREATE_CMD_ENTRY(EBPF_SHOW_PROGRAMS, handle_ebpf_show_programs),
CREATE_CMD_ENTRY(EBPF_SHOW_SECTIONS, handle_ebpf_show_sections),
CREATE_CMD_ENTRY(EBPF_SHOW_VERIFICATION, handle_ebpf_show_verification),
};
#define HLP_GROUP_ADD 1100
@ -106,7 +106,7 @@ InitHelperDll(DWORD netshVersion, void* reserved)
if (status == ERROR_SUCCESS)
{
status = EbpfApiInit();
status = ebpf_api_initiate();
}
return status;

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">

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

@ -14,10 +14,10 @@ TOKEN_VALUE g_LevelEnum[2] = {
{ L"verbose", VL_VERBOSE },
};
DWORD HandleEbpfShowDisassembly(
DWORD handle_ebpf_show_disassembly(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -29,31 +29,31 @@ DWORD HandleEbpfShowDisassembly(
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
std::string filename;
std::string section = ".text";
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}
@ -85,10 +85,10 @@ DWORD HandleEbpfShowDisassembly(
}
}
DWORD HandleEbpfShowSections(
DWORD handle_ebpf_show_sections(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -101,38 +101,38 @@ DWORD HandleEbpfShowSections(
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
{TOKEN_LEVEL, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
VERBOSITY_LEVEL level = VL_NORMAL;
std::string filename;
std::string section;
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}
case 2: // LEVEL
status = MatchEnumTag(NULL,
argv[currentIndex + i],
argv[current_index + i],
_countof(g_LevelEnum),
g_LevelEnum,
(PULONG)&level);
@ -202,10 +202,10 @@ DWORD HandleEbpfShowSections(
}
}
DWORD HandleEbpfShowVerification(
DWORD handle_ebpf_show_verification(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -217,31 +217,31 @@ DWORD HandleEbpfShowVerification(
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
std::string filename;
std::string section = ".text";
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}

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

@ -6,9 +6,9 @@
extern "C" {
#endif
FN_HANDLE_CMD HandleEbpfShowDisassembly;
FN_HANDLE_CMD HandleEbpfShowSections;
FN_HANDLE_CMD HandleEbpfShowVerification;
FN_HANDLE_CMD handle_ebpf_show_disassembly;
FN_HANDLE_CMD handle_ebpf_show_sections;
FN_HANDLE_CMD handle_ebpf_show_verification;
#ifdef __cplusplus
}

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

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.72.0.0" targetFramework="native" />
<package identifier="boost" version="1.72.0.0" targetFramework="native" />
</packages>

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

@ -11,7 +11,7 @@
#include <iostream>
#pragma comment(lib, "EbpfApi.lib")
HANDLE g_program_handle = INVALID_HANDLE_VALUE;
static HANDLE _program_handle = INVALID_HANDLE_VALUE;
typedef enum {
PINNED_ANY = 0,
@ -19,20 +19,20 @@ typedef enum {
PINNED_NO = 2,
} PINNED_CONSTRAINT;
TOKEN_VALUE g_PinnedEnum[] = {
static TOKEN_VALUE _pinned_enum[] = {
{ L"any", PINNED_ANY },
{ L"yes", PINNED_YES },
{ L"no", PINNED_NO },
};
TOKEN_VALUE g_EbpfProgramTypeEnum[] = {
static TOKEN_VALUE _ebpf_program_type_enum[] = {
{ L"xdp", EBPF_PROGRAM_TYPE_XDP },
};
unsigned long HandleEbpfAddProgram(
unsigned long handle_ebpf_add_program(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -44,41 +44,41 @@ unsigned long HandleEbpfAddProgram(
{TOKEN_TYPE, NS_REQ_ZERO, FALSE},
{TOKEN_PINNED, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
std::string filename;
std::string section = ".text";
EBPF_PROGRAM_TYPE type = EBPF_PROGRAM_TYPE_XDP;
PINNED_CONSTRAINT pinned = PINNED_ANY;
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}
case 2: // TYPE
status = MatchEnumTag(NULL,
argv[currentIndex + i],
_countof(g_EbpfProgramTypeEnum),
g_EbpfProgramTypeEnum,
argv[current_index + i],
_countof(_ebpf_program_type_enum),
_ebpf_program_type_enum,
(PULONG)&type);
if (status != NO_ERROR) {
status = ERROR_INVALID_PARAMETER;
@ -86,9 +86,9 @@ unsigned long HandleEbpfAddProgram(
break;
case 3: // PINNED
status = MatchEnumTag(NULL,
argv[currentIndex + i],
_countof(g_PinnedEnum),
g_PinnedEnum,
argv[current_index + i],
_countof(_pinned_enum),
_pinned_enum,
(PULONG)&pinned);
if (status != NO_ERROR) {
status = ERROR_INVALID_PARAMETER;
@ -103,36 +103,36 @@ unsigned long HandleEbpfAddProgram(
return status;
}
if (g_program_handle != INVALID_HANDLE_VALUE)
if (_program_handle != INVALID_HANDLE_VALUE)
{
EbpfApiDetachProgram(g_program_handle, EBPF_HOOK_POINT_XDP);
EbpfApiUnloadProgram(g_program_handle);
g_program_handle = INVALID_HANDLE_VALUE;
ebpf_api_detach_program(_program_handle, EBPF_HOOK_POINT_XDP);
ebpf_api_unload_program(_program_handle);
_program_handle = INVALID_HANDLE_VALUE;
}
char* error_message = nullptr;
status = EbpfApiLoadProgram(filename.c_str(), section.c_str(), &g_program_handle, &error_message);
status = ebpf_api_load_program(filename.c_str(), section.c_str(), &_program_handle, &error_message);
if (status != ERROR_SUCCESS)
{
std::cerr << "EbpfApiLoadProgram failed with error " << status << " and message " << error_message << std::endl;
std::cerr << "ebpf_api_load_program failed with error " << status << " and message " << error_message << std::endl;
return status;
}
status = EbpfApiAttachProgram(g_program_handle, EBPF_HOOK_POINT_XDP);
status = ebpf_api_attach_program(_program_handle, EBPF_HOOK_POINT_XDP);
if (status != ERROR_SUCCESS)
{
std::cerr << "EbpfApiAttachProgram failed with error " << status << std::endl;
std::cerr << "ebpf_api_attach_program failed with error " << status << std::endl;
return status;
}
return ERROR_SUCCESS;
}
DWORD HandleEbpfDeleteProgram(
DWORD handle_ebpf_delete_program(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -142,31 +142,31 @@ DWORD HandleEbpfDeleteProgram(
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
std::string filename;
std::string section = ".text";
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}
@ -176,21 +176,21 @@ DWORD HandleEbpfDeleteProgram(
}
}
if (g_program_handle != INVALID_HANDLE_VALUE)
if (_program_handle != INVALID_HANDLE_VALUE)
{
EbpfApiDetachProgram(g_program_handle, EBPF_HOOK_POINT_XDP);
EbpfApiUnloadProgram(g_program_handle);
g_program_handle = INVALID_HANDLE_VALUE;
ebpf_api_detach_program(_program_handle, EBPF_HOOK_POINT_XDP);
ebpf_api_unload_program(_program_handle);
_program_handle = INVALID_HANDLE_VALUE;
}
// TODO: delete program
return ERROR_SUCCESS;
}
DWORD HandleEbpfSetProgram(
DWORD handle_ebpf_set_program(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -201,40 +201,40 @@ DWORD HandleEbpfSetProgram(
{TOKEN_SECTION, NS_REQ_PRESENT, FALSE},
{TOKEN_PINNED, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
3, // Two required tags plus at least one optional tag.
tagType);
tag_type);
std::string filename;
std::string section = ".text";
PINNED_CONSTRAINT pinned = PINNED_ANY;
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 1: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}
case 2: // PINNED
status = MatchEnumTag(NULL,
argv[currentIndex + i],
_countof(g_PinnedEnum),
g_PinnedEnum,
argv[current_index + i],
_countof(_pinned_enum),
_pinned_enum,
(PULONG)&pinned);
if ((status != NO_ERROR) || (pinned == PINNED_ANY)) {
status = ERROR_INVALID_PARAMETER;
@ -253,10 +253,10 @@ DWORD HandleEbpfSetProgram(
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD HandleEbpfShowPrograms(
DWORD handle_ebpf_show_programs(
LPCWSTR machine,
LPWSTR* argv,
DWORD currentIndex,
DWORD current_index,
DWORD argc,
DWORD flags,
LPCVOID data,
@ -269,30 +269,30 @@ DWORD HandleEbpfShowPrograms(
{TOKEN_FILENAME, NS_REQ_ZERO, FALSE},
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
};
ULONG tagType[_countof(tags)] = { 0 };
ULONG tag_type[_countof(tags)] = { 0 };
ULONG status = PreprocessCommand(nullptr,
argv,
currentIndex,
current_index,
argc,
tags,
_countof(tags),
0,
_countof(tags),
tagType);
tag_type);
EBPF_PROGRAM_TYPE type = EBPF_PROGRAM_TYPE_XDP;
PINNED_CONSTRAINT pinned = PINNED_ANY;
VERBOSITY_LEVEL level = VL_NORMAL;
std::string filename;
std::string section = ".text";
for (int i = 0; (status == NO_ERROR) && ((i + currentIndex) < argc); i++) {
switch (tagType[i]) {
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
switch (tag_type[i]) {
case 0: // TYPE
status = MatchEnumTag(NULL,
argv[currentIndex + i],
_countof(g_EbpfProgramTypeEnum),
g_EbpfProgramTypeEnum,
argv[current_index + i],
_countof(_ebpf_program_type_enum),
_ebpf_program_type_enum,
(PULONG)&type);
if (status != NO_ERROR) {
status = ERROR_INVALID_PARAMETER;
@ -300,9 +300,9 @@ DWORD HandleEbpfShowPrograms(
break;
case 1: // PINNED
status = MatchEnumTag(NULL,
argv[currentIndex + i],
_countof(g_PinnedEnum),
g_PinnedEnum,
argv[current_index + i],
_countof(_pinned_enum),
_pinned_enum,
(PULONG)&pinned);
if (status != NO_ERROR) {
status = ERROR_INVALID_PARAMETER;
@ -310,7 +310,7 @@ DWORD HandleEbpfShowPrograms(
break;
case 2: // LEVEL
status = MatchEnumTag(NULL,
argv[currentIndex + i],
argv[current_index + i],
_countof(g_LevelEnum),
g_LevelEnum,
(PULONG)&level);
@ -320,13 +320,13 @@ DWORD HandleEbpfShowPrograms(
break;
case 3: // FILENAME
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
filename = std::string(ws.begin(), ws.end());
break;
}
case 4: // SECTION
{
std::wstring ws(argv[currentIndex + i]);
std::wstring ws(argv[current_index + i]);
section = std::string(ws.begin(), ws.end());
break;
}

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

@ -6,10 +6,10 @@
extern "C" {
#endif
FN_HANDLE_CMD HandleEbpfAddProgram;
FN_HANDLE_CMD HandleEbpfDeleteProgram;
FN_HANDLE_CMD HandleEbpfSetProgram;
FN_HANDLE_CMD HandleEbpfShowPrograms;
FN_HANDLE_CMD handle_ebpf_add_program;
FN_HANDLE_CMD handle_ebpf_delete_program;
FN_HANDLE_CMD handle_ebpf_set_program;
FN_HANDLE_CMD handle_ebpf_show_programs;
#ifdef __cplusplus
}