Merged PR 4114187: Update code to match coding conventions
Update code to match coding conventions
This commit is contained in:
Родитель
93d9783890
Коммит
3a73e0f548
|
@ -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
Двоичные данные
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
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче