Merged PR 4226082: Fix bugs so that portquota demo works

Fix bugs so that portquota demo works
This commit is contained in:
Alan Jowett 2021-03-10 21:02:37 +00:00
Родитель 09bfd2063d
Коммит 366e41afdd
11 изменённых файлов: 663 добавлений и 553 удалений

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

@ -123,7 +123,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\external\ebpf-verifier\build\ebpfverifier.vcxproj">
<Project>{d2e4cac3-b91e-3dd8-bbac-d570ec568c8b}</Project>
<Project>{bd587773-916f-365f-82c0-2e8db12f40a0}</Project>
</ProjectReference>
<ProjectReference Include="..\libs\api\api.vcxproj">
<Project>{c8bf60c3-40a9-43ad-891a-8aa34f1c3a68}</Project>

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

@ -19,79 +19,88 @@ extern "C"
ebpf_core_terminate();
ebpf_error_code_t
ebpf_core_protocol_attach_code(
_In_ const struct _ebpf_operation_attach_detach_request* request, _Inout_ void* reply);
ebpf_core_protocol_attach_code(_In_ const struct _ebpf_operation_attach_detach_request* request);
ebpf_error_code_t
ebpf_core_protocol_detach_code(
_In_ const struct _ebpf_operation_attach_detach_request* request, _Inout_ void* reply);
ebpf_core_protocol_detach_code(_In_ const struct _ebpf_operation_attach_detach_request* request);
ebpf_error_code_t
ebpf_core_protocol_unload_code(_In_ const struct _ebpf_operation_unload_code_request* request, _Inout_ void* reply);
ebpf_core_protocol_unload_code(_In_ const struct _ebpf_operation_unload_code_request* request);
ebpf_error_code_t
ebpf_core_protocol_load_code(
_In_ const struct _ebpf_operation_load_code_request* inputRequest,
_Inout_ struct _ebpf_operation_load_code_reply* loadReply);
_Inout_ struct _ebpf_operation_load_code_reply* loadReply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_resolve_helper(
_In_ const struct _ebpf_operation_resolve_helper_request* request,
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply);
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_resolve_map(
_In_ const struct _ebpf_operation_resolve_map_request* request,
_Inout_ struct _ebpf_operation_resolve_map_reply* reply);
_Inout_ struct _ebpf_operation_resolve_map_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_create_map(
_In_ const struct _ebpf_operation_create_map_request* request,
_Inout_ struct _ebpf_operation_create_map_reply* reply);
_Inout_ struct _ebpf_operation_create_map_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_map_lookup_element(
_In_ const struct _ebpf_operation_map_lookup_element_request* request,
_Inout_ struct _ebpf_operation_map_lookup_element_reply* reply);
_Inout_ struct _ebpf_operation_map_lookup_element_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_map_update_element(
_In_ const struct _ebpf_operation_map_update_element_request* request, _Inout_ void* reply);
ebpf_core_protocol_map_update_element(_In_ const struct _ebpf_operation_map_update_element_request* request);
ebpf_error_code_t
ebpf_core_protocol_map_delete_element(
_In_ const struct _ebpf_operation_map_delete_element_request* request, _Inout_ void* reply);
ebpf_core_protocol_map_delete_element(_In_ const struct _ebpf_operation_map_delete_element_request* request);
ebpf_error_code_t
ebpf_core_protocol_map_get_next_key(
_In_ const struct _ebpf_operation_map_next_key_request* request,
_Inout_ struct _ebpf_operation_map_next_key_reply* reply);
_Inout_ struct _ebpf_operation_map_next_key_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_enumerate_maps(
_In_ const struct _ebpf_operation_enumerate_maps_request* request,
_Inout_ struct _ebpf_operation_enumerate_maps_reply* reply);
_Inout_ struct _ebpf_operation_enumerate_maps_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_query_map_definition(
_In_ const struct _ebpf_operation_query_map_definition_request* request,
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply);
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_protocol_update_map_pinning(
_In_ const struct _ebpf_operation_update_map_pinning_request* request, _Inout_ void* reply);
ebpf_core_protocol_update_map_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request);
ebpf_error_code_t
ebpf_core_protocol_lookup_map_pinning(
_In_ const struct _ebpf_operation_lookup_map_pinning_request* request,
_Inout_ struct _ebpf_operation_lookup_map_pinning_reply* reply);
_Inout_ struct _ebpf_operation_lookup_map_pinning_reply* reply,
uint16_t reply_length);
ebpf_error_code_t
ebpf_core_invoke_hook(_In_ ebpf_program_type_t hook_point, _Inout_ void* context, _Inout_ uint32_t* result);
typedef struct _ebpf_protocol_handler
{
ebpf_error_code_t (*protocol_handler)(_In_ const void* input_buffer, void* output_buffer);
union
{
ebpf_error_code_t (*protocol_handler_no_reply)(_In_ const void* input_buffer);
ebpf_error_code_t (*protocol_handler_with_reply)(
_In_ const void* input_buffer, void* output_buffer, uint16_t output_buffer_length);
} dispatch;
size_t minimum_request_size;
size_t minimum_reply_size;
} const ebpf_protocol_handler_t;

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

@ -303,11 +303,10 @@ ebpf_core_terminate()
}
ebpf_error_code_t
ebpf_core_protocol_attach_code(_In_ const struct _ebpf_operation_attach_detach_request* request, _Inout_ void* reply)
ebpf_core_protocol_attach_code(_In_ const struct _ebpf_operation_attach_detach_request* request)
{
ebpf_error_code_t retval = EBPF_ERROR_NOT_FOUND;
ebpf_core_code_entry_t* code = NULL;
UNREFERENCED_PARAMETER(reply);
switch (request->hook) {
case EBPF_PROGRAM_TYPE_XDP:
@ -333,11 +332,10 @@ Done:
}
ebpf_error_code_t
ebpf_core_protocol_detach_code(_In_ const struct _ebpf_operation_attach_detach_request* request, _Inout_ void* reply)
ebpf_core_protocol_detach_code(_In_ const struct _ebpf_operation_attach_detach_request* request)
{
ebpf_error_code_t retval = EBPF_ERROR_NOT_FOUND;
ebpf_core_code_entry_t* code = NULL;
UNREFERENCED_PARAMETER(reply);
code = _ebpf_core_find_code_entry(request->handle);
if (!code) {
@ -354,21 +352,24 @@ Done:
}
ebpf_error_code_t
ebpf_core_protocol_unload_code(_In_ const struct _ebpf_operation_unload_code_request* request, _Inout_ void* reply)
ebpf_core_protocol_unload_code(_In_ const struct _ebpf_operation_unload_code_request* request)
{
UNREFERENCED_PARAMETER(reply);
return _ebpf_core_delete_code_entry(request->handle);
}
ebpf_error_code_t
ebpf_core_protocol_load_code(
_In_ const ebpf_operation_load_code_request_t* request, _Inout_ struct _ebpf_operation_load_code_reply* reply)
_In_ const ebpf_operation_load_code_request_t* request,
_Inout_ struct _ebpf_operation_load_code_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
size_t code_size = request->header.length - RTL_OFFSET_OF(ebpf_operation_load_code_request_t, code);
size_t allocation_size = 0;
ebpf_core_code_entry_t* code = NULL;
ebpf_memory_type_t memory_type;
UNREFERENCED_PARAMETER(reply_length);
retval = ebpf_safe_size_t_add(code_size, sizeof(ebpf_core_code_entry_t), &allocation_size);
if (retval != EBPF_ERROR_SUCCESS) {
goto Done;
@ -418,7 +419,6 @@ ebpf_core_protocol_load_code(
goto Done;
}
}
reply->handle = _ebpf_core_insert_code_entry(code);
retval = reply->handle != UINT64_MAX ? EBPF_ERROR_SUCCESS : EBPF_ERROR_OUT_OF_RESOURCES;
@ -436,8 +436,11 @@ Done:
ebpf_error_code_t
ebpf_core_protocol_resolve_helper(
_In_ const struct _ebpf_operation_resolve_helper_request* request,
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply)
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply,
uint16_t reply_length)
{
UNREFERENCED_PARAMETER(reply_length);
if (request->helper_id[0] >= RTL_COUNT_OF(_ebpf_program_helpers)) {
return EBPF_ERROR_INVALID_PARAMETER;
}
@ -449,9 +452,11 @@ ebpf_core_protocol_resolve_helper(
ebpf_error_code_t
ebpf_core_protocol_resolve_map(
_In_ const struct _ebpf_operation_resolve_map_request* request,
_Inout_ struct _ebpf_operation_resolve_map_reply* reply)
_Inout_ struct _ebpf_operation_resolve_map_reply* reply,
uint16_t reply_length)
{
ebpf_core_map_t* map;
UNREFERENCED_PARAMETER(reply_length);
map = _ebpf_core_find_map_entry(request->map_handle[0]);
if (map) {
@ -490,13 +495,14 @@ ebpf_core_invoke_hook(_In_ ebpf_program_type_t hook_point, _Inout_ void* context
ebpf_error_code_t
ebpf_core_protocol_create_map(
_In_ const struct _ebpf_operation_create_map_request* request,
_Inout_ struct _ebpf_operation_create_map_reply* reply)
_Inout_ struct _ebpf_operation_create_map_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
ebpf_core_map_t* map = NULL;
size_t type = request->ebpf_map_definition.type;
UNREFERENCED_PARAMETER(reply_length);
if (type >= RTL_COUNT_OF(ebpf_map_function_tables)) {
return EBPF_ERROR_INVALID_PARAMETER;
}
@ -532,7 +538,8 @@ Done:
ebpf_error_code_t
ebpf_core_protocol_map_lookup_element(
_In_ const ebpf_operation_map_lookup_element_request_t* request,
_Inout_ ebpf_operation_map_lookup_element_reply_t* reply)
_Inout_ ebpf_operation_map_lookup_element_reply_t* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
ebpf_core_map_t* map = NULL;
@ -553,7 +560,7 @@ ebpf_core_protocol_map_lookup_element(
goto Done;
}
if (reply->header.length <
if (reply_length <
(RTL_OFFSET_OF(ebpf_operation_map_lookup_element_reply_t, value) + map->ebpf_map_definition.value_size)) {
retval = EBPF_ERROR_INVALID_PARAMETER;
goto Done;
@ -573,13 +580,11 @@ Done:
}
ebpf_error_code_t
ebpf_core_protocol_map_update_element(
_In_ const epf_operation_map_update_element_request_t* request, _Inout_ void* reply)
ebpf_core_protocol_map_update_element(_In_ const epf_operation_map_update_element_request_t* request)
{
ebpf_error_code_t retval;
ebpf_core_map_t* map = NULL;
size_t type;
UNREFERENCED_PARAMETER(reply);
map = _ebpf_core_find_map_entry(request->handle);
if (!map) {
@ -603,13 +608,11 @@ Done:
}
ebpf_error_code_t
ebpf_core_protocol_map_delete_element(
_In_ const ebpf_operation_map_delete_element_request_t* request, _Inout_ void* reply)
ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_element_request_t* request)
{
ebpf_error_code_t retval;
ebpf_core_map_t* map = NULL;
size_t type;
UNREFERENCED_PARAMETER(reply);
map = _ebpf_core_find_map_entry(request->handle);
if (!map) {
@ -633,7 +636,9 @@ Done:
ebpf_error_code_t
ebpf_core_protocol_map_get_next_key(
_In_ const ebpf_operation_map_next_key_request_t* request, _Inout_ ebpf_operation_map_next_key_reply_t* reply)
_In_ const ebpf_operation_map_next_key_request_t* request,
_Inout_ ebpf_operation_map_next_key_reply_t* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
ebpf_core_map_t* map = NULL;
@ -666,7 +671,7 @@ ebpf_core_protocol_map_get_next_key(
}
next_key = reply->next_key;
if (reply->header.length <
if (reply_length <
(RTL_OFFSET_OF(ebpf_operation_map_next_key_reply_t, next_key) + map->ebpf_map_definition.key_size)) {
retval = EBPF_ERROR_INVALID_PARAMETER;
goto Done;
@ -681,10 +686,11 @@ Done:
ebpf_error_code_t
ebpf_core_protocol_enumerate_maps(
_In_ const struct _ebpf_operation_enumerate_maps_request* request,
_Inout_ struct _ebpf_operation_enumerate_maps_reply* reply)
_Inout_ struct _ebpf_operation_enumerate_maps_reply* reply,
uint16_t reply_length)
{
uint64_t next_handle = request->previous_handle;
UNREFERENCED_PARAMETER(reply);
UNREFERENCED_PARAMETER(reply_length);
// Start search from begining
if (next_handle == UINT64_MAX) {
@ -714,10 +720,12 @@ ebpf_core_protocol_enumerate_maps(
ebpf_error_code_t
ebpf_core_protocol_query_map_definition(
_In_ const struct _ebpf_operation_query_map_definition_request* request,
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply)
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval = EBPF_ERROR_INVALID_HANDLE;
ebpf_core_map_t* map = NULL;
UNREFERENCED_PARAMETER(reply_length);
map = _ebpf_core_find_map_entry(request->handle);
if (map) {
@ -729,14 +737,12 @@ ebpf_core_protocol_query_map_definition(
}
ebpf_error_code_t
ebpf_core_protocol_update_map_pinning(
_In_ const struct _ebpf_operation_update_map_pinning_request* request, _Inout_ void* reply)
ebpf_core_protocol_update_map_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
{
ebpf_error_code_t retval;
ebpf_core_pinning_entry_t* entry = NULL;
const uint8_t* name = request->name;
size_t name_length = request->header.length - RTL_OFFSET_OF(ebpf_operation_update_map_pinning_request_t, name);
UNREFERENCED_PARAMETER(reply);
if (name_length == 0) {
retval = EBPF_ERROR_INVALID_PARAMETER;
@ -774,11 +780,13 @@ Done:
ebpf_error_code_t
ebpf_core_protocol_lookup_map_pinning(
_In_ const struct _ebpf_operation_lookup_map_pinning_request* request,
_Inout_ struct _ebpf_operation_lookup_map_pinning_reply* reply)
_Inout_ struct _ebpf_operation_lookup_map_pinning_reply* reply,
uint16_t reply_length)
{
ebpf_error_code_t retval;
const uint8_t* name = request->name;
size_t name_length = request->header.length - RTL_OFFSET_OF(ebpf_operation_lookup_map_pinning_request_t, name);
UNREFERENCED_PARAMETER(reply_length);
if (name_length == 0) {
retval = EBPF_ERROR_INVALID_PARAMETER;
@ -830,37 +838,37 @@ ebpf_core_interpreter_helper_resolver(void* context, uint32_t helper_id)
ebpf_protocol_handler_t EbpfProtocolHandlers[EBPF_OPERATION_LOOKUP_MAP_PINNING + 1] = {
{NULL, sizeof(struct _ebpf_operation_eidence_request)}, // EBPF_OPERATION_EVIDENCE
{ebpf_core_protocol_resolve_helper,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_resolve_helper,
sizeof(struct _ebpf_operation_resolve_helper_request),
sizeof(struct _ebpf_operation_resolve_helper_reply)},
{ebpf_core_protocol_resolve_map,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_resolve_map,
sizeof(struct _ebpf_operation_resolve_map_request),
sizeof(struct _ebpf_operation_resolve_map_reply)},
{ebpf_core_protocol_load_code,
{(ebpf_error_code_t(__cdecl*)(const void*))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,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_create_map,
sizeof(struct _ebpf_operation_create_map_request),
sizeof(struct _ebpf_operation_create_map_reply)},
{ebpf_core_protocol_map_lookup_element,
{(ebpf_error_code_t(__cdecl*)(const void*))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},
{ebpf_core_protocol_map_get_next_key,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_map_get_next_key,
RTL_OFFSET_OF(ebpf_operation_map_next_key_request_t, previous_key),
sizeof(ebpf_operation_map_next_key_reply_t)},
{ebpf_core_protocol_enumerate_maps,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_enumerate_maps,
sizeof(struct _ebpf_operation_enumerate_maps_request),
sizeof(struct _ebpf_operation_enumerate_maps_reply)},
{ebpf_core_protocol_query_map_definition,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_query_map_definition,
sizeof(struct _ebpf_operation_query_map_definition_request),
sizeof(struct _ebpf_operation_query_map_definition_reply)},
{ebpf_core_protocol_update_map_pinning, sizeof(struct _ebpf_operation_update_map_pinning_request), 0},
{ebpf_core_protocol_lookup_map_pinning,
{(ebpf_error_code_t(__cdecl*)(const void*))ebpf_core_protocol_lookup_map_pinning,
sizeof(struct _ebpf_operation_lookup_map_pinning_request),
sizeof(struct _ebpf_operation_lookup_map_pinning_reply)},
};

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

@ -159,6 +159,14 @@ Done:
void
ebpf_hash_table_destroy(ebpf_hash_table_t* hash_table)
{
RTL_AVL_TABLE* table = (RTL_AVL_TABLE*)hash_table;
for (;;) {
uint8_t* entry;
entry = RtlEnumerateGenericTableAvl(table, TRUE);
if (!entry)
break;
RtlDeleteElementGenericTableAvl(table, entry);
}
ExFreePool(hash_table);
}
@ -173,7 +181,7 @@ ebpf_hash_table_lookup(ebpf_hash_table_t* hash_table, const uint8_t* key, uint8_
entry = RtlLookupElementGenericTableAvl(table, (uint8_t*)key);
if (!entry) {
if (entry) {
*value = entry + key_size;
retval = EBPF_ERROR_SUCCESS;
} else {
@ -202,7 +210,7 @@ ebpf_hash_table_update(ebpf_hash_table_t* hash_table, const uint8_t* key, const
temp = ebpf_allocate(temp_size, EBPF_MEMORY_NO_EXECUTE);
if (!temp) {
retval = EBPF_ERROR_INVALID_PARAMETER;
retval = EBPF_ERROR_OUT_OF_RESOURCES;
goto Done;
}

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

@ -16,7 +16,7 @@ typedef enum _ubpd_pool_tag
void*
ubpf_alloc(size_t size, size_t count)
{
void* memory = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, EBPF_POOL_TAG);
void* memory = ExAllocatePool2(POOL_FLAG_NON_PAGED, size * count, EBPF_POOL_TAG);
if (memory) {
memset(memory, 0, size * count);

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

@ -282,7 +282,7 @@ EbpfCoreEvtIoDeviceControl(
goto Done;
}
if (!EbpfProtocolHandlers[user_request->id].protocol_handler) {
if (!EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_no_reply) {
status = STATUS_INVALID_PARAMETER;
goto Done;
}
@ -309,8 +309,14 @@ EbpfCoreEvtIoDeviceControl(
user_reply = output_buffer;
}
status = ebpf_error_code_to_ntstatus(
EbpfProtocolHandlers[user_request->id].protocol_handler(user_request, user_reply));
if (EbpfProtocolHandlers[user_request->id].minimum_reply_size == 0) {
status = ebpf_error_code_to_ntstatus(
EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_no_reply(user_request));
} else {
status = ebpf_error_code_to_ntstatus(
EbpfProtocolHandlers[user_request->id].dispatch.protocol_handler_with_reply(
user_request, user_reply, (uint16_t)actual_output_length));
}
// Fill out the rest of the out buffer after processing the input
// buffer.

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

@ -36,106 +36,133 @@ Environment:
#include <guiddef.h>
// XDP like hook
typedef struct _xdp_md {
uint64_t data; /* 0 8 */
uint64_t data_end; /* 8 8 */
uint64_t data_meta; /* 16 8 */
typedef struct _xdp_md
{
uint64_t data; /* 0 8 */
uint64_t data_end; /* 8 8 */
uint64_t data_meta; /* 16 8 */
/* size: 12, cachelines: 1, members: 3 */
/* last cacheline: 12 bytes */
/* size: 12, cachelines: 1, members: 3 */
/* last cacheline: 12 bytes */
} xdp_md_t;
typedef enum _xdp_action { XDP_PASS = 1, XDP_DROP = 2 } xdp_action_t;
typedef enum _xdp_action
{
XDP_PASS = 1,
XDP_DROP = 2
} xdp_action_t;
// BIND hook
typedef struct _bind_md {
uint64_t app_id_start; // 0,8
uint64_t app_id_end; // 8,8
uint64_t process_id; // 16,8
uint8_t socket_address[16]; // 24,16
uint8_t socket_address_length; // 40,1
uint8_t operation; // 41,1
uint8_t protocol; // 42,1
typedef struct _bind_md
{
uint64_t app_id_start; // 0,8
uint64_t app_id_end; // 8,8
uint64_t process_id; // 16,8
uint8_t socket_address[16]; // 24,16
uint8_t socket_address_length; // 40,1
uint8_t operation; // 41,1
uint8_t protocol; // 42,1
} bind_md_t;
typedef enum _bind_operation {
BIND_OPERATION_BIND, // Entry to bind
BIND_OPERATION_POST_BIND, // After port allocation
BIND_OPERATION_UNBIND, // Release port
typedef enum _bind_operation
{
BIND_OPERATION_BIND, // Entry to bind
BIND_OPERATION_POST_BIND, // After port allocation
BIND_OPERATION_UNBIND, // Release port
} bind_operation_t;
typedef enum _bind_action {
BIND_PERMIT,
BIND_DENY,
BIND_REDIRECT,
typedef enum _bind_action
{
BIND_PERMIT,
BIND_DENY,
BIND_REDIRECT,
} bind_action_t;
typedef DWORD(__stdcall *bind_hook_function)(PVOID);
typedef DWORD(__stdcall* bind_hook_function)(PVOID);
#define RTL_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0]))
// Callout and sublayer GUIDs
// 7c7b3fb9-3331-436a-98e1-b901df457fff
DEFINE_GUID(EBPF_HOOK_SUBLAYER, 0x7c7b3fb9, 0x3331, 0x436a, 0x98, 0xe1, 0xb9,
0x01, 0xdf, 0x45, 0x7f, 0xff);
DEFINE_GUID(EBPF_HOOK_SUBLAYER, 0x7c7b3fb9, 0x3331, 0x436a, 0x98, 0xe1, 0xb9, 0x01, 0xdf, 0x45, 0x7f, 0xff);
// 5a5614e5-6b64-4738-8367-33c6ca07bf8f
DEFINE_GUID(EBPF_HOOK_L2_CALLOUT, 0x5a5614e5, 0x6b64, 0x4738, 0x83, 0x67, 0x33,
0xc6, 0xca, 0x07, 0xbf, 0x8f);
DEFINE_GUID(EBPF_HOOK_L2_CALLOUT, 0x5a5614e5, 0x6b64, 0x4738, 0x83, 0x67, 0x33, 0xc6, 0xca, 0x07, 0xbf, 0x8f);
// c69f4de0-3d80-457d-9aea-75faef42ec12
DEFINE_GUID(EBPF_HOOK_ALE_BIND_REDIRECT_CALLOUT, 0xc69f4de0, 0x3d80, 0x457d,
0x9a, 0xea, 0x75, 0xfa, 0xef, 0x42, 0xec, 0x12);
DEFINE_GUID(
EBPF_HOOK_ALE_BIND_REDIRECT_CALLOUT, 0xc69f4de0, 0x3d80, 0x457d, 0x9a, 0xea, 0x75, 0xfa, 0xef, 0x42, 0xec, 0x12);
// 732acf94-7319-4fed-97d0-41d3a18f3fa1
DEFINE_GUID(EBPF_HOOK_ALE_RESOURCE_ALLOCATION_CALLOUT, 0x732acf94, 0x7319,
0x4fed, 0x97, 0xd0, 0x41, 0xd3, 0xa1, 0x8f, 0x3f, 0xa1);
DEFINE_GUID(
EBPF_HOOK_ALE_RESOURCE_ALLOCATION_CALLOUT,
0x732acf94,
0x7319,
0x4fed,
0x97,
0xd0,
0x41,
0xd3,
0xa1,
0x8f,
0x3f,
0xa1);
// d5792949-2d91-4023-9993-3f3dd9d54b2b
DEFINE_GUID(EBPF_HOOK_ALE_RESOURCE_RELEASE_CALLOUT, 0xd5792949, 0x2d91, 0x4023,
0x99, 0x93, 0x3f, 0x3d, 0xd9, 0xd5, 0x4b, 0x2b);
DEFINE_GUID(
EBPF_HOOK_ALE_RESOURCE_RELEASE_CALLOUT, 0xd5792949, 0x2d91, 0x4023, 0x99, 0x93, 0x3f, 0x3d, 0xd9, 0xd5, 0x4b, 0x2b);
static void 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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output);
static void
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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output);
static void ebpf_hook_resource_allocation_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output);
static void
ebpf_hook_resource_allocation_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output);
static void ebpf_hook_resource_release_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output);
static void
ebpf_hook_resource_release_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output);
static void ebpf_hook_no_op_flow_delete(_In_ uint16_t layer_id,
_In_ uint32_t fwpm_callout_id,
_In_ uint64_t flow_context);
static void
ebpf_hook_no_op_flow_delete(_In_ uint16_t layer_id, _In_ uint32_t fwpm_callout_id, _In_ uint64_t flow_context);
static NTSTATUS
ebpf_hook_no_op_notify(_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID *filter_key,
_Inout_ const FWPS_FILTER *filter);
ebpf_hook_no_op_notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID* filter_key,
_Inout_ const FWPS_FILTER* filter);
typedef struct _ebpf_wfp_callout_state {
const GUID *callout_guid;
const GUID *layer_guid;
FWPS_CALLOUT_CLASSIFY_FN3 classify_fn;
FWPS_CALLOUT_NOTIFY_FN3 notify_fn;
FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 delete_fn;
wchar_t *name;
wchar_t *description;
FWP_ACTION_TYPE filter_action_type;
uint32_t assigned_callout_id;
typedef struct _ebpf_wfp_callout_state
{
const GUID* callout_guid;
const GUID* layer_guid;
FWPS_CALLOUT_CLASSIFY_FN3 classify_fn;
FWPS_CALLOUT_NOTIFY_FN3 notify_fn;
FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 delete_fn;
wchar_t* name;
wchar_t* description;
FWP_ACTION_TYPE filter_action_type;
uint32_t assigned_callout_id;
} ebpf_wfp_callout_state_t;
static ebpf_wfp_callout_state_t _ebpf_wfp_callout_state[] = {
@ -175,89 +202,96 @@ static ebpf_wfp_callout_state_t _ebpf_wfp_callout_state[] = {
static HANDLE _fwp_engine_handle;
static NTSTATUS
ebpf_hook_register_wfp_callout(_Inout_ ebpf_wfp_callout_state_t *callout_state,
_Inout_ void *device_object)
ebpf_hook_register_wfp_callout(_Inout_ ebpf_wfp_callout_state_t* callout_state, _Inout_ void* device_object)
/* ++
This function registers callouts and filters.
-- */
{
NTSTATUS status = STATUS_SUCCESS;
NTSTATUS status = STATUS_SUCCESS;
FWPS_CALLOUT callout_register_state = {0};
FWPM_CALLOUT callout_add_state = {0};
FWPS_CALLOUT callout_register_state = {0};
FWPM_CALLOUT callout_add_state = {0};
FWPM_DISPLAY_DATA display_data = {0};
FWPM_FILTER filter = {0};
FWPM_DISPLAY_DATA display_data = {0};
FWPM_FILTER filter = {0};
BOOLEAN was_callout_registered = FALSE;
BOOLEAN was_callout_registered = FALSE;
callout_register_state.calloutKey = *callout_state->callout_guid;
callout_register_state.classifyFn = callout_state->classify_fn;
callout_register_state.notifyFn = callout_state->notify_fn;
callout_register_state.flowDeleteFn = callout_state->delete_fn;
callout_register_state.flags = 0;
callout_register_state.calloutKey = *callout_state->callout_guid;
callout_register_state.classifyFn = callout_state->classify_fn;
callout_register_state.notifyFn = callout_state->notify_fn;
callout_register_state.flowDeleteFn = callout_state->delete_fn;
callout_register_state.flags = 0;
status = FwpsCalloutRegister(device_object, &callout_register_state,
&callout_state->assigned_callout_id);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpsCalloutRegister for %S failed with error %.2X\n",
callout_state->name, status));
goto Exit;
}
was_callout_registered = TRUE;
status = FwpsCalloutRegister(device_object, &callout_register_state, &callout_state->assigned_callout_id);
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpsCalloutRegister for %S failed with error %.2X\n",
callout_state->name,
status));
goto Exit;
}
was_callout_registered = TRUE;
display_data.name = callout_state->name;
display_data.description = callout_state->description;
display_data.name = callout_state->name;
display_data.description = callout_state->description;
callout_add_state.calloutKey = *callout_state->callout_guid;
callout_add_state.displayData = display_data;
callout_add_state.applicableLayer = *callout_state->layer_guid;
callout_add_state.calloutKey = *callout_state->callout_guid;
callout_add_state.displayData = display_data;
callout_add_state.applicableLayer = *callout_state->layer_guid;
status = FwpmCalloutAdd(_fwp_engine_handle, &callout_add_state, NULL, NULL);
status = FwpmCalloutAdd(_fwp_engine_handle, &callout_add_state, NULL, NULL);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmCalloutAdd for %S failed with error %.2X\n",
callout_state->name, status));
goto Exit;
}
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmCalloutAdd for %S failed with error %.2X\n",
callout_state->name,
status));
goto Exit;
}
filter.layerKey = *callout_state->layer_guid;
filter.displayData.name = callout_state->name;
filter.displayData.description = callout_state->description;
filter.action.type = callout_state->filter_action_type;
filter.action.calloutKey = *callout_state->callout_guid;
filter.filterCondition = NULL;
filter.numFilterConditions = 0;
filter.subLayerKey = EBPF_HOOK_SUBLAYER;
filter.weight.type = FWP_EMPTY; // auto-weight.
filter.layerKey = *callout_state->layer_guid;
filter.displayData.name = callout_state->name;
filter.displayData.description = callout_state->description;
filter.action.type = callout_state->filter_action_type;
filter.action.calloutKey = *callout_state->callout_guid;
filter.filterCondition = NULL;
filter.numFilterConditions = 0;
filter.subLayerKey = EBPF_HOOK_SUBLAYER;
filter.weight.type = FWP_EMPTY; // auto-weight.
status = FwpmFilterAdd(_fwp_engine_handle, &filter, NULL, NULL);
status = FwpmFilterAdd(_fwp_engine_handle, &filter, NULL, NULL);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmFilterAdd for %S failed with error %.2X\n",
callout_state->name, status));
goto Exit;
}
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmFilterAdd for %S failed with error %.2X\n",
callout_state->name,
status));
goto Exit;
}
Exit:
if (!NT_SUCCESS(status)) {
if (was_callout_registered) {
FwpsCalloutUnregisterById(callout_state->assigned_callout_id);
callout_state->assigned_callout_id = 0;
if (!NT_SUCCESS(status)) {
if (was_callout_registered) {
FwpsCalloutUnregisterById(callout_state->assigned_callout_id);
callout_state->assigned_callout_id = 0;
}
}
}
return status;
return status;
}
NTSTATUS
ebpf_hook_register_callouts(_Inout_ void *device_object)
ebpf_hook_register_callouts(_Inout_ void* device_object)
/* ++
This function registers dynamic callouts and filters that
@ -267,307 +301,306 @@ ebpf_hook_register_callouts(_Inout_ void *device_object)
-- */
{
NTSTATUS status = STATUS_SUCCESS;
FWPM_SUBLAYER ebpf_hook_sub_layer;
NTSTATUS status = STATUS_SUCCESS;
FWPM_SUBLAYER ebpf_hook_sub_layer;
BOOLEAN is_engined_opened = FALSE;
BOOLEAN is_in_transaction = FALSE;
BOOLEAN is_engined_opened = FALSE;
BOOLEAN is_in_transaction = FALSE;
FWPM_SESSION session = {0};
FWPM_SESSION session = {0};
size_t index;
size_t index;
if (_fwp_engine_handle != NULL) {
// already registered
goto Exit;
}
if (_fwp_engine_handle != NULL) {
// already registered
goto Exit;
}
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &session,
&_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmEngineOpen failed with error %.2X\n", status));
goto Exit;
}
is_engined_opened = TRUE;
status = FwpmTransactionBegin(_fwp_engine_handle, 0);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmTransactionBegin failed with error %.2X\n",
status));
goto Exit;
}
is_in_transaction = TRUE;
RtlZeroMemory(&ebpf_hook_sub_layer, sizeof(FWPM_SUBLAYER));
ebpf_hook_sub_layer.subLayerKey = EBPF_HOOK_SUBLAYER;
ebpf_hook_sub_layer.displayData.name = L"EBPF hook Sub-Layer";
ebpf_hook_sub_layer.displayData.description =
L"Sub-Layer for use by EBPF callouts";
ebpf_hook_sub_layer.flags = 0;
ebpf_hook_sub_layer.weight = FWP_EMPTY; // auto-weight.;
status = FwpmSubLayerAdd(_fwp_engine_handle, &ebpf_hook_sub_layer, NULL);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmSubLayerAdd failed with error %.2X\n", status));
goto Exit;
}
for (index = 0; index < RTL_COUNT_OF(_ebpf_wfp_callout_state); index++) {
status = ebpf_hook_register_wfp_callout(&_ebpf_wfp_callout_state[index],
device_object);
status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
KdPrintEx(
(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Ebpf_wfp: FwpmEngineOpen failed with error %.2X\n", status));
goto Exit;
}
is_engined_opened = TRUE;
status = FwpmTransactionBegin(_fwp_engine_handle, 0);
if (!NT_SUCCESS(status)) {
KdPrintEx((
DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Ebpf_wfp: FwpmTransactionBegin failed with error %.2X\n", status));
goto Exit;
}
is_in_transaction = TRUE;
RtlZeroMemory(&ebpf_hook_sub_layer, sizeof(FWPM_SUBLAYER));
ebpf_hook_sub_layer.subLayerKey = EBPF_HOOK_SUBLAYER;
ebpf_hook_sub_layer.displayData.name = L"EBPF hook Sub-Layer";
ebpf_hook_sub_layer.displayData.description = L"Sub-Layer for use by EBPF callouts";
ebpf_hook_sub_layer.flags = 0;
ebpf_hook_sub_layer.weight = FWP_EMPTY; // auto-weight.;
status = FwpmSubLayerAdd(_fwp_engine_handle, &ebpf_hook_sub_layer, NULL);
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Ebpf_wfp: FwpmSubLayerAdd failed with error %.2X\n", status));
goto Exit;
}
for (index = 0; index < RTL_COUNT_OF(_ebpf_wfp_callout_state); index++) {
status = ebpf_hook_register_wfp_callout(&_ebpf_wfp_callout_state[index], device_object);
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"Ebpf_wfp: ebpf_hook_register_wfp_callout failed for %S with "
"error %.2X\n",
_ebpf_wfp_callout_state[index].name, status));
goto Exit;
_ebpf_wfp_callout_state[index].name,
status));
goto Exit;
}
}
}
status = FwpmTransactionCommit(_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmTransactionCommit failed with error %.2X\n",
status));
goto Exit;
}
is_in_transaction = FALSE;
status = FwpmTransactionCommit(_fwp_engine_handle);
if (!NT_SUCCESS(status)) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID,
DPFLTR_INFO_LEVEL,
"Ebpf_wfp: FwpmTransactionCommit failed with error %.2X\n",
status));
goto Exit;
}
is_in_transaction = FALSE;
Exit:
if (!NT_SUCCESS(status)) {
if (is_in_transaction) {
FwpmTransactionAbort(_fwp_engine_handle);
_Analysis_assume_lock_not_held_(
_fwp_engine_handle); // Potential leak if "FwpmTransactionAbort" fails
if (!NT_SUCCESS(status)) {
if (is_in_transaction) {
FwpmTransactionAbort(_fwp_engine_handle);
_Analysis_assume_lock_not_held_(_fwp_engine_handle); // Potential leak if "FwpmTransactionAbort" fails
}
if (is_engined_opened) {
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
}
}
if (is_engined_opened) {
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
}
}
return status;
return status;
}
void ebpf_hook_unregister_callouts(void) {
size_t index;
if (_fwp_engine_handle != NULL) {
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
void
ebpf_hook_unregister_callouts(void)
{
size_t index;
if (_fwp_engine_handle != NULL) {
FwpmEngineClose(_fwp_engine_handle);
_fwp_engine_handle = NULL;
for (index = 0; index < RTL_COUNT_OF(_ebpf_wfp_callout_state); index++) {
FwpsCalloutUnregisterById(
_ebpf_wfp_callout_state[index].assigned_callout_id);
for (index = 0; index < RTL_COUNT_OF(_ebpf_wfp_callout_state); index++) {
FwpsCalloutUnregisterById(_ebpf_wfp_callout_state[index].assigned_callout_id);
}
}
}
}
static void 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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output)
static void
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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output)
/* ++
A simple classify function at the WFP L2 MAC layer.
-- */
{
FWP_ACTION_TYPE action = FWP_ACTION_PERMIT;
UNREFERENCED_PARAMETER(incoming_fixed_values);
UNREFERENCED_PARAMETER(incoming_metadata_values);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
NET_BUFFER_LIST *nbl = (NET_BUFFER_LIST *)layer_data;
NET_BUFFER *net_buffer = NULL;
uint8_t *packet_buffer;
uint32_t result = 0;
FWP_ACTION_TYPE action = FWP_ACTION_PERMIT;
UNREFERENCED_PARAMETER(incoming_fixed_values);
UNREFERENCED_PARAMETER(incoming_metadata_values);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
NET_BUFFER_LIST* nbl = (NET_BUFFER_LIST*)layer_data;
NET_BUFFER* net_buffer = NULL;
uint8_t* packet_buffer;
uint32_t result = 0;
if (nbl == NULL) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Null nbl \n"));
goto done;
}
net_buffer = NET_BUFFER_LIST_FIRST_NB(nbl);
if (net_buffer == NULL) {
KdPrintEx(
(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "net_buffer not present\n"));
// nothing to do
goto done;
}
packet_buffer = NdisGetDataBuffer(net_buffer, net_buffer->DataLength, NULL,
sizeof(uint16_t), 0);
xdp_md_t ctx = {(uint64_t)packet_buffer,
(uint64_t)packet_buffer + net_buffer->DataLength};
if (ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx, &result) ==
EBPF_ERROR_SUCCESS) {
switch (result) {
case XDP_PASS:
action = FWP_ACTION_PERMIT;
break;
case XDP_DROP:
action = FWP_ACTION_BLOCK;
break;
if (nbl == NULL) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Null nbl \n"));
goto done;
}
net_buffer = NET_BUFFER_LIST_FIRST_NB(nbl);
if (net_buffer == NULL) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "net_buffer not present\n"));
// nothing to do
goto done;
}
packet_buffer = NdisGetDataBuffer(net_buffer, net_buffer->DataLength, NULL, sizeof(uint16_t), 0);
xdp_md_t ctx = {(uint64_t)packet_buffer, (uint64_t)packet_buffer + net_buffer->DataLength};
if (ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_XDP, &ctx, &result) == EBPF_ERROR_SUCCESS) {
switch (result) {
case XDP_PASS:
action = FWP_ACTION_PERMIT;
break;
case XDP_DROP:
action = FWP_ACTION_BLOCK;
break;
}
}
}
done:
classify_output->actionType = action;
return;
classify_output->actionType = action;
return;
}
static void ebpf_hook_resource_allocation_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output)
void
ebpf_hook_resource_truncate_appid(bind_md_t* ctx)
{
wchar_t* last_separator = (wchar_t*)ctx->app_id_start;
for (wchar_t* position = (wchar_t*)ctx->app_id_start; position < (wchar_t*)ctx->app_id_end; position++) {
if (*position == '\\') {
last_separator = position;
}
}
if (*last_separator == '\\') {
last_separator++;
}
ctx->app_id_start = (uint64_t)last_separator;
}
static void
ebpf_hook_resource_allocation_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output)
/* ++
A simple classify function at the WFP Resource Allocation layer.
-- */
{
SOCKADDR_IN addr = {AF_INET};
uint32_t result;
bind_md_t ctx;
SOCKADDR_IN addr = {AF_INET};
uint32_t result;
bind_md_t ctx;
UNREFERENCED_PARAMETER(layer_data);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
UNREFERENCED_PARAMETER(layer_data);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
addr.sin_port =
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_PORT]
.value.uint16;
addr.sin_addr.S_un.S_addr =
incoming_fixed_values
->incomingValue
[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_ADDRESS]
.value.uint32;
addr.sin_port =
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_PORT].value.uint16;
addr.sin_addr.S_un.S_addr =
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_ADDRESS].value.uint32;
ctx.process_id = incoming_metadata_values->processId;
memcpy(&ctx.socket_address, &addr, sizeof(addr));
ctx.operation = BIND_OPERATION_BIND;
ctx.protocol =
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_PROTOCOL]
.value.uint8;
ctx.process_id = incoming_metadata_values->processId;
memcpy(&ctx.socket_address, &addr, sizeof(addr));
ctx.operation = BIND_OPERATION_BIND;
ctx.protocol = incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_PROTOCOL].value.uint8;
ctx.app_id_start =
(uint64_t)incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_ALE_APP_ID]
.value.byteBlob->data;
ctx.app_id_end =
ctx.app_id_start +
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_ALE_APP_ID]
.value.byteBlob->size;
ctx.app_id_start = (uint64_t)incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_ALE_APP_ID]
.value.byteBlob->data;
ctx.app_id_end =
ctx.app_id_start +
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_ALE_APP_ID].value.byteBlob->size;
if (ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_BIND, &ctx, &result) ==
EBPF_ERROR_SUCCESS) {
switch (result) {
case BIND_PERMIT:
case BIND_REDIRECT:
classify_output->actionType = FWP_ACTION_PERMIT;
break;
case BIND_DENY:
classify_output->actionType = FWP_ACTION_BLOCK;
ebpf_hook_resource_truncate_appid(&ctx);
if (ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_BIND, &ctx, &result) == EBPF_ERROR_SUCCESS) {
switch (result) {
case BIND_PERMIT:
case BIND_REDIRECT:
classify_output->actionType = FWP_ACTION_PERMIT;
break;
case BIND_DENY:
classify_output->actionType = FWP_ACTION_BLOCK;
}
}
}
return;
return;
}
static void ebpf_hook_resource_release_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT *classify_output)
static void
ebpf_hook_resource_release_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_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output)
/* ++
A simple classify function at the WFP Resource Release layer.
-- */
{
SOCKADDR_IN addr = {AF_INET};
uint32_t result;
bind_md_t ctx;
SOCKADDR_IN addr = {AF_INET};
uint32_t result;
bind_md_t ctx;
UNREFERENCED_PARAMETER(layer_data);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
UNREFERENCED_PARAMETER(layer_data);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flow_context);
addr.sin_port =
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_PORT]
.value.uint16;
addr.sin_addr.S_un.S_addr =
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_ADDRESS]
.value.uint32;
addr.sin_port = incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_PORT].value.uint16;
addr.sin_addr.S_un.S_addr =
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_LOCAL_ADDRESS].value.uint32;
ctx.process_id = incoming_metadata_values->processId;
memcpy(&ctx.socket_address, &addr, sizeof(addr));
ctx.operation = BIND_OPERATION_UNBIND;
ctx.protocol =
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_PROTOCOL]
.value.uint8;
ctx.process_id = incoming_metadata_values->processId;
memcpy(&ctx.socket_address, &addr, sizeof(addr));
ctx.operation = BIND_OPERATION_UNBIND;
ctx.protocol = incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_IP_PROTOCOL].value.uint8;
ctx.app_id_start =
(uint64_t)incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_ALE_APP_ID]
.value.byteBlob->data;
ctx.app_id_end =
ctx.app_id_start +
incoming_fixed_values
->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_ALE_APP_ID]
.value.byteBlob->size;
ctx.app_id_start = (uint64_t)incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_ALE_APP_ID]
.value.byteBlob->data;
ctx.app_id_end =
ctx.app_id_start +
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_RESOURCE_RELEASE_V4_ALE_APP_ID].value.byteBlob->size;
ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_BIND, &ctx, &result);
ebpf_hook_resource_truncate_appid(&ctx);
ebpf_core_invoke_hook(EBPF_PROGRAM_TYPE_BIND, &ctx, &result);
classify_output->actionType = FWP_ACTION_PERMIT;
classify_output->actionType = FWP_ACTION_PERMIT;
return;
return;
}
static NTSTATUS
ebpf_hook_no_op_notify(_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID *filter_key,
_Inout_ const FWPS_FILTER *filter) {
UNREFERENCED_PARAMETER(callout_notification_type);
UNREFERENCED_PARAMETER(filter_key);
UNREFERENCED_PARAMETER(filter);
ebpf_hook_no_op_notify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE callout_notification_type,
_In_ const GUID* filter_key,
_Inout_ const FWPS_FILTER* filter)
{
UNREFERENCED_PARAMETER(callout_notification_type);
UNREFERENCED_PARAMETER(filter_key);
UNREFERENCED_PARAMETER(filter);
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
static void ebpf_hook_no_op_flow_delete(_In_ uint16_t layer_id,
_In_ uint32_t fwpm_callout_id,
_In_ uint64_t flow_context)
static void
ebpf_hook_no_op_flow_delete(_In_ uint16_t layer_id, _In_ uint32_t fwpm_callout_id, _In_ uint64_t flow_context)
/* ++
This is the flowDeleteFn function of the L2 callout.
-- */
{
UNREFERENCED_PARAMETER(layer_id);
UNREFERENCED_PARAMETER(fwpm_callout_id);
UNREFERENCED_PARAMETER(flow_context);
return;
UNREFERENCED_PARAMETER(layer_id);
UNREFERENCED_PARAMETER(fwpm_callout_id);
UNREFERENCED_PARAMETER(flow_context);
return;
}

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

@ -90,7 +90,13 @@ GlueDeviceIoControl(
user_reply->id = user_request->id;
*lpBytesReturned = user_reply->length;
}
retval = EbpfProtocolHandlers[request_id].protocol_handler(user_request, user_reply);
if (EbpfProtocolHandlers[request_id].minimum_reply_size == 0) {
retval = EbpfProtocolHandlers[request_id].dispatch.protocol_handler_no_reply(user_request);
} else {
retval = EbpfProtocolHandlers[request_id].dispatch.protocol_handler_with_reply(
user_request, user_reply, static_cast<uint16_t>(nOutBufferSize));
}
if (retval != EBPF_ERROR_SUCCESS) {
switch (retval) {
case EBPF_ERROR_OUT_OF_RESOURCES:
@ -370,9 +376,7 @@ uint32_t
get_bind_count_for_pid(ebpf_handle_t handle, uint64_t pid)
{
process_entry_t entry{};
REQUIRE(
ebpf_api_map_lookup_element(handle, sizeof(pid), (uint8_t*)&pid, sizeof(entry), (uint8_t*)&entry) ==
ERROR_SUCCESS);
ebpf_api_map_lookup_element(handle, sizeof(pid), (uint8_t*)&pid, sizeof(entry), (uint8_t*)&entry);
return entry.count;
}
@ -530,9 +534,9 @@ TEST_CASE("bindmonitor-interpret", "[bindmonitor_interpret]")
emulate_unbind(fake_pid, "fake_app_1");
REQUIRE(get_bind_count_for_pid(map_handles[0], fake_pid) == 0);
// Unbind a port we don't own
emulate_unbind(fake_pid, "fake_app_1");
REQUIRE(get_bind_count_for_pid(map_handles[0], fake_pid) == 0);
// Bind from two apps to test enumeration
REQUIRE(emulate_bind(fake_pid, "fake_app_1") == ebpf::BIND_PERMIT);
REQUIRE(get_bind_count_for_pid(map_handles[0], fake_pid) == 1);
fake_pid = 54321;
REQUIRE(emulate_bind(fake_pid, "fake_app_2") == ebpf::BIND_PERMIT);

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

@ -10,70 +10,84 @@
#include "ebpf.h"
typedef struct _process_entry {
uint32_t count;
uint8_t name[64];
typedef struct _process_entry
{
uint32_t count;
uint8_t name[64];
} process_entry_t;
#pragma clang section data = "maps"
bpf_map_def_t process_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(process_entry_t),
.max_entries = 1024};
bpf_map_def_t process_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_HASH,
.key_size = sizeof(uint64_t),
.value_size = sizeof(process_entry_t),
.max_entries = 1024};
bpf_map_def_t limits_map = {.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
bpf_map_def_t limits_map = {
.size = sizeof(bpf_map_def_t),
.type = EBPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1};
inline void copy_app_id(process_entry_t *entry, uint64_t start_index,
char *begin, char *end) {
uint64_t index = 0;
for (index = start_index; index < start_index + 16; index++) {
entry->name[index] = (begin + index < end) ? begin[index] : 0;
}
inline void
copy_app_id(process_entry_t* entry, uint64_t start_index, char* begin, char* end)
{
uint64_t index = 0;
for (index = start_index; index < start_index + 16; index++) {
entry->name[index] = (begin + index < end) ? begin[index] : 0;
}
}
#pragma clang section text = "bind"
int BindMonitor(bind_md_t *ctx) {
uint64_t key = ctx->process_id;
uint32_t limit_key = 0;
uint32_t *limit = ebpf_map_lookup_elem(&limits_map, &limit_key);
if (!limit || *limit == 0) {
return BIND_PERMIT;
}
process_entry_t *entry = ebpf_map_lookup_elem(&process_map, &key);
if (!entry) {
process_entry_t value = {0};
// To work around a limitation in eBPF verifier, copy the string
// in blocks of 16 bytes. Copying all 64 bytes triggers a verification
// failure.
copy_app_id(&value, 0, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 16, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 32, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 48, ctx->app_id_start, ctx->app_id_end);
ebpf_map_update_element(&process_map, &key, &value, 0);
entry = ebpf_map_lookup_elem(&process_map, &key);
}
switch (ctx->operation) {
case BIND_OPERATION_BIND:
if (entry->count >= *limit) {
return BIND_DENY;
int
BindMonitor(bind_md_t* ctx)
{
uint64_t key = ctx->process_id;
uint32_t limit_key = 0;
uint32_t* limit = ebpf_map_lookup_elem(&limits_map, &limit_key);
if (!limit || *limit == 0) {
return BIND_PERMIT;
}
entry->count++;
break;
case BIND_OPERATION_UNBIND:
if (entry->count > 0)
entry->count--;
break;
default:
break;
}
process_entry_t* entry = ebpf_map_lookup_elem(&process_map, &key);
// Only add entries on bind
if ((!entry) && (ctx->operation == BIND_OPERATION_BIND)) {
process_entry_t value = {0};
// To work around a limitation in eBPF verifier, copy the string
// in blocks of 16 bytes. Copying all 64 bytes triggers a verification
// failure.
copy_app_id(&value, 0, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 16, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 32, ctx->app_id_start, ctx->app_id_end);
copy_app_id(&value, 48, ctx->app_id_start, ctx->app_id_end);
ebpf_map_update_element(&process_map, &key, &value, 0);
entry = ebpf_map_lookup_elem(&process_map, &key);
}
if (!entry) {
return BIND_PERMIT;
}
return BIND_PERMIT;
switch (ctx->operation) {
case BIND_OPERATION_BIND:
if (entry->count >= *limit) {
return BIND_DENY;
}
entry->count++;
break;
case BIND_OPERATION_UNBIND:
if (entry->count > 0)
entry->count--;
break;
default:
break;
}
if (entry->count == 0) {
ebpf_map_delete_elem(&process_map, &key);
}
return BIND_PERMIT;
}

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

@ -13,94 +13,114 @@ typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
uint16_t ntohs(uint16_t us) { return us << 8 | us >> 8; }
uint16_t
ntohs(uint16_t us)
{
return us << 8 | us >> 8;
}
typedef struct _xdp_md {
void *data;
void *data_end;
uint64_t data_meta;
typedef struct _xdp_md
{
void* data;
void* data_end;
uint64_t data_meta;
} xdp_md_t;
typedef struct _bind_md {
char *app_id_start;
char *app_id_end;
uint64_t process_id;
uint8_t socket_address[16];
uint8_t socket_address_length;
uint8_t operation;
uint8_t protocol;
typedef struct _bind_md
{
char* app_id_start;
char* app_id_end;
uint64_t process_id;
uint8_t socket_address[16];
uint8_t socket_address_length;
uint8_t operation;
uint8_t protocol;
} bind_md_t;
typedef enum _bind_operation {
BIND_OPERATION_BIND, // Entry to bind
BIND_OPERATION_POST_BIND, // After port allocation
BIND_OPERATION_UNBIND, // Release port
typedef enum _bind_operation
{
BIND_OPERATION_BIND, // Entry to bind
BIND_OPERATION_POST_BIND, // After port allocation
BIND_OPERATION_UNBIND, // Release port
} bind_operation_t;
typedef enum _bind_action {
BIND_PERMIT,
BIND_DENY,
BIND_REDIRECT,
typedef enum _bind_action
{
BIND_PERMIT,
BIND_DENY,
BIND_REDIRECT,
} bind_action_t;
typedef struct _IPV4_HEADER {
union {
uint8_t VersionAndHeaderLength; // Version and header length.
struct {
uint8_t HeaderLength : 4;
uint8_t Version : 4;
typedef struct _IPV4_HEADER
{
union
{
uint8_t VersionAndHeaderLength; // Version and header length.
struct
{
uint8_t HeaderLength : 4;
uint8_t Version : 4;
};
};
};
union {
uint8_t TypeOfServiceAndEcnField; // Type of service & ECN (RFC 3168).
struct {
uint8_t EcnField : 2;
uint8_t TypeOfService : 6;
union
{
uint8_t TypeOfServiceAndEcnField; // Type of service & ECN (RFC 3168).
struct
{
uint8_t EcnField : 2;
uint8_t TypeOfService : 6;
};
};
};
uint16_t TotalLength; // Total length of datagram.
uint16_t Identification;
union {
uint16_t FlagsAndOffset; // Flags and fragment offset.
struct {
uint16_t DontUse1 : 5; // High bits of fragment offset.
uint16_t MoreFragments : 1;
uint16_t DontFragment : 1;
uint16_t Reserved : 1;
uint16_t DontUse2 : 8; // Low bits of fragment offset.
uint16_t TotalLength; // Total length of datagram.
uint16_t Identification;
union
{
uint16_t FlagsAndOffset; // Flags and fragment offset.
struct
{
uint16_t DontUse1 : 5; // High bits of fragment offset.
uint16_t MoreFragments : 1;
uint16_t DontFragment : 1;
uint16_t Reserved : 1;
uint16_t DontUse2 : 8; // Low bits of fragment offset.
};
};
};
uint8_t TimeToLive;
uint8_t Protocol;
uint16_t HeaderChecksum;
uint32_t SourceAddress;
uint32_t DestinationAddress;
uint8_t TimeToLive;
uint8_t Protocol;
uint16_t HeaderChecksum;
uint32_t SourceAddress;
uint32_t DestinationAddress;
} IPV4_HEADER, *PIPV4_HEADER;
typedef struct UDP_HEADER_ {
uint16_t srcPort;
uint16_t destPort;
uint16_t length;
uint16_t checksum;
typedef struct UDP_HEADER_
{
uint16_t srcPort;
uint16_t destPort;
uint16_t length;
uint16_t checksum;
} UDP_HEADER;
typedef struct _bpf_map_def {
uint32_t size;
uint32_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
typedef struct _bpf_map_def
{
uint32_t size;
uint32_t type;
uint32_t key_size;
uint32_t value_size;
uint32_t max_entries;
} bpf_map_def_t;
typedef enum _ebpf_map_type {
EBPF_MAP_TYPE_UNSPECIFIED = 0,
EBPF_MAP_TYPE_HASH = 1,
EBPF_MAP_TYPE_ARRAY = 2,
typedef enum _ebpf_map_type
{
EBPF_MAP_TYPE_UNSPECIFIED = 0,
EBPF_MAP_TYPE_HASH = 1,
EBPF_MAP_TYPE_ARRAY = 2,
} ebpf_map_type_t;
typedef void *(*ebpf_map_lookup_elem_t)(void *map, void *key);
typedef void* (*ebpf_map_lookup_elem_t)(bpf_map_def_t* map, void* key);
#define ebpf_map_lookup_elem ((ebpf_map_lookup_elem_t)1)
typedef void (*ebpf_map_update_element_t)(void *map, void *key, void *data,
uint64_t flags);
typedef void (*ebpf_map_update_element_t)(bpf_map_def_t* map, void* key, void* data, uint64_t flags);
#define ebpf_map_update_element ((ebpf_map_update_element_t)2)
typedef void (*ebpf_map_delete_elem_t)(bpf_map_def_t* map, void* key);
#define ebpf_map_delete_elem ((ebpf_map_delete_elem_t)3)

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

@ -4,6 +4,7 @@
*/
#include <iostream>
#include <string>
#include <windows.h>
#include "ebpf_api.h"
@ -32,6 +33,13 @@ load(int argc, char** argv)
ebpf_api_free_error_message(error_message);
return 1;
}
result = ebpf_api_attach_program(program, ebpf_program_type::EBPF_PROGRAM_TYPE_BIND);
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);
@ -82,8 +90,8 @@ stats(int argc, char** argv)
fprintf(stderr, "Failed to look up eBPF map entry: %d\n", result);
return 1;
}
printf("%lld\t%d\t%s\n", pid, process_entry.count, process_entry.name);
std::wstring name(reinterpret_cast<wchar_t*>(process_entry.name), process_entry.count / 2);
printf("%lld\t%d\t%S\n", pid, process_entry.count, reinterpret_cast<wchar_t*>(process_entry.name));
result = ebpf_api_map_next_key(
map, sizeof(uint64_t), reinterpret_cast<uint8_t*>(&pid), reinterpret_cast<uint8_t*>(&pid));
};