eBPF should use Windows Handles for eBPF objects (#110)

* Pickup changes from upstream ubpf

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Add ebpf_handle_kernel.c to interface with Windows object manager to manage lifetimes.

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* PR feedback

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2021-04-30 12:49:23 -06:00 коммит произвёл GitHub
Родитель 5be028810b
Коммит b138e2fb83
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 262 добавлений и 123 удалений

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

@ -1 +1 @@
Subproject commit 442a9b750835deed3ccc63788061738de93ed0f8
Subproject commit 1bd3e436951886faa2435c42b7139f7d2a55f0ee

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

@ -17,8 +17,8 @@ EXPORTS
ebpf_api_elf_disassemble_section
ebpf_api_elf_verify_section
ebpf_api_elf_free
ebpf_api_pin_map
ebpf_api_unpin_map
ebpf_api_pin_object
ebpf_api_unpin_object
ebpf_api_get_next_map
ebpf_api_get_pinned_map
ebpf_api_get_next_program

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

@ -228,19 +228,19 @@ extern "C"
ebpf_api_free_string(const char* string);
/**
* @brief Associate a name with a map handle.
* @param[in] handle Handle to map.
* @brief Associate a name with an object handle.
* @param[in] handle Handle to object.
* @param[in] name Name to associate with handle.
*/
uint32_t
ebpf_api_pin_map(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length);
ebpf_api_pin_object(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length);
/**
* @brief Dissociate a name with a map handle.
* @brief Dissociate a name with an object handle.
* @param[in] name Name to dissociate.
*/
uint32_t
ebpf_api_unpin_map(const uint8_t* name, uint32_t name_length);
ebpf_api_unpin_object(const uint8_t* name, uint32_t name_length);
/**
* @brief Find a map given its associated name.

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

@ -15,6 +15,7 @@ extern "C"
typedef enum _ebpf_object_type
{
EBPF_OBJECT_UNKNOWN,
EBPF_OBJECT_MAP,
EBPF_OBJECT_LINK,
EBPF_OBJECT_PROGRAM,

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

@ -13,6 +13,10 @@ extern "C"
#define EBPF_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0]))
#define EBPF_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m))
#define EBPF_DEVICE_NAME L"\\Device\\EbpfIoDevice"
#define EBPF_SYMBOLIC_DEVICE_NAME L"\\GLOBAL??\\EbpfIoDevice"
#define EBPF_DEVICE_WIN32_NAME L"\\\\.\\EbpfIoDevice"
/**
* @brief A UTF-8 encoded string.
* Notes:

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

@ -19,8 +19,8 @@ typedef enum _ebpf_operation_id
EBPF_OPERATION_GET_NEXT_PROGRAM,
EBPF_OPERATION_QUERY_MAP_DEFINITION,
EBPF_OPERATION_QUERY_PROGRAM_INFORMATION,
EBPF_OPERATION_UPDATE_MAP_PINNING,
EBPF_OPERATION_GET_MAP_PINNING,
EBPF_OPERATION_UPDATE_PINNING,
EBPF_OPERATION_GET_PINNING,
EBPF_OPERATION_LINK_PROGRAM,
EBPF_OPERATION_CLOSE_HANDLE,
EBPF_OPERATION_GET_EC_FUNCTION,
@ -194,15 +194,15 @@ typedef struct _ebpf_operation_update_map_pinning_request
struct _ebpf_operation_header header;
uint64_t handle;
uint8_t name[1];
} ebpf_operation_update_map_pinning_request_t;
} ebpf_operation_update_pinning_request_t;
typedef struct _ebpf_operation_get_map_pinning_request
typedef struct _ebpf_operation_get_pinning_request
{
struct _ebpf_operation_header header;
uint8_t name[1];
} ebpf_operation_get_map_pinning_request_t;
} ebpf_operation_get_pinning_request_t;
typedef struct _ebpf_operation_get_map_pinning_reply
typedef struct _ebpf_operation_get_pinning_reply
{
struct _ebpf_operation_header header;
uint64_t handle;

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

@ -10,6 +10,7 @@
#include <stdexcept>
#include "ebpf_protocol.h"
#include "ebpf_platform.h"
#include "platform.h"
#include "tlv.h"
extern "C"
@ -33,12 +34,6 @@ struct empty_reply
{
} _empty_reply;
extern "C"
{
void
set_error_print(struct ubpf_vm* vm, void* address);
}
template <typename request_t, typename reply_t = empty_reply>
static uint32_t
invoke_ioctl(ebpf_handle_t handle, request_t& request, reply_t& reply = _empty_reply)
@ -100,14 +95,12 @@ invoke_ioctl(ebpf_handle_t handle, request_t& request, reply_t& reply = _empty_r
uint32_t
ebpf_api_initiate()
{
LPCWSTR ebpfDeviceName = L"\\\\.\\EbpfIoDevice";
if (device_handle != INVALID_HANDLE_VALUE) {
return ERROR_ALREADY_INITIALIZED;
}
device_handle = Platform::CreateFile(
ebpfDeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
EBPF_DEVICE_WIN32_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (device_handle == INVALID_HANDLE_VALUE) {
return GetLastError();
@ -222,7 +215,10 @@ resolve_maps_in_byte_code(std::vector<uint8_t>& byte_code)
request->header.length = static_cast<uint16_t>(request_buffer.size());
for (size_t index = 0; index < map_handles.size(); index++) {
request->map_handle[index] = map_handles[index];
if (map_handles[index] > _map_file_descriptors.size()) {
return ERROR_INVALID_PARAMETER;
}
request->map_handle[index] = _map_file_descriptors[map_handles[index] - 1].handle;
}
uint32_t result = invoke_ioctl(device_handle, request_buffer, reply_buffer);
@ -402,7 +398,7 @@ ebpf_api_load_program(
}
}
set_error_print(vm, reinterpret_cast<void*>(log_function_address));
set_error_print(vm, reinterpret_cast<int (*)(FILE * stream, const char* format, ...)>(log_function_address));
if (ubpf_load(
vm, byte_code.data(), static_cast<uint32_t>(byte_code.size()), const_cast<char**>(error_message)) < 0) {
@ -457,12 +453,12 @@ ebpf_api_free_string(const char* error_message)
}
uint32_t
ebpf_api_pin_map(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length)
ebpf_api_pin_object(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length)
{
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_update_map_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_update_map_pinning_request_t*>(request_buffer.data());
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_update_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_update_pinning_request_t*>(request_buffer.data());
request->header.id = EBPF_OPERATION_UPDATE_MAP_PINNING;
request->header.id = EBPF_OPERATION_UPDATE_PINNING;
request->header.length = static_cast<uint16_t>(request_buffer.size());
request->handle = reinterpret_cast<uint64_t>(handle);
std::copy(name, name + name_length, request->name);
@ -470,12 +466,12 @@ ebpf_api_pin_map(ebpf_handle_t handle, const uint8_t* name, uint32_t name_length
}
uint32_t
ebpf_api_unpin_map(const uint8_t* name, uint32_t name_length)
ebpf_api_unpin_object(const uint8_t* name, uint32_t name_length)
{
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_update_map_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_update_map_pinning_request_t*>(request_buffer.data());
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_update_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_update_pinning_request_t*>(request_buffer.data());
request->header.id = EBPF_OPERATION_UPDATE_MAP_PINNING;
request->header.id = EBPF_OPERATION_UPDATE_PINNING;
request->header.length = static_cast<uint16_t>(request_buffer.size());
request->handle = UINT64_MAX;
std::copy(name, name + name_length, request->name);
@ -485,11 +481,11 @@ ebpf_api_unpin_map(const uint8_t* name, uint32_t name_length)
uint32_t
ebpf_api_get_pinned_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle)
{
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_get_map_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_get_map_pinning_request_t*>(request_buffer.data());
std::vector<uint8_t> request_buffer(offsetof(ebpf_operation_get_pinning_request_t, name) + name_length);
auto request = reinterpret_cast<ebpf_operation_get_pinning_request_t*>(request_buffer.data());
ebpf_operation_get_map_pinning_reply_t reply;
request->header.id = EBPF_OPERATION_GET_MAP_PINNING;
request->header.id = EBPF_OPERATION_GET_PINNING;
request->header.length = static_cast<uint16_t>(request_buffer.size());
std::copy(name, name + name_length, request->name);
auto result = invoke_ioctl(device_handle, request_buffer, reply);
@ -497,7 +493,7 @@ ebpf_api_get_pinned_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t
return result;
}
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_GET_MAP_PINNING) {
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_GET_PINNING) {
return ERROR_INVALID_PARAMETER;
}

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

@ -507,13 +507,13 @@ Done:
}
static ebpf_error_code_t
_ebpf_core_protocol_update_map_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
{
ebpf_error_code_t retval;
const ebpf_utf8_string_t name = {
(uint8_t*)request->name,
request->header.length - EBPF_OFFSET_OF(ebpf_operation_update_map_pinning_request_t, name)};
ebpf_map_t* map = NULL;
request->header.length - EBPF_OFFSET_OF(ebpf_operation_update_pinning_request_t, name)};
ebpf_object_t* object = NULL;
if (name.length == 0) {
retval = EBPF_ERROR_INVALID_PARAMETER;
@ -524,29 +524,28 @@ _ebpf_core_protocol_update_map_pinning(_In_ const struct _ebpf_operation_update_
retval = ebpf_pinning_table_delete(_ebpf_core_map_pinning_table, &name);
goto Done;
} else {
retval = ebpf_reference_object_by_handle(request->handle, EBPF_OBJECT_MAP, (ebpf_object_t**)&map);
retval = ebpf_reference_object_by_handle(request->handle, EBPF_OBJECT_UNKNOWN, (ebpf_object_t**)&object);
if (retval != EBPF_ERROR_SUCCESS)
goto Done;
retval = ebpf_pinning_table_insert(_ebpf_core_map_pinning_table, &name, (ebpf_object_t*)map);
retval = ebpf_pinning_table_insert(_ebpf_core_map_pinning_table, &name, (ebpf_object_t*)object);
}
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
ebpf_object_release_reference((ebpf_object_t*)object);
return retval;
}
static ebpf_error_code_t
_ebpf_core_protocol_get_pinned_map(
_In_ const struct _ebpf_operation_get_map_pinning_request* request,
_Inout_ struct _ebpf_operation_get_map_pinning_reply* reply,
_ebpf_core_protocol_get_pinned_object(
_In_ const struct _ebpf_operation_get_pinning_request* request,
_Inout_ struct _ebpf_operation_get_pinning_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
ebpf_map_t* map = NULL;
ebpf_object_t* object = NULL;
const ebpf_utf8_string_t name = {
(uint8_t*)request->name,
request->header.length - EBPF_OFFSET_OF(ebpf_operation_get_map_pinning_request_t, name)};
(uint8_t*)request->name, request->header.length - EBPF_OFFSET_OF(ebpf_operation_get_pinning_request_t, name)};
UNREFERENCED_PARAMETER(reply_length);
if (name.length == 0) {
@ -554,14 +553,14 @@ _ebpf_core_protocol_get_pinned_map(
goto Done;
}
retval = ebpf_pinning_table_find(_ebpf_core_map_pinning_table, &name, (ebpf_object_t**)&map);
retval = ebpf_pinning_table_find(_ebpf_core_map_pinning_table, &name, (ebpf_object_t**)&object);
if (retval != EBPF_ERROR_SUCCESS)
goto Done;
retval = ebpf_handle_create(&reply->handle, (ebpf_object_t*)map);
retval = ebpf_handle_create(&reply->handle, (ebpf_object_t*)object);
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
ebpf_object_release_reference((ebpf_object_t*)object);
return retval;
}
@ -691,10 +690,10 @@ static ebpf_protocol_handler_t _ebpf_protocol_handlers[EBPF_OPERATION_GET_EC_FUN
{(ebpf_error_code_t(__cdecl*)(const void*))_ebpf_core_protocol_query_program_information,
sizeof(struct _ebpf_operation_query_program_information_request),
sizeof(struct _ebpf_operation_query_program_information_reply)},
{_ebpf_core_protocol_update_map_pinning, sizeof(struct _ebpf_operation_update_map_pinning_request), 0},
{(ebpf_error_code_t(__cdecl*)(const void*))_ebpf_core_protocol_get_pinned_map,
sizeof(struct _ebpf_operation_get_map_pinning_request),
sizeof(struct _ebpf_operation_get_map_pinning_reply)},
{_ebpf_core_protocol_update_pinning, sizeof(struct _ebpf_operation_update_map_pinning_request), 0},
{(ebpf_error_code_t(__cdecl*)(const void*))_ebpf_core_protocol_get_pinned_object,
sizeof(struct _ebpf_operation_get_pinning_request),
sizeof(struct _ebpf_operation_get_pinning_reply)},
{(ebpf_error_code_t(__cdecl*)(const void*))_ebpf_core_protocol_link_program,
sizeof(ebpf_operation_link_program_request_t),
sizeof(ebpf_operation_link_program_reply_t)},

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

@ -133,6 +133,9 @@ ebpf_error_code_t
_ebpf_link_instance_invoke(const ebpf_link_t* link, void* program_context, uint32_t* result)
{
ebpf_error_code_t return_value;
if (!link)
return EBPF_ERROR_SUCCESS;
return_value = ebpf_epoch_enter();
if (return_value != EBPF_ERROR_SUCCESS)
return return_value;

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

@ -9,6 +9,8 @@
#include "ebpf_epoch.h"
#include "ebpf_link.h"
#include "ebpf_object.h"
typedef struct _FILE FILE;
#include "ubpf.h"
typedef struct _ebpf_program

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

@ -90,12 +90,14 @@ ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_
return EBPF_ERROR_INVALID_HANDLE;
ebpf_lock_lock(&_ebpf_handle_table_lock, &state);
if (_ebpf_handle_table[handle] != NULL && _ebpf_handle_table[handle]->type == object_type) {
if ((_ebpf_handle_table[handle] != NULL) &&
((_ebpf_handle_table[handle]->type == object_type) || (object_type == EBPF_OBJECT_UNKNOWN))) {
ebpf_object_acquire_reference(_ebpf_handle_table[handle]);
*object = _ebpf_handle_table[handle];
return_value = EBPF_ERROR_SUCCESS;
} else
return_value = EBPF_ERROR_INVALID_HANDLE;
ebpf_lock_unlock(&_ebpf_handle_table_lock, &state);
return return_value;
}

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

@ -0,0 +1,123 @@
/*
* Copyright (c) Microsoft Corporation
* SPDX-License-Identifier: MIT
*/
#include "ebpf_handle.h"
ebpf_error_code_t
ebpf_handle_table_initiate()
{
return EBPF_ERROR_SUCCESS;
}
void
ebpf_handle_table_terminate()
{}
ebpf_error_code_t
ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
{
ebpf_error_code_t return_value;
HANDLE file_handle = 0;
OBJECT_ATTRIBUTES object_attributes;
UNICODE_STRING object_name;
IO_STATUS_BLOCK io_status_block;
NTSTATUS status;
FILE_OBJECT* file_object = NULL;
RtlInitUnicodeString(&object_name, EBPF_SYMBOLIC_DEVICE_NAME);
InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL);
status = ZwCreateFile(
&file_handle,
GENERIC_READ | GENERIC_WRITE,
&object_attributes,
&io_status_block,
NULL,
0,
0,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL,
0);
if (!NT_SUCCESS(status)) {
return_value = EBPF_ERROR_NOT_SUPPORTED;
goto Done;
}
status = ObReferenceObjectByHandle(file_handle, 0, NULL, UserMode, &file_object, NULL);
if (!NT_SUCCESS(status)) {
return_value = EBPF_ERROR_NOT_SUPPORTED;
goto Done;
}
ebpf_object_acquire_reference(object);
file_object->FsContext2 = object;
*handle = (ebpf_handle_t)file_handle;
file_handle = 0;
return_value = EBPF_ERROR_SUCCESS;
Done:
if (file_object)
ObDereferenceObject(file_object);
if (file_handle)
ObCloseHandle(file_handle, UserMode);
return return_value;
}
ebpf_error_code_t
ebpf_handle_close(ebpf_handle_t handle)
{
if (!NT_SUCCESS(ObCloseHandle((HANDLE)handle, UserMode)))
return EBPF_ERROR_INVALID_HANDLE;
else
return EBPF_ERROR_SUCCESS;
}
ebpf_error_code_t
ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_type, ebpf_object_t** object)
{
ebpf_error_code_t return_value;
NTSTATUS status;
FILE_OBJECT* file_object = NULL;
ebpf_object_t* local_object;
status = ObReferenceObjectByHandle((HANDLE)handle, 0, NULL, UserMode, &file_object, NULL);
if (!NT_SUCCESS(status)) {
return_value = EBPF_ERROR_INVALID_HANDLE;
goto Done;
}
local_object = (ebpf_object_t*)file_object->FsContext2;
if (local_object == NULL) {
return_value = EBPF_ERROR_INVALID_HANDLE;
goto Done;
}
if ((object_type != EBPF_OBJECT_UNKNOWN) && (ebpf_object_get_type(local_object) != object_type)) {
return_value = EBPF_ERROR_INVALID_HANDLE;
goto Done;
}
ebpf_object_acquire_reference(local_object);
*object = local_object;
return_value = EBPF_ERROR_SUCCESS;
Done:
if (file_object)
ObDereferenceObject(file_object);
return return_value;
}
ebpf_error_code_t
ebpf_get_next_handle_by_type(ebpf_handle_t previous_handle, ebpf_object_type_t object_type, ebpf_handle_t* next_handle)
{
UNREFERENCED_PARAMETER(previous_handle);
UNREFERENCED_PARAMETER(object_type);
UNREFERENCED_PARAMETER(next_handle);
return EBPF_ERROR_NOT_SUPPORTED;
}

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

@ -39,11 +39,11 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\ebpf_handle.c" />
<ClCompile Include="..\ebpf_hash_table.c" />
<ClCompile Include="..\ebpf_object.c" />
<ClCompile Include="..\ebpf_pinning_table.c" />
<ClCompile Include="ebpf_extension_kernel.c" />
<ClCompile Include="ebpf_handle_kernel.c" />
<ClCompile Include="ebpf_platform_kernel.c" />
</ItemGroup>
<ItemGroup>

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

@ -31,10 +31,10 @@
<ClCompile Include="..\ebpf_object.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_handle.c">
<ClCompile Include="ebpf_extension_kernel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ebpf_extension_kernel.c">
<ClCompile Include="ebpf_handle_kernel.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

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

@ -339,13 +339,7 @@ ebpf_guid_create(GUID* new_guid)
int32_t
ebpf_log_function(void* context, const char* format_string, ...)
{
va_list arg_start;
va_start(arg_start, format_string);
UNREFERENCED_PARAMETER(context);
vprintf(format_string, arg_start);
va_end(arg_start);
UNREFERENCED_PARAMETER(format_string);
return 0;
}

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

@ -7,8 +7,8 @@
Abstract:
WDF based driver that does the following:
1. Registers as a WFP L2 Callout
2. Opens an IOCTL surface
1. Registers a set of WFP callouts.
2. Opens an IOCTL surface that forwards commands to ebfp_core.
Environment:
@ -16,43 +16,24 @@ Environment:
--*/
// ntddk.h needs to be included first due to inter header dependencies on Windows.
#include <ntddk.h>
#include <wdf.h>
#pragma warning(push)
#pragma warning(disable : 4201) // unnamed struct/union
#include <fwpmk.h>
#include <fwpsk.h>
#pragma warning(pop)
#include <netiodef.h>
#include <wdf.h>
#include "ebpf_core.h"
#include "ebpf_l2_hook.h"
#include "ebpf_protocol.h"
#include "ebpf_windows.h"
#include <fwpmk.h>
#include <netiodef.h>
#define RTL_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m))
#include "ebpf_object.h"
// Driver global variables
static DEVICE_OBJECT* _wdm_device_object;
static BOOLEAN _driver_unloading_flag = FALSE;
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_UNLOAD EvtDriverUnload;
// Typedefs
typedef VOID(WINAPI* FUNCTION_TYPE)(VOID);
typedef DWORD(WINAPI* FUNCTION_TYPE1)(DWORD);
typedef DWORD(WINAPI* FUNCTION_TYPE2)(PVOID, PVOID);
//
// Constants
//
static const wchar_t EBPF_DEVICE_NAME[] = L"\\Device\\EbpfIoDevice";
static const wchar_t EBPF_SYMBOLIC_DEVICE_NAME[] = L"\\GLOBAL??\\EbpfIoDevice";
static DEVICE_OBJECT* _ebpf_driver_device_object;
static BOOLEAN _ebpf_driver_unloading_flag = FALSE;
#ifndef CTL_CODE
#define CTL_CODE(DeviceType, Function, Method, Access) \
@ -67,8 +48,11 @@ static const wchar_t EBPF_SYMBOLIC_DEVICE_NAME[] = L"\\GLOBAL??\\EbpfIoDevice";
//
// Pre-Declarations
//
static void
_ebpf_driver_file_close(WDFFILEOBJECT wdf_file_object);
static VOID
EbpfCoreEvtIoDeviceControl(
_ebpf_driver_io_device_control(
_In_ WDFQUEUE queue,
_In_ WDFREQUEST request,
size_t output_buffer_length,
@ -76,7 +60,7 @@ EbpfCoreEvtIoDeviceControl(
ULONG io_control_code);
inline NTSTATUS
ebpf_error_code_to_ntstatus(ebpf_error_code_t error)
_ebpf_driver_error_code_to_ntstatus(ebpf_error_code_t error)
{
switch (error) {
case EBPF_ERROR_SUCCESS:
@ -100,12 +84,12 @@ ebpf_error_code_to_ntstatus(ebpf_error_code_t error)
}
}
_Function_class_(EVT_WDF_DRIVER_UNLOAD) _IRQL_requires_same_
_IRQL_requires_max_(PASSIVE_LEVEL) void EvtDriverUnload(_In_ WDFDRIVER driver_object)
static _Function_class_(EVT_WDF_DRIVER_UNLOAD) _IRQL_requires_same_
_IRQL_requires_max_(PASSIVE_LEVEL) void _ebpf_driver_unload(_In_ WDFDRIVER driver_object)
{
UNREFERENCED_PARAMETER(driver_object);
_driver_unloading_flag = TRUE;
_ebpf_driver_unloading_flag = TRUE;
ebpf_hook_unregister_providers();
@ -119,7 +103,7 @@ _Function_class_(EVT_WDF_DRIVER_UNLOAD) _IRQL_requires_same_
// for a callout driver and setup the ioctl surface
//
static NTSTATUS
EbpfCoreInitDriverObjects(
_ebpf_driver_initialize_objects(
_Inout_ DRIVER_OBJECT* driver_object,
_In_ const UNICODE_STRING* registry_path,
_Out_ WDFDRIVER* driver,
@ -132,11 +116,13 @@ EbpfCoreInitDriverObjects(
UNICODE_STRING ebpf_device_name;
UNICODE_STRING ebpf_symbolic_device_name;
BOOLEAN device_create_flag = FALSE;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_FILEOBJECT_CONFIG file_object_config;
WDF_DRIVER_CONFIG_INIT(&driver_configuration, WDF_NO_EVENT_CALLBACK);
driver_configuration.DriverInitFlags |= WdfDriverInitNonPnpDriver;
driver_configuration.EvtDriverUnload = EvtDriverUnload;
driver_configuration.EvtDriverUnload = _ebpf_driver_unload;
status = WdfDriverCreate(driver_object, registry_path, WDF_NO_OBJECT_ATTRIBUTES, &driver_configuration, driver);
@ -146,7 +132,7 @@ EbpfCoreInitDriverObjects(
device_initialize = WdfControlDeviceInitAllocate(
*driver,
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL // only kernel/system and admins
&SDDL_DEVOBJ_SYS_ALL_ADM_ALL // only kernel/system and administrators.
);
if (!device_initialize) {
status = STATUS_INSUFFICIENT_RESOURCES;
@ -162,6 +148,16 @@ EbpfCoreInitDriverObjects(
RtlInitUnicodeString(&ebpf_device_name, EBPF_DEVICE_NAME);
WdfDeviceInitAssignName(device_initialize, &ebpf_device_name);
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.SynchronizationScope = WdfSynchronizationScopeNone;
WDF_FILEOBJECT_CONFIG_INIT(
&file_object_config,
NULL,
_ebpf_driver_file_close,
WDF_NO_EVENT_CALLBACK // No cleanup callback function
);
WdfDeviceInitSetFileObjectConfig(device_initialize, &file_object_config, &attributes);
status = WdfDeviceCreate(&device_initialize, WDF_NO_OBJECT_ATTRIBUTES, device);
if (!NT_SUCCESS(status)) {
@ -185,7 +181,7 @@ EbpfCoreInitDriverObjects(
// parallel default queue
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&io_queue_configuration, WdfIoQueueDispatchParallel);
io_queue_configuration.EvtIoDeviceControl = EbpfCoreEvtIoDeviceControl;
io_queue_configuration.EvtIoDeviceControl = _ebpf_driver_io_device_control;
status = WdfIoQueueCreate(
*device,
@ -197,7 +193,7 @@ EbpfCoreInitDriverObjects(
goto Exit;
}
status = ebpf_error_code_to_ntstatus(ebpf_core_initiate());
status = _ebpf_driver_error_code_to_ntstatus(ebpf_core_initiate());
if (!NT_SUCCESS(status)) {
goto Exit;
}
@ -222,8 +218,15 @@ Exit:
return status;
}
static void
_ebpf_driver_file_close(WDFFILEOBJECT wdf_file_object)
{
FILE_OBJECT* file_object = WdfFileObjectWdmGetFileObject(wdf_file_object);
ebpf_object_release_reference(file_object->FsContext2);
}
static VOID
EbpfCoreEvtIoDeviceControl(
_ebpf_driver_io_device_control(
_In_ WDFQUEUE queue,
_In_ WDFREQUEST request,
size_t output_buffer_length,
@ -271,7 +274,7 @@ EbpfCoreEvtIoDeviceControl(
size_t minimum_request_size = 0;
size_t minimum_reply_size = 0;
status = ebpf_hook_register_callouts(_wdm_device_object);
status = ebpf_hook_register_callouts(_ebpf_driver_device_object);
// non fatal for now while testing
user_request = input_buffer;
@ -280,7 +283,7 @@ EbpfCoreEvtIoDeviceControl(
goto Done;
}
status = ebpf_error_code_to_ntstatus(ebpf_core_get_protocol_handler_properties(
status = _ebpf_driver_error_code_to_ntstatus(ebpf_core_get_protocol_handler_properties(
user_request->id, &minimum_request_size, &minimum_reply_size));
if (status != STATUS_SUCCESS)
goto Done;
@ -307,7 +310,7 @@ EbpfCoreEvtIoDeviceControl(
user_reply = output_buffer;
}
status = ebpf_error_code_to_ntstatus(ebpf_core_invoke_protocol_handler(
status = _ebpf_driver_error_code_to_ntstatus(ebpf_core_invoke_protocol_handler(
user_request->id, user_request, user_reply, (uint16_t)actual_output_length));
// Fill out the rest of the out buffer after processing the input
@ -344,15 +347,15 @@ DriverEntry(_In_ DRIVER_OBJECT* driver_object, _In_ UNICODE_STRING* registry_pat
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "EbpfCore: DriverEntry\n"));
status = EbpfCoreInitDriverObjects(driver_object, registry_path, &driver, &device);
status = _ebpf_driver_initialize_objects(driver_object, registry_path, &driver, &device);
if (!NT_SUCCESS(status)) {
goto Exit;
}
_wdm_device_object = WdfDeviceWdmGetDeviceObject(device);
_ebpf_driver_device_object = WdfDeviceWdmGetDeviceObject(device);
ebpf_hook_register_callouts(_wdm_device_object);
ebpf_hook_register_callouts(_ebpf_driver_device_object);
// ignore status. at boot, registration can fail.
// we will try to re-register during program load.

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

@ -658,12 +658,12 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
std::string limit_maps_name = "bindmonitor::limits_map";
REQUIRE(
ebpf_api_pin_map(
ebpf_api_pin_object(
map_handles[0],
reinterpret_cast<const uint8_t*>(process_maps_name.c_str()),
static_cast<uint32_t>(process_maps_name.size())) == ERROR_SUCCESS);
REQUIRE(
ebpf_api_pin_map(
ebpf_api_pin_object(
map_handles[1],
reinterpret_cast<const uint8_t*>(limit_maps_name.c_str()),
static_cast<uint32_t>(limit_maps_name.size())) == ERROR_SUCCESS);
@ -681,11 +681,11 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
&map_handles[3]) == ERROR_SUCCESS);
REQUIRE(
ebpf_api_unpin_map(
ebpf_api_unpin_object(
reinterpret_cast<const uint8_t*>(process_maps_name.c_str()),
static_cast<uint32_t>(process_maps_name.size())) == ERROR_SUCCESS);
REQUIRE(
ebpf_api_unpin_map(
ebpf_api_unpin_object(
reinterpret_cast<const uint8_t*>(limit_maps_name.c_str()), static_cast<uint32_t>(limit_maps_name.size())) ==
ERROR_SUCCESS);
REQUIRE(

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

@ -10,6 +10,7 @@
const unsigned char process_map[] = "port_quota::process_map";
const unsigned char limits_map[] = "port_quota::limits_map";
const unsigned char program_link[] = "port_quota::program_link";
typedef struct _process_entry
{
@ -37,19 +38,26 @@ load(int argc, char** argv)
return 1;
}
result = ebpf_api_pin_object(maps[0], process_map, sizeof(process_map));
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to pin eBPF program: %d\n", result);
ebpf_api_free_string(error_message);
return 1;
}
result = ebpf_api_pin_object(maps[1], limits_map, sizeof(limits_map));
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to pin eBPF program: %d\n", result);
ebpf_api_free_string(error_message);
return 1;
}
result = ebpf_api_link_program(program, EBPF_ATTACH_TYPE_BIND, &link);
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to attach eBPF program\n");
return 1;
}
result = ebpf_api_pin_map(maps[0], process_map, sizeof(process_map));
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to pin eBPF program: %d\n", result);
ebpf_api_free_string(error_message);
return 1;
}
result = ebpf_api_pin_map(maps[1], limits_map, sizeof(limits_map));
result = ebpf_api_pin_object(link, program_link, sizeof(program_link));
if (result != ERROR_SUCCESS) {
fprintf(stderr, "Failed to pin eBPF program: %d\n", result);
ebpf_api_free_string(error_message);
@ -63,6 +71,10 @@ unload(int argc, char** argv)
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
ebpf_api_unpin_object(program_link, sizeof(program_link));
ebpf_api_unpin_object(limits_map, sizeof(limits_map));
ebpf_api_unpin_object(process_map, sizeof(process_map));
fprintf(stderr, "Not implemented yet.\n");
return 1;
}