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:
Родитель
5be028810b
Коммит
b138e2fb83
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче