Merged PR 4226082: Fix bugs so that portquota demo works
Fix bugs so that portquota demo works
This commit is contained in:
Родитель
09bfd2063d
Коммит
366e41afdd
|
@ -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));
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче