Instrument eBPF for Windows platform layer (#647)
* Instrument eBPF Core with tracing Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Родитель
65f3a545a5
Коммит
260a8d77dc
|
@ -188,3 +188,10 @@ This application tests various XDP functionalities. It has the following tests:
|
|||
2. Load the test eBPF program by running the following commands: `netsh`, `ebpf`, `add program reflect_packet.o xdp` and note the ID.
|
||||
3. From a remote host, run xdp_tests.exe and in `--remote-ip` parameter pass an IPv4 or IPv6 address of an Ethernet-like interface on the system under test in string format.
|
||||
4. Unload the program from system under test by running `delete program <id>` on the netsh prompt, where <id> is the ID noted above.
|
||||
|
||||
### Capturing traces
|
||||
eBPF for Windows uses ETW for tracing. To capture a trace use the following commands:
|
||||
1) Start tracing: ```wpr.exe -start ebpfforwindows.wprp -filemode```
|
||||
2) Run the scenario to be traced.
|
||||
3) Stop tracing: ```wpr.exe -stop ebpfforwindows.etl```
|
||||
4) Convert the traces to a human readable version: ```netsh trace convert ebpfforwindows.etl ebpfforwindows.csv csv```
|
||||
|
|
|
@ -22,7 +22,7 @@ GUID ebpf_general_helper_function_interface_id = {/* 8d2a1d3f-9ce6-473d-b48e-17a
|
|||
static ebpf_pinning_table_t* _ebpf_core_map_pinning_table = NULL;
|
||||
|
||||
// Assume enabled until we can query it.
|
||||
static ebpf_code_integrity_state_t _ebpf_core_code_integrity_state = EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE;
|
||||
static ebpf_code_integrity_state_t _ebpf_core_code_integrity_state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
|
||||
|
||||
// Map related helpers.
|
||||
static void*
|
||||
|
@ -85,6 +85,10 @@ ebpf_core_initiate()
|
|||
if (return_value != EBPF_SUCCESS)
|
||||
goto Done;
|
||||
|
||||
return_value = ebpf_trace_initiate();
|
||||
if (return_value != EBPF_SUCCESS)
|
||||
goto Done;
|
||||
|
||||
return_value = ebpf_epoch_initiate();
|
||||
if (return_value != EBPF_SUCCESS)
|
||||
goto Done;
|
||||
|
@ -160,20 +164,27 @@ ebpf_core_terminate()
|
|||
// Verify that all ebpf_object_t objects have been freed.
|
||||
ebpf_object_tracking_terminate();
|
||||
|
||||
ebpf_trace_terminate();
|
||||
|
||||
ebpf_platform_terminate();
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_load_code(_In_ const ebpf_operation_load_code_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* program = NULL;
|
||||
uint8_t* code = NULL;
|
||||
size_t code_length = 0;
|
||||
|
||||
if (request->code_type == EBPF_CODE_NATIVE) {
|
||||
if (_ebpf_core_code_integrity_state == EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE) {
|
||||
if (_ebpf_core_code_integrity_state == EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE) {
|
||||
retval = EBPF_BLOCKED_BY_POLICY;
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_CORE,
|
||||
"code_type == EBPF_CODE_NATIVE blocked by EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE");
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +202,7 @@ _ebpf_core_protocol_load_code(_In_ const ebpf_operation_load_code_request_t* req
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -200,6 +211,7 @@ _ebpf_core_protocol_resolve_helper(
|
|||
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_program_t* program = NULL;
|
||||
ebpf_result_t return_value = EBPF_SUCCESS;
|
||||
size_t count_of_helpers =
|
||||
|
@ -245,7 +257,7 @@ Done:
|
|||
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
ebpf_free(request_helper_ids);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -254,6 +266,7 @@ _ebpf_core_protocol_resolve_map(
|
|||
_Inout_ struct _ebpf_operation_resolve_map_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_program_t* program = NULL;
|
||||
uint32_t count_of_maps =
|
||||
(request->header.length - EBPF_OFFSET_OF(ebpf_operation_resolve_map_request_t, map_handle)) /
|
||||
|
@ -292,7 +305,7 @@ _ebpf_core_protocol_resolve_map(
|
|||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -301,6 +314,7 @@ _ebpf_core_protocol_create_map(
|
|||
_Inout_ struct _ebpf_operation_create_map_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
UNREFERENCED_PARAMETER(reply_length);
|
||||
|
@ -327,7 +341,7 @@ _ebpf_core_protocol_create_map(
|
|||
Done:
|
||||
ebpf_object_release_reference(map_object);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -336,6 +350,7 @@ _ebpf_core_protocol_create_program(
|
|||
_Inout_ ebpf_operation_create_program_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* program = NULL;
|
||||
ebpf_program_parameters_t parameters;
|
||||
|
@ -384,7 +399,7 @@ _ebpf_core_protocol_create_program(
|
|||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -393,6 +408,7 @@ _ebpf_core_protocol_map_find_element(
|
|||
_Inout_ ebpf_operation_map_find_element_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
size_t value_length;
|
||||
|
@ -427,12 +443,13 @@ _ebpf_core_protocol_map_find_element(
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_map_update_element(_In_ const epf_operation_map_update_element_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
size_t value_length;
|
||||
|
@ -460,13 +477,14 @@ _ebpf_core_protocol_map_update_element(_In_ const epf_operation_map_update_eleme
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_map_update_element_with_handle(
|
||||
_In_ const ebpf_operation_map_update_element_with_handle_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
size_t key_length;
|
||||
|
@ -493,12 +511,13 @@ _ebpf_core_protocol_map_update_element_with_handle(
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_element_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
size_t key_length;
|
||||
|
@ -516,7 +535,7 @@ _ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_elem
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -525,6 +544,7 @@ _ebpf_core_protocol_map_get_next_key(
|
|||
_Inout_ ebpf_operation_map_get_next_key_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_map_t* map = NULL;
|
||||
size_t previous_key_length;
|
||||
|
@ -557,12 +577,13 @@ _ebpf_core_protocol_map_get_next_key(
|
|||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_get_next_handle(ebpf_handle_t previous_handle, ebpf_object_type_t type, ebpf_handle_t* next_handle)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_object_t* previous_object = NULL;
|
||||
ebpf_object_t* next_object = NULL;
|
||||
|
@ -586,7 +607,7 @@ Done:
|
|||
ebpf_object_release_reference(previous_object);
|
||||
ebpf_object_release_reference(next_object);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -595,8 +616,9 @@ _ebpf_core_protocol_get_next_map(
|
|||
_Inout_ struct _ebpf_operation_get_next_map_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
UNREFERENCED_PARAMETER(reply_length);
|
||||
return _ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_MAP, &reply->next_handle);
|
||||
EBPF_RETURN_RESULT(_ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_MAP, &reply->next_handle));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -605,8 +627,9 @@ _ebpf_core_protocol_get_next_program(
|
|||
_Inout_ struct _ebpf_operation_get_next_program_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
UNREFERENCED_PARAMETER(reply_length);
|
||||
return _ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_PROGRAM, &reply->next_handle);
|
||||
EBPF_RETURN_RESULT(_ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_PROGRAM, &reply->next_handle));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -615,12 +638,13 @@ _ebpf_core_protocol_query_map_definition(
|
|||
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
UNREFERENCED_PARAMETER(reply_length);
|
||||
|
||||
ebpf_object_t* object;
|
||||
ebpf_result_t result = ebpf_reference_object_by_handle(request->handle, EBPF_OBJECT_MAP, &object);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_map_t* map = (ebpf_map_t*)object;
|
||||
|
@ -629,7 +653,7 @@ _ebpf_core_protocol_query_map_definition(
|
|||
|
||||
ebpf_object_release_reference(object);
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -638,6 +662,7 @@ _ebpf_core_protocol_query_program_info(
|
|||
_Inout_ struct _ebpf_operation_query_program_info_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* program = NULL;
|
||||
size_t required_reply_length;
|
||||
|
@ -678,12 +703,13 @@ _ebpf_core_protocol_query_program_info(
|
|||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
const ebpf_utf8_string_t path = {
|
||||
(uint8_t*)request->path,
|
||||
|
@ -708,7 +734,7 @@ _ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_
|
|||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)object);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -717,6 +743,7 @@ _ebpf_core_protocol_get_pinned_object(
|
|||
_Inout_ struct _ebpf_operation_get_pinning_reply* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_object_t* object = NULL;
|
||||
const ebpf_utf8_string_t path = {
|
||||
|
@ -736,13 +763,14 @@ _ebpf_core_protocol_get_pinned_object(
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)object);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_link_program(
|
||||
_In_ const ebpf_operation_link_program_request_t* request, _Inout_ ebpf_operation_link_program_reply_t* reply)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* program = NULL;
|
||||
ebpf_link_t* link = NULL;
|
||||
|
@ -773,12 +801,13 @@ Done:
|
|||
}
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
ebpf_object_release_reference((ebpf_object_t*)link);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_link_t* link = NULL;
|
||||
|
||||
|
@ -791,24 +820,26 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ
|
|||
|
||||
Done:
|
||||
ebpf_object_release_reference((ebpf_object_t*)link);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_close_handle(_In_ const ebpf_operation_close_handle_request_t* request)
|
||||
{
|
||||
return ebpf_handle_close(request->handle);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(ebpf_handle_close(request->handle));
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
_ebpf_core_protocol_get_ec_function(
|
||||
_In_ const ebpf_operation_get_ec_function_request_t* request, _Inout_ ebpf_operation_get_ec_function_reply_t* reply)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (request->function != EBPF_EC_FUNCTION_LOG)
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
|
||||
reply->address = (uint64_t)ebpf_log_function;
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
// Get helper info for a program or program type. This is used by the jitter/verifier,
|
||||
|
@ -820,6 +851,7 @@ _ebpf_core_protocol_get_program_info(
|
|||
_Inout_ ebpf_operation_get_program_info_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* program = NULL;
|
||||
ebpf_program_parameters_t program_parameters = {0};
|
||||
|
@ -866,7 +898,7 @@ _ebpf_core_protocol_get_program_info(
|
|||
Done:
|
||||
ebpf_program_free_program_info(program_info);
|
||||
ebpf_object_release_reference((ebpf_object_t*)program);
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -959,6 +991,7 @@ _ebpf_core_protocol_get_map_info(
|
|||
_In_ ebpf_operation_get_map_info_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
uint16_t entry_count = 0;
|
||||
ebpf_pinning_entry_t* pinning_entries = NULL;
|
||||
|
@ -992,7 +1025,7 @@ Exit:
|
|||
ebpf_free(map_info);
|
||||
ebpf_pinning_entries_release(entry_count, pinning_entries);
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1025,7 +1058,8 @@ _ebpf_core_protocol_get_map_handle_by_id(
|
|||
_Out_ ebpf_operation_get_handle_by_id_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
return _get_handle_by_id(EBPF_OBJECT_MAP, request, reply, reply_length);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(_get_handle_by_id(EBPF_OBJECT_MAP, request, reply, reply_length));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1034,7 +1068,8 @@ _ebpf_core_protocol_get_program_handle_by_id(
|
|||
_Out_ ebpf_operation_get_handle_by_id_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
return _get_handle_by_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(_get_handle_by_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1057,7 +1092,7 @@ _get_next_id(
|
|||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ebpf_object_get_next_id(request->start_id, type, &reply->next_id);
|
||||
EBPF_RETURN_RESULT(ebpf_object_get_next_id(request->start_id, type, &reply->next_id));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1066,7 +1101,8 @@ _ebpf_core_protocol_get_next_link_id(
|
|||
_Out_ ebpf_operation_get_next_id_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
return _get_next_id(EBPF_OBJECT_LINK, request, reply, reply_length);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_LINK, request, reply, reply_length));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1075,7 +1111,8 @@ _ebpf_core_protocol_get_next_map_id(
|
|||
_Out_ ebpf_operation_get_next_id_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
return _get_next_id(EBPF_OBJECT_MAP, request, reply, reply_length);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_MAP, request, reply, reply_length));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1084,7 +1121,8 @@ _ebpf_core_protocol_get_next_program_id(
|
|||
_Out_ ebpf_operation_get_next_id_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
return _get_next_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length));
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1093,6 +1131,7 @@ _ebpf_core_protocol_get_next_pinned_program_path(
|
|||
_Out_ ebpf_operation_get_next_pinned_path_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_utf8_string_t start_path;
|
||||
ebpf_utf8_string_t next_path;
|
||||
|
||||
|
@ -1109,12 +1148,13 @@ _ebpf_core_protocol_get_next_pinned_program_path(
|
|||
reply->header.length =
|
||||
(uint16_t)next_path.length + EBPF_OFFSET_OF(ebpf_operation_get_next_pinned_path_reply_t, next_path);
|
||||
}
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_core_protocol_bind_map(_In_ const ebpf_operation_bind_map_request_t* request)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result;
|
||||
ebpf_program_t* program = NULL;
|
||||
ebpf_map_t* map = NULL;
|
||||
|
@ -1138,7 +1178,7 @@ Done:
|
|||
if (map) {
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
}
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
|
@ -1147,6 +1187,7 @@ _ebpf_core_protocol_get_object_info(
|
|||
_Out_ ebpf_operation_get_object_info_reply_t* reply,
|
||||
uint16_t reply_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
uint16_t info_size = reply_length - FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info);
|
||||
|
||||
ebpf_object_t* object;
|
||||
|
@ -1174,7 +1215,7 @@ _ebpf_core_protocol_get_object_info(
|
|||
reply->header.length = FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info) + info_size;
|
||||
}
|
||||
ebpf_object_release_reference(object);
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -1184,6 +1225,7 @@ _ebpf_core_protocol_wait_for_map_change(
|
|||
uint16_t output_buffer_length,
|
||||
_In_ void* async_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
UNREFERENCED_PARAMETER(reply);
|
||||
UNREFERENCED_PARAMETER(output_buffer_length);
|
||||
|
||||
|
@ -1196,7 +1238,7 @@ _ebpf_core_protocol_wait_for_map_change(
|
|||
result = ebpf_map_wait_for_update(map, async_context);
|
||||
|
||||
ebpf_object_release_reference((ebpf_object_t*)map);
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
static void*
|
||||
|
|
|
@ -43,26 +43,28 @@ _ebpf_link_free(ebpf_object_t* object)
|
|||
ebpf_result_t
|
||||
ebpf_link_create(ebpf_link_t** link)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
*link = ebpf_epoch_allocate(sizeof(ebpf_link_t));
|
||||
if (*link == NULL)
|
||||
return EBPF_NO_MEMORY;
|
||||
EBPF_RETURN_RESULT(EBPF_NO_MEMORY);
|
||||
|
||||
memset(*link, 0, sizeof(ebpf_link_t));
|
||||
|
||||
ebpf_result_t result = ebpf_object_initialize(&(*link)->object, EBPF_OBJECT_LINK, _ebpf_link_free, NULL);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
ebpf_epoch_free(link);
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_lock_create(&(*link)->attach_lock);
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_link_initialize(
|
||||
ebpf_link_t* link, ebpf_attach_type_t attach_type, const uint8_t* context_data, size_t context_data_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_extension_data_t* provider_data;
|
||||
ebpf_attach_provider_data_t* attach_provider_data;
|
||||
|
@ -91,11 +93,15 @@ ebpf_link_initialize(
|
|||
NULL);
|
||||
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "No providers support attach type", attach_type);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ((provider_data->version != EBPF_ATTACH_PROVIDER_DATA_VERSION) || (!provider_data->data) ||
|
||||
(provider_data->size != sizeof(ebpf_attach_provider_data_t))) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "Provider version not supported", attach_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -105,12 +111,13 @@ ebpf_link_initialize(
|
|||
link->attach_type = attach_type;
|
||||
|
||||
Exit:
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value = EBPF_SUCCESS;
|
||||
ebpf_lock_state_t state;
|
||||
state = ebpf_lock_lock(&link->attach_lock);
|
||||
|
@ -121,6 +128,11 @@ ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
|
|||
|
||||
const ebpf_program_type_t* program_type = ebpf_program_type(program);
|
||||
if (memcmp(program_type, &link->program_type, sizeof(link->program_type)) != 0) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_LINK,
|
||||
"Attach failed due to incorrect program type",
|
||||
*program_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -130,12 +142,13 @@ ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
|
|||
|
||||
Done:
|
||||
ebpf_lock_unlock(&link->attach_lock, state);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_link_detach_program(_Inout_ ebpf_link_t* link)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_program_t* program;
|
||||
|
||||
|
@ -153,16 +166,21 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link)
|
|||
|
||||
ebpf_extension_unload(link->extension_client_context);
|
||||
ebpf_free(link->client_data.data);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_link_instance_invoke(
|
||||
_In_ const void* extension_client_binding_context, _In_ void* program_context, _Out_ uint32_t* result)
|
||||
{
|
||||
// No function entry exit traces as this is a high volume function.
|
||||
ebpf_result_t return_value;
|
||||
ebpf_link_t* link = (ebpf_link_t*)ebpf_extension_get_client_context(extension_client_binding_context);
|
||||
|
||||
if (link == NULL) {
|
||||
GUID npi_id = ebpf_extension_get_provider_guid(extension_client_binding_context);
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_LINK, "Client context is null", npi_id);
|
||||
return_value = EBPF_FAILED;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -174,17 +192,18 @@ _ebpf_link_instance_invoke(
|
|||
ebpf_epoch_exit();
|
||||
|
||||
Exit:
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_link_get_info(
|
||||
_In_ const ebpf_link_t* link, _Out_writes_to_(*info_size, *info_size) uint8_t* buffer, _Inout_ uint16_t* info_size)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
struct bpf_link_info* info = (struct bpf_link_info*)buffer;
|
||||
|
||||
if (*info_size < sizeof(*info)) {
|
||||
return EBPF_INSUFFICIENT_BUFFER;
|
||||
EBPF_RETURN_RESULT(EBPF_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
info->id = link->object.id;
|
||||
|
@ -195,5 +214,5 @@ ebpf_link_get_info(
|
|||
info->attach_type = BPF_ATTACH_TYPE_UNSPEC; // TODO(#223): get actual integer, and also return attach_type_uuid
|
||||
|
||||
*info_size = sizeof(*info);
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -1340,6 +1340,7 @@ _ebpf_map_signal_async_contexts(_In_ ebpf_core_map_t* map)
|
|||
static void
|
||||
_ebpf_map_delete(_In_ ebpf_object_t* object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_map_t* map = (ebpf_map_t*)object;
|
||||
|
||||
if (map->inner_map_template != NULL) {
|
||||
|
@ -1348,6 +1349,7 @@ _ebpf_map_delete(_In_ ebpf_object_t* object)
|
|||
ebpf_free(map->name.value);
|
||||
_ebpf_map_signal_async_contexts(map);
|
||||
ebpf_map_function_tables[map->ebpf_map_definition.type].delete_map(map);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -1357,6 +1359,7 @@ ebpf_map_create(
|
|||
ebpf_handle_t inner_map_handle,
|
||||
_Outptr_ ebpf_map_t** ebpf_map)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_map_t* local_map = NULL;
|
||||
ebpf_object_t* inner_map_template_object = NULL;
|
||||
ebpf_map_type_t type = ebpf_map_definition->type;
|
||||
|
@ -1373,17 +1376,32 @@ ebpf_map_create(
|
|||
break;
|
||||
}
|
||||
|
||||
if ((type >= EBPF_COUNT_OF(ebpf_map_function_tables)) || (map_name->length >= BPF_OBJ_NAME_LEN)) {
|
||||
if (type >= EBPF_COUNT_OF(ebpf_map_function_tables)) {
|
||||
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Unsupported map type", type);
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (map_name->length >= BPF_OBJ_NAME_LEN) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Map name too long", map_name->length);
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (!ebpf_map_function_tables[type].create_map) {
|
||||
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Unsupported map type", type);
|
||||
result = EBPF_OPERATION_NOT_SUPPORTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (local_map_definition.size != sizeof(local_map_definition)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Unsupported map definition size",
|
||||
local_map_definition.size,
|
||||
sizeof(local_map_definition));
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -1392,6 +1410,8 @@ ebpf_map_create(
|
|||
local_map_definition.type == BPF_MAP_TYPE_HASH_OF_MAPS) {
|
||||
if (inner_map_handle == ebpf_handle_invalid) {
|
||||
// Must have a valid inner_map_handle.
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Map in map must have a valid inner_map_handle");
|
||||
result = EBPF_INVALID_FD;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -1435,7 +1455,7 @@ Exit:
|
|||
ebpf_epoch_free(local_map);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -1447,12 +1467,25 @@ ebpf_map_find_entry(
|
|||
_Out_writes_(value_size) uint8_t* value,
|
||||
int flags)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
uint8_t* return_value = NULL;
|
||||
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!(flags & EBPF_MAP_FLAG_HELPER) && (value_size != map->ebpf_map_definition.value_size)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map value size",
|
||||
value_size,
|
||||
map->ebpf_map_definition.value_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -1461,6 +1494,8 @@ ebpf_map_find_entry(
|
|||
|
||||
// Disallow reads to prog array maps from this helper call for now.
|
||||
if (type == BPF_MAP_TYPE_PROG_ARRAY) {
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Find not supported on BPF_MAP_TYPE_PROG_ARRAY");
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -1501,19 +1536,29 @@ ebpf_map_find_entry(
|
|||
ebpf_result_t
|
||||
ebpf_map_associate_program(_In_ ebpf_map_t* map, _In_ const ebpf_program_t* program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (ebpf_map_function_tables[map->ebpf_map_definition.type].associate_program)
|
||||
return ebpf_map_function_tables[map->ebpf_map_definition.type].associate_program(map, program);
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
_Ret_maybenull_ ebpf_program_t*
|
||||
ebpf_map_get_program_from_entry(_In_ ebpf_map_t* map, size_t key_size, _In_reads_(key_size) const uint8_t* key)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
if (key_size != map->ebpf_map_definition.key_size) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return NULL;
|
||||
}
|
||||
ebpf_map_type_t type = map->ebpf_map_definition.type;
|
||||
if (type != BPF_MAP_TYPE_PROG_ARRAY) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Operation not supported on map", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1533,17 +1578,35 @@ ebpf_map_update_entry(
|
|||
ebpf_map_option_t option,
|
||||
int flags)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
ebpf_result_t result;
|
||||
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!(flags & EBPF_MAP_FLAG_HELPER) && (value_size != map->ebpf_map_definition.value_size)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map value size",
|
||||
value_size,
|
||||
map->ebpf_map_definition.value_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if ((ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry == NULL) ||
|
||||
(ebpf_map_function_tables[map->ebpf_map_definition.type].find_entry == NULL)) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"ebpf_map_update_entry not supported on map",
|
||||
map->ebpf_map_definition.type);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -1567,11 +1630,23 @@ ebpf_map_update_entry_with_handle(
|
|||
uintptr_t value_handle,
|
||||
ebpf_map_option_t option)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
if (key_size != map->ebpf_map_definition.key_size) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry_with_handle == NULL) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"ebpf_map_update_entry_with_handle not supported on map",
|
||||
map->ebpf_map_definition.type);
|
||||
return EBPF_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
return ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry_with_handle(
|
||||
|
@ -1581,7 +1656,14 @@ ebpf_map_update_entry_with_handle(
|
|||
ebpf_result_t
|
||||
ebpf_map_delete_entry(_In_ ebpf_map_t* map, size_t key_size, _In_reads_(key_size) const uint8_t* key, int flags)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
ebpf_result_t result = ebpf_map_function_tables[map->ebpf_map_definition.type].delete_entry(map, key);
|
||||
|
@ -1598,7 +1680,14 @@ ebpf_map_next_key(
|
|||
_In_reads_opt_(key_size) const uint8_t* previous_key,
|
||||
_Out_writes_(key_size) uint8_t* next_key)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
if (key_size != map->ebpf_map_definition.key_size) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"Incorrect map key size",
|
||||
key_size,
|
||||
map->ebpf_map_definition.key_size);
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
}
|
||||
return ebpf_map_function_tables[map->ebpf_map_definition.type].next_key(map, previous_key, next_key);
|
||||
|
@ -1608,9 +1697,16 @@ ebpf_result_t
|
|||
ebpf_map_get_info(
|
||||
_In_ const ebpf_map_t* map, _Out_writes_to_(*info_size, *info_size) uint8_t* buffer, _Inout_ uint16_t* info_size)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
struct bpf_map_info* info = (struct bpf_map_info*)buffer;
|
||||
|
||||
if (*info_size < sizeof(*info)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_MAP,
|
||||
"ebpf_map_get_info buffer too small",
|
||||
*info_size,
|
||||
sizeof(*info));
|
||||
return EBPF_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,11 +80,13 @@ ebpf_program_terminate()
|
|||
static void
|
||||
_ebpf_program_detach_links(_Inout_ ebpf_program_t* program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
while (!ebpf_list_is_empty(&program->links)) {
|
||||
ebpf_list_entry_t* entry = program->links.Flink;
|
||||
ebpf_object_t* object = CONTAINING_RECORD(entry, ebpf_object_t, object_list_entry);
|
||||
ebpf_link_detach_program((ebpf_link_t*)object);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -93,6 +95,7 @@ _ebpf_program_program_info_provider_changed(
|
|||
_In_ const void* provider_binding_context,
|
||||
_In_opt_ const ebpf_extension_data_t* provider_data)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_program_t* program = (ebpf_program_t*)client_binding_context;
|
||||
uint32_t* provider_helper_function_ids = NULL;
|
||||
|
@ -105,6 +108,11 @@ _ebpf_program_program_info_provider_changed(
|
|||
|
||||
ebpf_program_data_t* program_data = (ebpf_program_data_t*)provider_data->data;
|
||||
if (program_data == NULL) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"An extension cannot have empty program_data",
|
||||
program->parameters.program_type);
|
||||
// An extension cannot have empty program_data.
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -112,20 +120,37 @@ _ebpf_program_program_info_provider_changed(
|
|||
helper_function_addresses = program_data->helper_function_addresses;
|
||||
|
||||
if ((program->provider_helper_function_count > 0) &&
|
||||
(helper_function_addresses->helper_function_count != program->provider_helper_function_count))
|
||||
(helper_function_addresses->helper_function_count != program->provider_helper_function_count)) {
|
||||
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"A program info provider cannot modify helper function count upon reload",
|
||||
program->parameters.program_type);
|
||||
// A program info provider cannot modify helper function count upon reload.
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (helper_function_addresses != NULL) {
|
||||
ebpf_program_info_t* program_info = program_data->program_info;
|
||||
ebpf_helper_function_prototype_t* helper_prototypes = NULL;
|
||||
ebpf_assert(program_info != NULL);
|
||||
if (program_info->count_of_helpers != helper_function_addresses->helper_function_count) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"A program info provider cannot modify helper function count upon reload",
|
||||
program->parameters.program_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
helper_prototypes = program_info->helper_prototype;
|
||||
if (helper_prototypes == NULL) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"program_info->helper_prototype can not be NULL",
|
||||
program->parameters.program_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -169,6 +194,7 @@ _ebpf_program_program_info_provider_changed(
|
|||
Exit:
|
||||
ebpf_free(provider_helper_function_ids);
|
||||
program->program_invalidated = (program->program_info_provider_data == NULL);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,11 +206,11 @@ Exit:
|
|||
static void
|
||||
_ebpf_program_free(ebpf_object_t* object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
size_t index;
|
||||
ebpf_program_t* program = (ebpf_program_t*)object;
|
||||
if (!program) {
|
||||
return;
|
||||
}
|
||||
if (!program)
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
// Detach from all the attach points.
|
||||
_ebpf_program_detach_links(program);
|
||||
|
@ -194,6 +220,7 @@ _ebpf_program_free(ebpf_object_t* object)
|
|||
ebpf_object_release_reference((ebpf_object_t*)program->maps[index]);
|
||||
|
||||
ebpf_epoch_schedule_work_item(program->cleanup_work_item);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
static const ebpf_program_type_t*
|
||||
|
@ -212,6 +239,7 @@ _ebpf_program_get_program_type(_In_ const ebpf_object_t* object)
|
|||
static void
|
||||
_ebpf_program_epoch_free(void* context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_program_t* program = (ebpf_program_t*)context;
|
||||
|
||||
ebpf_lock_destroy(&program->lock);
|
||||
|
@ -242,11 +270,13 @@ _ebpf_program_epoch_free(void* context)
|
|||
|
||||
ebpf_free(program->cleanup_work_item);
|
||||
ebpf_free(program);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
ebpf_program_load_providers(ebpf_program_t* program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
void* provider_binding_context;
|
||||
ebpf_program_data_t* general_helper_program_data = NULL;
|
||||
|
@ -264,16 +294,32 @@ ebpf_program_load_providers(ebpf_program_t* program)
|
|||
&program->general_helper_provider_dispatch_table,
|
||||
NULL);
|
||||
|
||||
if (return_value != EBPF_SUCCESS)
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"Failed to load general helper functions",
|
||||
ebpf_general_helper_function_interface_id);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (program->general_helper_provider_data == NULL) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"program->general_helper_provider_data can not be NULL",
|
||||
ebpf_general_helper_function_interface_id);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
general_helper_program_data = (ebpf_program_data_t*)program->general_helper_provider_data->data;
|
||||
if (general_helper_program_data->helper_function_addresses == NULL) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"general_helper_program_data->helper_function_addresses can not be NULL",
|
||||
ebpf_general_helper_function_interface_id);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -289,15 +335,23 @@ ebpf_program_load_providers(ebpf_program_t* program)
|
|||
NULL,
|
||||
_ebpf_program_program_info_provider_changed);
|
||||
|
||||
if (return_value != EBPF_SUCCESS)
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"Failed to load program information provider",
|
||||
program->parameters.program_type);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
Done:
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_create(ebpf_program_t** program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t retval;
|
||||
ebpf_program_t* local_program;
|
||||
|
||||
|
@ -332,19 +386,33 @@ Done:
|
|||
if (local_program)
|
||||
_ebpf_program_epoch_free(local_program);
|
||||
|
||||
return retval;
|
||||
EBPF_RETURN_RESULT(retval);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_initialize(ebpf_program_t* program, const ebpf_program_parameters_t* program_parameters)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_utf8_string_t local_program_name = {NULL, 0};
|
||||
ebpf_utf8_string_t local_section_name = {NULL, 0};
|
||||
ebpf_utf8_string_t local_file_name = {NULL, 0};
|
||||
|
||||
if ((program->parameters.code_type != EBPF_CODE_NONE) ||
|
||||
(program_parameters->program_name.length >= BPF_OBJ_NAME_LEN)) {
|
||||
if (program->parameters.code_type != EBPF_CODE_NONE) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"ebpf_program_initialize program->parameters.code_type must be EBPF_CODE_NONE",
|
||||
program->parameters.code_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
if (program_parameters->program_name.length >= BPF_OBJ_NAME_LEN) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"Program name must be less than BPF_OBJ_NAME_LEN",
|
||||
program_parameters->program_name.length);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -383,7 +451,7 @@ Done:
|
|||
ebpf_free(local_program_name.value);
|
||||
ebpf_free(local_section_name.value);
|
||||
ebpf_free(local_file_name.value);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
_Ret_notnull_ const ebpf_program_parameters_t*
|
||||
|
@ -401,10 +469,11 @@ ebpf_program_type(_In_ const ebpf_program_t* program)
|
|||
ebpf_result_t
|
||||
ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
// First make sure the map can be associated.
|
||||
ebpf_result_t result = ebpf_map_associate_program(map, program);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_lock_state_t state = ebpf_lock_lock(&program->lock);
|
||||
|
@ -425,12 +494,13 @@ ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map)
|
|||
Done:
|
||||
ebpf_lock_unlock(&program->lock, state);
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t maps_count)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
size_t index;
|
||||
ebpf_map_t** program_maps = ebpf_allocate(maps_count * sizeof(ebpf_map_t*));
|
||||
if (!program_maps)
|
||||
|
@ -446,7 +516,7 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t
|
|||
result = ebpf_map_associate_program(map, program);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
ebpf_free(program_maps);
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,18 +527,24 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t
|
|||
ebpf_object_acquire_reference((ebpf_object_t*)program_maps[index]);
|
||||
}
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_program_load_machine_code(
|
||||
_Inout_ ebpf_program_t* program, _In_ const uint8_t* machine_code, size_t machine_code_size)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
uint8_t* local_machine_code = NULL;
|
||||
ebpf_memory_descriptor_t* local_code_memory_descriptor = NULL;
|
||||
|
||||
if (program->parameters.code_type != EBPF_CODE_NATIVE) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"_ebpf_program_load_machine_code program->parameters.code_type must be EBPF_CODE_NATIVE",
|
||||
program->parameters.code_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -496,12 +572,13 @@ _ebpf_program_load_machine_code(
|
|||
Done:
|
||||
ebpf_unmap_memory(local_code_memory_descriptor);
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_program_register_helpers(ebpf_program_t* program)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
size_t index = 0;
|
||||
ebpf_program_data_t* general_helper_program_data =
|
||||
|
@ -534,23 +611,31 @@ _ebpf_program_register_helpers(ebpf_program_t* program)
|
|||
continue;
|
||||
|
||||
if (ubpf_register(program->code_or_vm.vm, (unsigned int)index, NULL, (void*)helper) < 0) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, "ubpf_register failed", index);
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
static ebpf_result_t
|
||||
_ebpf_program_load_byte_code(
|
||||
_Inout_ ebpf_program_t* program, _In_ const ebpf_instruction_t* instructions, size_t instruction_count)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
char* error_message = NULL;
|
||||
|
||||
if (program->parameters.code_type != EBPF_CODE_EBPF) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"_ebpf_program_load_byte_code program->parameters.code_type must be EBPF_CODE_EBPF",
|
||||
program->parameters.code_type);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -576,6 +661,8 @@ _ebpf_program_load_byte_code(
|
|||
instructions,
|
||||
(uint32_t)(instruction_count * sizeof(ebpf_instruction_t)),
|
||||
&error_message) != 0) {
|
||||
EBPF_LOG_MESSAGE_STRING(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, "ubpf_load failed", error_message);
|
||||
ebpf_free(error_message);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
|
@ -587,13 +674,14 @@ Done:
|
|||
program->code_or_vm.vm = NULL;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_load_code(
|
||||
_Inout_ ebpf_program_t* program, ebpf_code_type_t code_type, _In_ const uint8_t* code, size_t code_size)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
program->parameters.code_type = code_type;
|
||||
if (program->parameters.code_type == EBPF_CODE_NATIVE)
|
||||
|
@ -601,9 +689,16 @@ ebpf_program_load_code(
|
|||
else if (program->parameters.code_type == EBPF_CODE_EBPF)
|
||||
result = _ebpf_program_load_byte_code(
|
||||
program, (const ebpf_instruction_t*)code, code_size / sizeof(ebpf_instruction_t));
|
||||
else
|
||||
else {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"ebpf_program_load_code unknown program->parameters.code_type",
|
||||
program->parameters.code_type);
|
||||
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
return result;
|
||||
}
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
typedef struct _ebpf_program_tail_call_state
|
||||
|
@ -615,6 +710,7 @@ typedef struct _ebpf_program_tail_call_state
|
|||
ebpf_result_t
|
||||
ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
ebpf_result_t result;
|
||||
ebpf_program_tail_call_state_t* state = NULL;
|
||||
result = ebpf_state_load(_ebpf_program_state_index, (uintptr_t*)&state);
|
||||
|
@ -636,6 +732,7 @@ ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program)
|
|||
void
|
||||
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
ebpf_program_tail_call_state_t state = {0};
|
||||
const ebpf_program_t* current_program = program;
|
||||
|
||||
|
@ -684,6 +781,7 @@ static ebpf_result_t
|
|||
_ebpf_program_get_helper_function_address(
|
||||
_In_ const ebpf_program_t* program, const uint32_t helper_function_id, uint64_t* address)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (helper_function_id > EBPF_MAX_GENERAL_HELPER_FUNCTION) {
|
||||
void* function_address;
|
||||
ebpf_result_t return_value;
|
||||
|
@ -691,7 +789,7 @@ _ebpf_program_get_helper_function_address(
|
|||
return_value =
|
||||
ebpf_get_trampoline_function(program->trampoline_table, trampoline_table_index, &function_address);
|
||||
if (return_value != EBPF_SUCCESS)
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
|
||||
*address = (uint64_t)function_address;
|
||||
} else {
|
||||
|
@ -709,13 +807,14 @@ _ebpf_program_get_helper_function_address(
|
|||
*address = general_helper_function_addresses->helper_function_address[helper_function_id];
|
||||
}
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_get_helper_function_addresses(
|
||||
_In_ const ebpf_program_t* program, size_t addresses_count, _Out_writes_(addresses_count) uint64_t* addresses)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
|
||||
if (program->helper_function_count > addresses_count) {
|
||||
|
@ -731,7 +830,7 @@ ebpf_program_get_helper_function_addresses(
|
|||
}
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -740,9 +839,15 @@ ebpf_program_set_helper_function_ids(
|
|||
const size_t helper_function_count,
|
||||
_In_reads_(helper_function_count) const uint32_t* helper_function_ids)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
|
||||
if (program->helper_function_ids != NULL) {
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_PROGRAM,
|
||||
"ebpf_program_set_helper_function_ids - helper function IDs already set");
|
||||
// Helper function IDs already set.
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
|
@ -762,12 +867,13 @@ ebpf_program_set_helper_function_ids(
|
|||
program->helper_function_ids[index] = helper_function_ids[index];
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_program_info_t** program_info)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
ebpf_program_data_t* program_data = NULL;
|
||||
ebpf_program_data_t* general_helper_program_data = NULL;
|
||||
|
@ -845,7 +951,7 @@ Exit:
|
|||
ebpf_program_free_program_info(local_program_info);
|
||||
}
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -860,6 +966,7 @@ ebpf_program_free_program_info(_In_opt_ _Post_invalid_ ebpf_program_info_t* prog
|
|||
void
|
||||
ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* link)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
// Acquire "attach" reference on the link object.
|
||||
ebpf_object_acquire_reference((ebpf_object_t*)link);
|
||||
|
||||
|
@ -869,11 +976,13 @@ ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l
|
|||
ebpf_list_insert_tail(&program->links, &((ebpf_object_t*)link)->object_list_entry);
|
||||
program->link_count++;
|
||||
ebpf_lock_unlock(&program->lock, state);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_program_detach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* link)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
// Remove the link from the attach list.
|
||||
ebpf_lock_state_t state;
|
||||
state = ebpf_lock_lock(&program->lock);
|
||||
|
@ -883,6 +992,7 @@ ebpf_program_detach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l
|
|||
|
||||
// Release the "attach" reference.
|
||||
ebpf_object_release_reference((ebpf_object_t*)link);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -891,9 +1001,10 @@ ebpf_program_get_info(
|
|||
_Out_writes_to_(*info_size, *info_size) uint8_t* buffer,
|
||||
_Inout_ uint16_t* info_size)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
struct bpf_prog_info* info = (struct bpf_prog_info*)buffer;
|
||||
if (*info_size < sizeof(*info)) {
|
||||
return EBPF_INSUFFICIENT_BUFFER;
|
||||
EBPF_RETURN_RESULT(EBPF_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
info->id = program->object.id;
|
||||
|
@ -909,5 +1020,5 @@ ebpf_program_get_info(
|
|||
info->link_count = program->link_count;
|
||||
|
||||
*info_size = sizeof(*info);
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ ebpf_async_terminate()
|
|||
ebpf_assert(ebpf_hash_table_key_count(_ebpf_async_tracker_table) == 0);
|
||||
ebpf_hash_table_destroy(_ebpf_async_tracker_table);
|
||||
_ebpf_async_tracker_table = NULL;
|
||||
EBPF_LOG_EXIT();
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -91,17 +91,15 @@ ebpf_async_cancel(_In_ void* context)
|
|||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_async_tracker_t* tracker = _tracker_from_context(context);
|
||||
if (!tracker) {
|
||||
EBPF_LOG_EXIT();
|
||||
return false;
|
||||
}
|
||||
if (!tracker)
|
||||
EBPF_RETURN_BOOL(false);
|
||||
|
||||
void* cancellation_context = tracker->cancellation_context;
|
||||
void (*on_cancellation)(_In_ void* context) = tracker->on_cancel;
|
||||
if (on_cancellation)
|
||||
on_cancellation(cancellation_context);
|
||||
|
||||
EBPF_LOG_EXIT();
|
||||
return true;
|
||||
EBPF_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -111,16 +109,15 @@ ebpf_async_complete(_In_ void* context, ebpf_result_t result)
|
|||
ebpf_async_tracker_t* tracker = _tracker_from_context(context);
|
||||
if (!tracker) {
|
||||
ebpf_assert(!"Async action was double completed");
|
||||
EBPF_LOG_EXIT();
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
void (*on_complete)(_In_ void* context, ebpf_result_t result) = tracker->on_complete;
|
||||
if (!_remove_tracker(context)) {
|
||||
ebpf_assert(!"Async action was double completed");
|
||||
EBPF_LOG_EXIT();
|
||||
EBPF_RETURN_VOID();
|
||||
return;
|
||||
}
|
||||
if (on_complete)
|
||||
on_complete(context, result);
|
||||
EBPF_LOG_EXIT();
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ _ebpf_epoch_update_thread_state(uint32_t cpu_id, uintptr_t thread_id, int64_t cu
|
|||
ebpf_result_t
|
||||
ebpf_epoch_initiate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value = EBPF_SUCCESS;
|
||||
uint32_t cpu_id;
|
||||
uint32_t cpu_count;
|
||||
|
@ -176,12 +177,13 @@ ebpf_epoch_initiate()
|
|||
|
||||
Error:
|
||||
ebpf_epoch_terminate();
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_epoch_terminate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
uint32_t cpu_id;
|
||||
|
||||
ebpf_free_timer_work_item(_ebpf_flush_timer);
|
||||
|
@ -198,6 +200,7 @@ ebpf_epoch_terminate()
|
|||
_ebpf_epoch_cpu_count = 0;
|
||||
|
||||
ebpf_free_cache_aligned(_ebpf_epoch_cpu_table);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -249,6 +252,8 @@ ebpf_epoch_flush()
|
|||
int64_t released_epoch;
|
||||
ebpf_result_t return_value = _ebpf_epoch_get_release_epoch(&released_epoch);
|
||||
if (return_value == EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_EPOCH, "_ebpf_release_epoch updated", released_epoch);
|
||||
_ebpf_release_epoch = released_epoch;
|
||||
}
|
||||
}
|
||||
|
@ -426,6 +431,11 @@ _ebpf_epoch_get_release_epoch(_Out_ int64_t* release_epoch)
|
|||
uint32_t cpu_id;
|
||||
ebpf_lock_state_t lock_state;
|
||||
ebpf_result_t return_value;
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_VERBOSE,
|
||||
EBPF_TRACELOG_KEYWORD_EPOCH,
|
||||
"Captured value of _ebpf_current_epoch",
|
||||
lowest_epoch);
|
||||
|
||||
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_count; cpu_id++) {
|
||||
ebpf_epoch_state_t* thread_epoch_state = NULL;
|
||||
|
@ -526,6 +536,7 @@ _ebpf_epoch_update_thread_state(uint32_t cpu_id, uintptr_t thread_id, int64_t cu
|
|||
if (enter) {
|
||||
goto Exit;
|
||||
}
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_EPOCH, "Thread state not found on current CPU");
|
||||
|
||||
// If this is an exit call and the current CPU doesn't have the active entry
|
||||
// then scan all CPUs until we find it.
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ebpf_platform.h"
|
||||
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <winmeta.h>
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
ebpf_tracelog_provider,
|
||||
"EbpfForWindowsProvider",
|
||||
// {394f321c-5cf4-404c-aa34-4df1428a7f9c}
|
||||
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_trace_initiate()
|
||||
{
|
||||
TLG_STATUS status = TraceLoggingRegister(ebpf_tracelog_provider);
|
||||
if (status != 0) {
|
||||
return EBPF_NO_MEMORY;
|
||||
} else {
|
||||
return EBPF_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent tail call optimization of the call to TraceLoggingUnregister to resolve verifier stop C4/DD
|
||||
// "An attempt was made to unload a driver without calling EtwUnregister".
|
||||
#pragma optimize("", off)
|
||||
void
|
||||
ebpf_trace_terminate()
|
||||
{
|
||||
TraceLoggingUnregister(ebpf_tracelog_provider);
|
||||
}
|
||||
#pragma optimize("", on)
|
|
@ -140,6 +140,8 @@ ebpf_object_initialize(
|
|||
ebpf_free_object_t free_function,
|
||||
ebpf_object_get_program_type_t get_program_type_function)
|
||||
{
|
||||
EBPF_LOG_MESSAGE_POINTER_ENUM(
|
||||
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object initialized", object, object_type);
|
||||
object->marker = _ebpf_object_marker;
|
||||
object->reference_count = 1;
|
||||
object->type = object_type;
|
||||
|
@ -172,6 +174,9 @@ _Requires_lock_held_(&_ebpf_object_tracking_list_lock) void _ebpf_object_release
|
|||
new_ref_count = ebpf_interlocked_decrement_int32(&object->reference_count);
|
||||
|
||||
if (new_ref_count == 0) {
|
||||
EBPF_LOG_MESSAGE_POINTER_ENUM(
|
||||
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object terminated", object, object->type);
|
||||
|
||||
_ebpf_object_tracking_list_remove(object);
|
||||
object->marker = ~object->marker;
|
||||
object->free_function(object);
|
||||
|
@ -192,6 +197,8 @@ ebpf_object_release_reference(ebpf_object_t* object)
|
|||
new_ref_count = ebpf_interlocked_decrement_int32(&object->reference_count);
|
||||
|
||||
if (new_ref_count == 0) {
|
||||
EBPF_LOG_MESSAGE_POINTER_ENUM(
|
||||
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object terminated", object, object->type);
|
||||
ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock);
|
||||
_ebpf_object_tracking_list_remove(object);
|
||||
ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state);
|
||||
|
|
|
@ -48,6 +48,7 @@ _ebpf_pinning_entry_free(ebpf_pinning_entry_t* pinning_entry)
|
|||
ebpf_result_t
|
||||
ebpf_pinning_table_allocate(ebpf_pinning_table_t** pinning_table)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
*pinning_table = ebpf_allocate(sizeof(ebpf_pinning_table_t));
|
||||
if (*pinning_table == NULL) {
|
||||
|
@ -80,12 +81,13 @@ Done:
|
|||
ebpf_free(*pinning_table);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_pinning_table_free(ebpf_pinning_table_t* pinning_table)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_utf8_string_t* key = NULL;
|
||||
|
||||
|
@ -99,24 +101,26 @@ ebpf_pinning_table_free(ebpf_pinning_table_t* pinning_table)
|
|||
|
||||
ebpf_hash_table_destroy(pinning_table->hash_table);
|
||||
ebpf_free(pinning_table);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_pinning_table_insert(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path, ebpf_object_t* object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_result_t return_value;
|
||||
ebpf_utf8_string_t* new_key;
|
||||
ebpf_pinning_entry_t* new_pinning_entry;
|
||||
|
||||
if (path->length >= EBPF_MAX_PIN_PATH_LENGTH || path->length == 0) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
// Block embedded null terminators
|
||||
for (size_t index = 0; index < path->length; index++) {
|
||||
if (path->value[index] == 0) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,13 +156,17 @@ ebpf_pinning_table_insert(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_s
|
|||
|
||||
Done:
|
||||
_ebpf_pinning_entry_free(new_pinning_entry);
|
||||
if (return_value == EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_UTF8_STRING(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "Pinned object", *path);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_pinning_table_find(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path, ebpf_object_t** object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_result_t return_value;
|
||||
const ebpf_utf8_string_t* existing_key = path;
|
||||
|
@ -175,12 +183,13 @@ ebpf_pinning_table_find(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_str
|
|||
|
||||
ebpf_lock_unlock(&pinning_table->lock, state);
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_pinning_table_delete(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_result_t return_value;
|
||||
const ebpf_utf8_string_t* existing_key = path;
|
||||
|
@ -199,7 +208,10 @@ ebpf_pinning_table_delete(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_s
|
|||
}
|
||||
ebpf_lock_unlock(&pinning_table->lock, state);
|
||||
|
||||
return return_value;
|
||||
if (return_value == EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_UTF8_STRING(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "Unpinned object", *path);
|
||||
}
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -209,6 +221,7 @@ ebpf_pinning_table_enumerate_entries(
|
|||
_Out_ uint16_t* entry_count,
|
||||
_Outptr_result_buffer_maybenull_(*entry_count) ebpf_pinning_entry_t** pinning_entries)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
ebpf_lock_state_t state = 0;
|
||||
bool lock_held = FALSE;
|
||||
|
@ -297,7 +310,7 @@ Exit:
|
|||
*entry_count = local_entry_count;
|
||||
*pinning_entries = local_pinning_entries;
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -307,8 +320,9 @@ ebpf_pinning_table_get_next_path(
|
|||
_In_ const ebpf_utf8_string_t* start_path,
|
||||
_Inout_ ebpf_utf8_string_t* next_path)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if ((pinning_table == NULL) || (start_path == NULL) || (next_path == NULL)) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
const uint8_t* previous_key = (start_path->length == 0) ? NULL : (const uint8_t*)&start_path;
|
||||
|
@ -342,15 +356,16 @@ ebpf_pinning_table_get_next_path(
|
|||
}
|
||||
|
||||
ebpf_lock_unlock(&pinning_table->lock, state);
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_pinning_entries_release(uint16_t entry_count, _In_opt_count_(entry_count) ebpf_pinning_entry_t* pinning_entries)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
uint16_t index;
|
||||
if (!pinning_entries)
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
for (index = 0; index < entry_count; index++) {
|
||||
ebpf_pinning_entry_t* entry = &pinning_entries[index];
|
||||
|
@ -359,4 +374,5 @@ ebpf_pinning_entries_release(uint16_t entry_count, _In_opt_count_(entry_count) e
|
|||
ebpf_object_release_reference(entry->object);
|
||||
}
|
||||
ebpf_free(pinning_entries);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ extern "C"
|
|||
typedef enum _ebpf_code_integrity_state
|
||||
{
|
||||
EBPF_CODE_INTEGRITY_DEFAULT = 0,
|
||||
EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE = 1
|
||||
EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE = 1
|
||||
} ebpf_code_integrity_state_t;
|
||||
|
||||
typedef struct _ebpf_non_preemptible_work_item ebpf_non_preemptible_work_item_t;
|
||||
|
@ -717,6 +717,9 @@ extern "C"
|
|||
void*
|
||||
ebpf_extension_get_client_context(_In_ const void* extension_client_binding_context);
|
||||
|
||||
GUID
|
||||
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context);
|
||||
|
||||
/**
|
||||
* @brief Unload an extension.
|
||||
*
|
||||
|
@ -959,53 +962,217 @@ extern "C"
|
|||
|
||||
TRACELOGGING_DECLARE_PROVIDER(ebpf_tracelog_provider);
|
||||
|
||||
#define EBPF_EVENT_SUCCESS "EbpfSuccess"
|
||||
#define EBPF_EVENT_GENERIC_ERROR "EbpfGenericError"
|
||||
#define EBPF_EVENT_GENERIC_MESSAGE "EbpfGenericMessage"
|
||||
ebpf_result_t
|
||||
ebpf_trace_initiate();
|
||||
|
||||
#define EBPF_LOG_FUNCTION_SUCCESS() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_EVENT_SUCCESS, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
void
|
||||
ebpf_trace_terminate();
|
||||
|
||||
#define EBPF_TRACELOG_EVENT_SUCCESS "EbpfSuccess"
|
||||
#define EBPF_TRACELOG_EVENT_GENERIC_ERROR "EbpfGenericError"
|
||||
#define EBPF_TRACELOG_EVENT_GENERIC_MESSAGE "EbpfGenericMessage"
|
||||
#define EBPF_TRACELOG_EVENT_API_ERROR "EbpfApiError"
|
||||
|
||||
#define EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT 0x1
|
||||
#define EBPF_TRACELOG_KEYWORD_BASE 0x2
|
||||
#define EBPF_TRACELOG_KEYWORD_ERROR 0x4
|
||||
#define EBPF_TRACELOG_KEYWORD_EPOCH 0x8
|
||||
#define EBPF_TRACELOG_KEYWORD_CORE 0x10
|
||||
#define EBPF_TRACELOG_KEYWORD_LINK 0x20
|
||||
#define EBPF_TRACELOG_KEYWORD_MAP 0x40
|
||||
#define EBPF_TRACELOG_KEYWORD_PROGRAM 0x80
|
||||
|
||||
#define EBPF_TRACELOG_LEVEL_LOG_ALWAYS WINEVENT_LEVEL_LOG_ALWAYS
|
||||
#define EBPF_TRACELOG_LEVEL_CRITICAL WINEVENT_LEVEL_CRITICAL
|
||||
#define EBPF_TRACELOG_LEVEL_ERROR WINEVENT_LEVEL_ERROR
|
||||
#define EBPF_TRACELOG_LEVEL_WARNING WINEVENT_LEVEL_WARNING
|
||||
#define EBPF_TRACELOG_LEVEL_INFO WINEVENT_LEVEL_INFO
|
||||
#define EBPF_TRACELOG_LEVEL_VERBOSE WINEVENT_LEVEL_VERBOSE
|
||||
|
||||
#define EBPF_LOG_FUNCTION_SUCCESS() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_SUCCESS, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_BASE), \
|
||||
TraceLoggingString(__FUNCTION__ "returned success", "Message"));
|
||||
|
||||
#define EBPF_LOG_FUNCTION_ERROR(Result) \
|
||||
#define EBPF_LOG_FUNCTION_ERROR(result) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_EVENT_GENERIC_ERROR, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_ERROR, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_ERROR), \
|
||||
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_ERROR), \
|
||||
TraceLoggingString(__FUNCTION__ " returned error", "ErrorMessage"), \
|
||||
TraceLoggingLong(Result, "Error"));
|
||||
TraceLoggingLong(result, "Error"));
|
||||
|
||||
#define EBPF_LOG_ENTRY() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
TraceLoggingOpcode(WINEVENT_OPCODE_START), \
|
||||
#define EBPF_LOG_ENTRY() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT), \
|
||||
TraceLoggingOpcode(WINEVENT_OPCODE_START), \
|
||||
TraceLoggingString(__FUNCTION__, "<=="));
|
||||
|
||||
#define EBPF_LOG_EXIT() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
TraceLoggingOpcode(WINEVENT_OPCODE_STOP), \
|
||||
#define EBPF_LOG_EXIT() \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
|
||||
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT), \
|
||||
TraceLoggingOpcode(WINEVENT_OPCODE_STOP), \
|
||||
TraceLoggingString(__FUNCTION__, "==>"));
|
||||
|
||||
#define EBPF_RETURN_RESULT(status) \
|
||||
do { \
|
||||
ebpf_result_t result = (status); \
|
||||
if (result == EBPF_SUCCESS) { \
|
||||
EBPF_LOG_FUNCTION_SUCCESS(); \
|
||||
} else { \
|
||||
EBPF_LOG_FUNCTION_ERROR(result); \
|
||||
} \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return result; \
|
||||
#define EBPF_RETURN_RESULT(status) \
|
||||
do { \
|
||||
ebpf_result_t local_result = (status); \
|
||||
if (local_result == EBPF_SUCCESS) { \
|
||||
EBPF_LOG_FUNCTION_SUCCESS(); \
|
||||
} else { \
|
||||
EBPF_LOG_FUNCTION_ERROR(local_result); \
|
||||
} \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return local_result; \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_RETURN_NTSTATUS(status) \
|
||||
do { \
|
||||
ebpf_result_t local_result = (status); \
|
||||
if (!NT_SUCCESS(status)) { \
|
||||
EBPF_LOG_FUNCTION_SUCCESS(); \
|
||||
} else { \
|
||||
EBPF_LOG_FUNCTION_ERROR(local_result); \
|
||||
} \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return local_result; \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_RETURN_POINTER(type, pointer) \
|
||||
do { \
|
||||
type local_result = (type)(pointer); \
|
||||
if (local_result != NULL) { \
|
||||
EBPF_LOG_FUNCTION_SUCCESS(); \
|
||||
} else { \
|
||||
EBPF_LOG_FUNCTION_ERROR(EBPF_NO_MEMORY); \
|
||||
} \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return local_result; \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_RETURN_BOOL(flag) \
|
||||
do { \
|
||||
bool local_result = (flag); \
|
||||
if (local_result) { \
|
||||
EBPF_LOG_FUNCTION_SUCCESS(); \
|
||||
} else { \
|
||||
EBPF_LOG_FUNCTION_ERROR(EBPF_FAILED); \
|
||||
} \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return local_result; \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_RETURN_VOID() \
|
||||
do { \
|
||||
EBPF_LOG_EXIT(); \
|
||||
return; \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_LOG_MESSAGE(trace_level, keyword, message) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(trace_level), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString(message, "Message"));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_UTF8_STRING(trace_level, keyword, message, string) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(trace_level), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString(message, "Message"), \
|
||||
TraceLoggingCountedUtf8String((const char*)(string).value, (ULONG)(string).length, #string));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_UINT64(trace_level, keyword, message, value) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel((trace_level)), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString((message), "Message"), \
|
||||
TraceLoggingUInt64((value), (#value)));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_UINT64_UINT64(trace_level, keyword, message, value1, value2) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel((trace_level)), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString((message), "Message"), \
|
||||
TraceLoggingUInt64((value1), (#value1)), \
|
||||
TraceLoggingUInt64((value2), (#value2)));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_POINTER_ENUM(trace_level, keyword, message, pointer, enum) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel((trace_level)), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString((message), "Message"), \
|
||||
TraceLoggingPointer((pointer), (#pointer)), \
|
||||
TraceLoggingUInt32((enum), (#enum)));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_GUID(trace_level, keyword, message, guid) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel((trace_level)), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString((message), "Message"), \
|
||||
TraceLoggingGuid((guid), (#guid)));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_GUID_GUID(trace_level, keyword, message, guid1, guid2) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel((trace_level)), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString((message), "Message"), \
|
||||
TraceLoggingGuid((guid1), (#guid1)), \
|
||||
TraceLoggingGuid((guid2), (#guid2)));
|
||||
|
||||
#define EBPF_LOG_MESSAGE_STRING(trace_level, keyword, message, string) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(trace_level), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString(message, "Message"), \
|
||||
TraceLoggingString(string, #string));
|
||||
|
||||
#define EBPF_LOG_WIN32_API_FAILURE(keyword, api) \
|
||||
do { \
|
||||
DWORD last_error = GetLastError(); \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_API_ERROR, \
|
||||
TraceLoggingLevel(EBPF_TRACELOG_LEVEL_ERROR), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString(#api, "Api"), \
|
||||
TraceLoggingWinError(last_error)); \
|
||||
} while (false);
|
||||
|
||||
#define EBPF_LOG_NTSTATUS_API_FAILURE(keyword, api, status) \
|
||||
TraceLoggingWrite( \
|
||||
ebpf_tracelog_provider, \
|
||||
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
|
||||
TraceLoggingLevel(EBPF_TRACELOG_LEVEL_ERROR), \
|
||||
TraceLoggingKeyword((keyword)), \
|
||||
TraceLoggingString(#api, "api"), \
|
||||
TraceLoggingNTStatus(status));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -70,6 +70,7 @@ _ring_buffer_acquire_record(_Inout_ ebpf_ring_buffer_t* ring, size_t requested_l
|
|||
ebpf_result_t
|
||||
ebpf_ring_buffer_create(_Outptr_ ebpf_ring_buffer_t** ring, size_t capacity)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result;
|
||||
ebpf_ring_buffer_t* local_ring_buffer = ebpf_epoch_allocate(sizeof(ebpf_ring_buffer_t));
|
||||
if (!local_ring_buffer) {
|
||||
|
@ -98,16 +99,18 @@ ebpf_ring_buffer_create(_Outptr_ ebpf_ring_buffer_t** ring, size_t capacity)
|
|||
Error:
|
||||
ebpf_ring_buffer_destroy(local_ring_buffer);
|
||||
local_ring_buffer = NULL;
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_ring_buffer_destroy(_Frees_ptr_opt_ ebpf_ring_buffer_t* ring)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (ring) {
|
||||
ebpf_free_ring_buffer_memory(ring->ring_descriptor);
|
||||
ebpf_epoch_free(ring);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct _ebpf_serialized_helper_function_prototype_array
|
|||
void
|
||||
ebpf_map_info_array_free(uint16_t map_count, _In_opt_count_(map_count) _Post_ptr_invalid_ ebpf_map_info_t* map_info)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
uint16_t map_index;
|
||||
|
||||
if (map_info != NULL) {
|
||||
|
@ -54,6 +55,7 @@ ebpf_map_info_array_free(uint16_t map_count, _In_opt_count_(map_count) _Post_ptr
|
|||
}
|
||||
ebpf_free(map_info);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -65,6 +67,7 @@ ebpf_serialize_internal_map_info_array(
|
|||
_Out_ size_t* serialized_data_length,
|
||||
_Out_ size_t* required_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
uint16_t map_index;
|
||||
uint8_t* current = NULL;
|
||||
|
@ -88,6 +91,12 @@ ebpf_serialize_internal_map_info_array(
|
|||
|
||||
// Output buffer too small.
|
||||
if (output_buffer_length < *required_length) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Output buffer is too small",
|
||||
output_buffer_length,
|
||||
*required_length);
|
||||
result = EBPF_INSUFFICIENT_BUFFER;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -120,7 +129,7 @@ ebpf_serialize_internal_map_info_array(
|
|||
}
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
|
@ -132,6 +141,7 @@ ebpf_deserialize_map_info_array(
|
|||
uint16_t map_count,
|
||||
_Outptr_result_buffer_maybenull_(map_count) ebpf_map_info_t** map_info)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
uint16_t map_index;
|
||||
size_t out_map_size;
|
||||
|
@ -164,6 +174,12 @@ ebpf_deserialize_map_info_array(
|
|||
|
||||
// Check if sufficient input buffer remaining.
|
||||
if (buffer_left < sizeof(ebpf_serialized_map_info_t)) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Insufficient input buffer remaining",
|
||||
buffer_left,
|
||||
sizeof(ebpf_serialized_map_info_t));
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -185,6 +201,12 @@ ebpf_deserialize_map_info_array(
|
|||
|
||||
// Check if sufficient input buffer remaining.
|
||||
if (buffer_left < source->pin_path_length) {
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Insufficient input buffer remaining",
|
||||
buffer_left,
|
||||
source->pin_path_length);
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -217,13 +239,14 @@ ebpf_deserialize_map_info_array(
|
|||
Exit:
|
||||
ebpf_map_info_array_free(map_count, out_map_info);
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
void
|
||||
ebpf_program_info_free(_In_opt_ _Post_invalid_ ebpf_program_info_t* program_info)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (program_info != NULL) {
|
||||
ebpf_free(program_info->program_type_descriptor.context_descriptor);
|
||||
ebpf_free((void*)program_info->program_type_descriptor.name);
|
||||
|
@ -235,6 +258,7 @@ ebpf_program_info_free(_In_opt_ _Post_invalid_ ebpf_program_info_t* program_info
|
|||
ebpf_free(program_info->helper_prototype);
|
||||
ebpf_free(program_info);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -245,6 +269,7 @@ ebpf_serialize_program_info(
|
|||
_Out_ size_t* serialized_data_length,
|
||||
_Out_ size_t* required_length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
uint8_t* current = NULL;
|
||||
const ebpf_program_type_descriptor_t* program_type_descriptor;
|
||||
|
@ -261,6 +286,8 @@ ebpf_serialize_program_info(
|
|||
program_type_descriptor = &program_info->program_type_descriptor;
|
||||
|
||||
if (program_type_descriptor->name == NULL) {
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_BASE, "program_type_descriptor->name is NULL");
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -268,12 +295,19 @@ ebpf_serialize_program_info(
|
|||
helper_prototype_array = program_info->helper_prototype;
|
||||
if (helper_prototype_array != NULL) {
|
||||
if (program_info->count_of_helpers == 0) {
|
||||
EBPF_LOG_MESSAGE(
|
||||
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_BASE, "program_info->count_of_helpers 0");
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
for (helper_prototype_index = 0; helper_prototype_index < program_info->count_of_helpers;
|
||||
helper_prototype_index++) {
|
||||
if (helper_prototype_array[helper_prototype_index].name == NULL) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"helper_prototype_array[helper_prototype_index].name is null",
|
||||
helper_prototype_index);
|
||||
result = EBPF_INVALID_ARGUMENT;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -343,6 +377,12 @@ ebpf_serialize_program_info(
|
|||
|
||||
if (output_buffer_length < *required_length) {
|
||||
// Output buffer too small.
|
||||
EBPF_LOG_MESSAGE_UINT64_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Output buffer is too small",
|
||||
output_buffer_length,
|
||||
*required_length);
|
||||
result = EBPF_INSUFFICIENT_BUFFER;
|
||||
goto Exit;
|
||||
}
|
||||
|
@ -404,7 +444,7 @@ ebpf_serialize_program_info(
|
|||
}
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -413,6 +453,7 @@ ebpf_deserialize_program_info(
|
|||
_In_reads_bytes_(input_buffer_length) const uint8_t* input_buffer,
|
||||
_Outptr_ ebpf_program_info_t** program_info)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t result = EBPF_SUCCESS;
|
||||
ebpf_program_info_t* local_program_info;
|
||||
const uint8_t* current;
|
||||
|
@ -598,5 +639,5 @@ Exit:
|
|||
ebpf_program_info_free(local_program_info);
|
||||
}
|
||||
|
||||
return result;
|
||||
EBPF_RETURN_RESULT(result);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ static uint32_t _ebpf_state_cpu_table_size = 0;
|
|||
ebpf_result_t
|
||||
ebpf_state_initiate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value = EBPF_SUCCESS;
|
||||
|
||||
_ebpf_state_next_index = 0;
|
||||
|
@ -50,11 +51,11 @@ ebpf_state_initiate()
|
|||
goto Error;
|
||||
}
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
|
||||
Error:
|
||||
ebpf_state_terminate();
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,24 +65,28 @@ Error:
|
|||
void
|
||||
ebpf_state_terminate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_hash_table_destroy(_ebpf_state_thread_table);
|
||||
ebpf_free_cache_aligned(_ebpf_state_cpu_table);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_state_allocate_index(_Out_ size_t* new_index)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (_ebpf_state_next_index >= EBPF_MAX_STATE_ENTRIES) {
|
||||
return EBPF_NO_MEMORY;
|
||||
EBPF_RETURN_RESULT(EBPF_NO_MEMORY);
|
||||
}
|
||||
|
||||
*new_index = ebpf_interlocked_increment_int64(&_ebpf_state_next_index) - 1;
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
_ebpf_state_get_entry(_Out_ ebpf_state_entry_t** entry)
|
||||
{
|
||||
// High frequency call, don't log entry/exit.
|
||||
ebpf_state_entry_t* local_entry = NULL;
|
||||
|
||||
if (!ebpf_is_non_preemptible_work_item_supported() || ebpf_is_preemptible()) {
|
||||
|
@ -121,6 +126,7 @@ _ebpf_state_get_entry(_Out_ ebpf_state_entry_t** entry)
|
|||
ebpf_result_t
|
||||
ebpf_state_store(size_t index, uintptr_t value)
|
||||
{
|
||||
// High frequency call, don't log entry/exit.
|
||||
ebpf_state_entry_t* entry = NULL;
|
||||
ebpf_result_t return_value;
|
||||
|
||||
|
@ -134,6 +140,7 @@ ebpf_state_store(size_t index, uintptr_t value)
|
|||
ebpf_result_t
|
||||
ebpf_state_load(size_t index, _Out_ uintptr_t* value)
|
||||
{
|
||||
// High frequency call, don't log entry/exit.
|
||||
ebpf_state_entry_t* entry = NULL;
|
||||
ebpf_result_t return_value;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ typedef struct _ebpf_trampoline_table
|
|||
ebpf_result_t
|
||||
ebpf_allocate_trampoline_table(size_t entry_count, _Outptr_ ebpf_trampoline_table_t** trampoline_table)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_trampoline_table_t* local_trampoline_table = NULL;
|
||||
|
||||
|
@ -48,16 +49,18 @@ Exit:
|
|||
ebpf_free_trampoline_table(local_trampoline_table);
|
||||
// Set local_trampoline_table to satisfy the static analyzer.
|
||||
local_trampoline_table = NULL;
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_free_trampoline_table(_Frees_ptr_opt_ ebpf_trampoline_table_t* trampoline_table)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (trampoline_table) {
|
||||
ebpf_unmap_memory(trampoline_table->memory_descriptor);
|
||||
ebpf_free(trampoline_table);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -67,6 +70,7 @@ ebpf_update_trampoline_table(
|
|||
_In_reads_(helper_function_count) const uint32_t* helper_function_ids,
|
||||
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
#if defined(_AMD64_)
|
||||
|
||||
size_t function_count = helper_function_addresses->helper_function_count;
|
||||
|
@ -108,17 +112,18 @@ ebpf_update_trampoline_table(
|
|||
|
||||
Exit:
|
||||
return_value = ebpf_protect_memory(trampoline_table->memory_descriptor, EBPF_PAGE_PROTECT_READ_EXECUTE);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
#elif
|
||||
UNREFERENCED_PARAMETER(trampoline_table);
|
||||
UNREFERENCED_PARAMETER(dispatch_table);
|
||||
return EBPF_OPERATION_NOT_SUPPORTED;
|
||||
EBPF_RETURN_RESULT(EBPF_OPERATION_NOT_SUPPORTED);
|
||||
#endif
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_trampoline_entry_t* local_entries;
|
||||
ebpf_result_t return_value;
|
||||
|
||||
|
@ -138,13 +143,14 @@ ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_tabl
|
|||
|
||||
return_value = EBPF_SUCCESS;
|
||||
Exit:
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_get_trampoline_helper_address(
|
||||
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** helper_address)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_trampoline_entry_t* local_entries;
|
||||
ebpf_result_t return_value;
|
||||
|
||||
|
@ -164,5 +170,5 @@ ebpf_get_trampoline_helper_address(
|
|||
|
||||
return_value = EBPF_SUCCESS;
|
||||
Exit:
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "ebpf_platform.h"
|
||||
|
||||
// EBPF_RETURN_NTSTATUS(STATUS_SUCCESS) and similar macro invocations trigger C4127.
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
|
||||
struct _ebpf_extension_client_binding_context;
|
||||
|
||||
typedef struct _ebpf_extension_client
|
||||
|
@ -55,24 +58,33 @@ static void
|
|||
_ebpf_extension_client_notify_change(
|
||||
ebpf_extension_client_t* client_context, ebpf_extension_client_binding_context_t* client_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (client_context->extension_change_callback)
|
||||
client_context->extension_change_callback(
|
||||
client_context->extension_client_context,
|
||||
client_binding_context->provider_binding_context,
|
||||
client_binding_context->provider_data);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
_ebpf_extension_client_attach_provider(
|
||||
HANDLE nmr_binding_handle, void* client_context, const NPI_REGISTRATION_INSTANCE* provider_registration_instance)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)client_context;
|
||||
ebpf_extension_client_binding_context_t* local_client_binding_context = NULL;
|
||||
|
||||
// Only permit one provider to attach.
|
||||
if (local_client_context->client_binding_context != NULL) {
|
||||
return STATUS_NOINTERFACE;
|
||||
status = STATUS_NOINTERFACE;
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Client already attached to provider",
|
||||
*provider_registration_instance->NpiId)
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// Check that the interface matches.
|
||||
|
@ -80,7 +92,14 @@ _ebpf_extension_client_attach_provider(
|
|||
provider_registration_instance->NpiId,
|
||||
&local_client_context->npi_id,
|
||||
sizeof(local_client_context->npi_id)) != 0) {
|
||||
return STATUS_NOINTERFACE;
|
||||
status = STATUS_NOINTERFACE;
|
||||
EBPF_LOG_MESSAGE_GUID_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Interface doesn't match",
|
||||
*provider_registration_instance->NpiId,
|
||||
local_client_context->npi_id);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
local_client_binding_context =
|
||||
|
@ -109,14 +128,17 @@ _ebpf_extension_client_attach_provider(
|
|||
|
||||
if (NT_SUCCESS(status))
|
||||
_ebpf_extension_client_notify_change(local_client_context, local_client_binding_context);
|
||||
else
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrClientAttachProvider, status);
|
||||
|
||||
Done:
|
||||
return status;
|
||||
EBPF_RETURN_NTSTATUS(status);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
_ebpf_extension_client_detach_provider(void* client_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_extension_client_binding_context_t* local_client_binding_context =
|
||||
(ebpf_extension_client_binding_context_t*)client_binding_context;
|
||||
ebpf_extension_client_t* local_client_context = local_client_binding_context->extension_client;
|
||||
|
@ -130,13 +152,15 @@ _ebpf_extension_client_detach_provider(void* client_binding_context)
|
|||
ebpf_free(local_client_binding_context);
|
||||
local_client_context->client_binding_context = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
_ebpf_extension_client_cleanup_binding_context(void* client_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
UNREFERENCED_PARAMETER(client_binding_context);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -151,6 +175,7 @@ ebpf_extension_load(
|
|||
_Outptr_opt_ const ebpf_extension_dispatch_table_t** provider_dispatch_table,
|
||||
_In_opt_ ebpf_extension_change_callback_t extension_changed)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_extension_client_t* local_client_context = NULL;
|
||||
ebpf_extension_client_binding_context_t* local_client_binding_context = NULL;
|
||||
|
@ -202,6 +227,7 @@ ebpf_extension_load(
|
|||
|
||||
status = NmrRegisterClient(client_characteristics, local_client_context, &local_client_context->nmr_client_handle);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrRegisterClient, status);
|
||||
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -209,6 +235,11 @@ ebpf_extension_load(
|
|||
local_client_binding_context = local_client_context->client_binding_context;
|
||||
|
||||
if (local_client_binding_context == NULL) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"local_client_context->client_binding_context is NULL",
|
||||
*interface_id);
|
||||
ebpf_extension_unload(local_client_context);
|
||||
local_client_context = NULL;
|
||||
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
|
||||
|
@ -216,6 +247,11 @@ ebpf_extension_load(
|
|||
}
|
||||
|
||||
if (!local_client_binding_context->provider_is_attached) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"local_client_binding_context->provider_is_attached is FALSE",
|
||||
*interface_id);
|
||||
ebpf_extension_unload(local_client_context);
|
||||
local_client_context = NULL;
|
||||
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
|
||||
|
@ -238,26 +274,34 @@ Done:
|
|||
ebpf_free(local_client_context->client_binding_context);
|
||||
ebpf_free(local_client_context);
|
||||
local_client_context = NULL;
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
if (client_context) {
|
||||
status = NmrDeregisterClient(client_context->nmr_client_handle);
|
||||
if (status == STATUS_PENDING)
|
||||
NmrWaitForClientDeregisterComplete(client_context->nmr_client_handle);
|
||||
if (status == STATUS_PENDING) {
|
||||
status = NmrWaitForClientDeregisterComplete(client_context->nmr_client_handle);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrWaitForClientDeregisterComplete, status);
|
||||
}
|
||||
} else
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrDeregisterClient, status);
|
||||
}
|
||||
if (client_context != NULL)
|
||||
ebpf_free(client_context->client_binding_context);
|
||||
ebpf_free(client_context);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
void*
|
||||
ebpf_extension_get_client_context(_In_ const void* extension_client_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
void* local_extension_client_context = NULL;
|
||||
ebpf_extension_client_binding_context_t* local_client_binding_context =
|
||||
(ebpf_extension_client_binding_context_t*)extension_client_binding_context;
|
||||
|
@ -265,7 +309,14 @@ ebpf_extension_get_client_context(_In_ const void* extension_client_binding_cont
|
|||
if (local_client_context != NULL)
|
||||
local_extension_client_context = local_client_context->extension_client_context;
|
||||
|
||||
return local_extension_client_context;
|
||||
EBPF_RETURN_POINTER(void*, local_extension_client_context);
|
||||
}
|
||||
|
||||
GUID
|
||||
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context)
|
||||
{
|
||||
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)extension_client_binding_context;
|
||||
return local_client_context->npi_id;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -278,6 +329,7 @@ _ebpf_extension_provider_attach_client(
|
|||
void** provider_binding_context,
|
||||
const void** provider_dispatch)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
ebpf_result_t return_value;
|
||||
ebpf_extension_provider_t* local_provider_context = (ebpf_extension_provider_t*)provider_context;
|
||||
|
@ -288,6 +340,13 @@ _ebpf_extension_provider_attach_client(
|
|||
client_registration_instance->NpiId,
|
||||
&local_provider_context->npi_id,
|
||||
sizeof(local_provider_context->npi_id)) != 0) {
|
||||
|
||||
EBPF_LOG_MESSAGE_GUID_GUID(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Interface doesn't match",
|
||||
*client_registration_instance->NpiId,
|
||||
local_provider_context->npi_id);
|
||||
status = STATUS_NOINTERFACE;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -313,6 +372,11 @@ _ebpf_extension_provider_attach_client(
|
|||
(const ebpf_extension_dispatch_table_t*)client_dispatch);
|
||||
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_WARNING,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"client_attach_callback return failure",
|
||||
return_value);
|
||||
status = STATUS_NOINTERFACE;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -325,12 +389,13 @@ _ebpf_extension_provider_attach_client(
|
|||
|
||||
Done:
|
||||
ebpf_free(local_provider_binding_context);
|
||||
return status;
|
||||
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
_ebpf_extension_provider_detach_client(void* provider_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_extension_provider_binding_context* local_provider_binding_context =
|
||||
(ebpf_extension_provider_binding_context*)provider_binding_context;
|
||||
|
||||
|
@ -338,13 +403,15 @@ _ebpf_extension_provider_detach_client(void* provider_binding_context)
|
|||
local_provider_binding_context->client_detach_callback(
|
||||
local_provider_binding_context->callback_context, &local_provider_binding_context->client_id);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
_ebpf_extension_provider_cleanup_binding_context(void* provider_binding_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_free(provider_binding_context);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -358,6 +425,7 @@ ebpf_provider_load(
|
|||
_In_opt_ ebpf_provider_client_attach_callback_t client_attach_callback,
|
||||
_In_opt_ ebpf_provider_client_detach_callback_t client_detach_callback)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_extension_provider_t* local_provider_context;
|
||||
NPI_PROVIDER_CHARACTERISTICS* provider_characteristics;
|
||||
|
@ -409,6 +477,7 @@ ebpf_provider_load(
|
|||
provider_characteristics, local_provider_context, &local_provider_context->nmr_provider_handle);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrRegisterProvider, status);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
|
@ -419,18 +488,24 @@ ebpf_provider_load(
|
|||
Done:
|
||||
ebpf_free(local_provider_context);
|
||||
local_provider_context = NULL;
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
if (provider_context) {
|
||||
status = NmrDeregisterProvider(provider_context->nmr_provider_handle);
|
||||
if (status == STATUS_PENDING)
|
||||
NmrWaitForProviderDeregisterComplete(provider_context->nmr_provider_handle);
|
||||
if (status == STATUS_PENDING) {
|
||||
status = NmrWaitForProviderDeregisterComplete(provider_context->nmr_provider_handle);
|
||||
if (!NT_SUCCESS(status))
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrWaitForProviderDeregisterComplete, status);
|
||||
} else
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrDeregisterProvider, status);
|
||||
}
|
||||
|
||||
ebpf_free(provider_context);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ ebpf_handle_table_terminate()
|
|||
ebpf_result_t
|
||||
ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
HANDLE file_handle = 0;
|
||||
OBJECT_ATTRIBUTES object_attributes;
|
||||
|
@ -46,12 +47,14 @@ ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
|
|||
0);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ZwCreateFile, status);
|
||||
return_value = EBPF_OPERATION_NOT_SUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
status = ObReferenceObjectByHandle(file_handle, 0, NULL, UserMode, &file_object, NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObReferenceObjectByHandle, status);
|
||||
return_value = EBPF_OPERATION_NOT_SUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -69,16 +72,19 @@ Done:
|
|||
if (file_handle)
|
||||
ObCloseHandle(file_handle, UserMode);
|
||||
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_handle_close(ebpf_handle_t handle)
|
||||
{
|
||||
if (!NT_SUCCESS(ObCloseHandle((HANDLE)handle, UserMode)))
|
||||
return EBPF_INVALID_OBJECT;
|
||||
else
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status = ObCloseHandle((HANDLE)handle, UserMode);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObCloseHandle, status);
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_OBJECT);
|
||||
} else
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
|
@ -91,6 +97,7 @@ ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_
|
|||
|
||||
status = ObReferenceObjectByHandle((HANDLE)handle, 0, NULL, UserMode, &file_object, NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObReferenceObjectByHandle, status);
|
||||
return_value = EBPF_INVALID_OBJECT;
|
||||
goto Done;
|
||||
}
|
||||
|
|
|
@ -8,13 +8,6 @@
|
|||
#include "ebpf_platform.h"
|
||||
|
||||
#include <ntstrsafe.h>
|
||||
#include <wdm.h>
|
||||
#include <TraceLoggingProvider.h>
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
ebpf_tracelog_provider,
|
||||
"EbpfForWindowsProvider",
|
||||
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
|
||||
|
||||
typedef struct _ebpf_memory_descriptor
|
||||
{
|
||||
|
@ -40,23 +33,14 @@ static KDEFERRED_ROUTINE _ebpf_timer_routine;
|
|||
ebpf_result_t
|
||||
ebpf_platform_initiate()
|
||||
{
|
||||
TLG_STATUS status = TraceLoggingRegister(ebpf_tracelog_provider);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return EBPF_NO_MEMORY;
|
||||
}
|
||||
return EBPF_SUCCESS;
|
||||
}
|
||||
|
||||
// Prevent tail call optimization of the call to TraceLoggingUnregister to resolve verifier stop C4/DD
|
||||
// "An attempt was made to unload a driver without calling EtwUnregister".
|
||||
#pragma optimize("", off)
|
||||
void
|
||||
ebpf_platform_terminate()
|
||||
{
|
||||
KeFlushQueuedDpcs();
|
||||
TraceLoggingUnregister(ebpf_tracelog_provider);
|
||||
}
|
||||
#pragma optimize("", on)
|
||||
|
||||
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
|
||||
_Post_writable_byte_size_(size) void* ebpf_allocate(size_t size)
|
||||
|
@ -106,6 +90,7 @@ ebpf_free_cache_aligned(_Frees_ptr_opt_ void* memory)
|
|||
ebpf_memory_descriptor_t*
|
||||
ebpf_map_memory(size_t length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
MDL* memory_descriptor_list = NULL;
|
||||
PHYSICAL_ADDRESS start_address;
|
||||
PHYSICAL_ADDRESS end_address;
|
||||
|
@ -120,29 +105,35 @@ ebpf_map_memory(size_t length)
|
|||
void* address =
|
||||
MmMapLockedPagesSpecifyCache(memory_descriptor_list, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
|
||||
if (!address) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
|
||||
MmFreePagesFromMdl(memory_descriptor_list);
|
||||
ExFreePool(memory_descriptor_list);
|
||||
memory_descriptor_list = NULL;
|
||||
}
|
||||
} else {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmAllocatePagesForMdlEx, STATUS_NO_MEMORY);
|
||||
}
|
||||
return (ebpf_memory_descriptor_t*)memory_descriptor_list;
|
||||
EBPF_RETURN_POINTER(ebpf_memory_descriptor_t*, memory_descriptor_list);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (!memory_descriptor)
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
MmUnmapLockedPages(
|
||||
ebpf_memory_descriptor_get_base_address(memory_descriptor), &memory_descriptor->memory_descriptor_list);
|
||||
MmFreePagesFromMdl(&memory_descriptor->memory_descriptor_list);
|
||||
ExFreePool(memory_descriptor);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf_page_protection_t protection)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
ULONG mm_protection_state = 0;
|
||||
switch (protection) {
|
||||
|
@ -156,25 +147,32 @@ ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf
|
|||
mm_protection_state = PAGE_EXECUTE_READ;
|
||||
break;
|
||||
default:
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
status = MmProtectMdlSystemAddress((MDL*)&memory_descriptor->memory_descriptor_list, mm_protection_state);
|
||||
if (!NT_SUCCESS(status))
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
if (!NT_SUCCESS(status)) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmProtectMdlSystemAddress, status);
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
void*
|
||||
ebpf_memory_descriptor_get_base_address(ebpf_memory_descriptor_t* memory_descriptor)
|
||||
{
|
||||
return MmGetSystemAddressForMdlSafe(&memory_descriptor->memory_descriptor_list, NormalPagePriority);
|
||||
void* address = MmGetSystemAddressForMdlSafe(&memory_descriptor->memory_descriptor_list, NormalPagePriority);
|
||||
if (!address) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmGetSystemAddressForMdlSafe, STATUS_NO_MEMORY);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
_Ret_maybenull_ ebpf_ring_descriptor_t*
|
||||
ebpf_allocate_ring_buffer_memory(size_t length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
NTSTATUS status;
|
||||
size_t requested_page_count = length / PAGE_SIZE;
|
||||
|
||||
|
@ -188,6 +186,11 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
|
||||
if (length % PAGE_SIZE != 0 || length > MAXUINT32 / 2) {
|
||||
status = STATUS_NO_MEMORY;
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Ring buffer length doesn't match allocation granularity",
|
||||
length);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
|
@ -207,6 +210,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
FALSE,
|
||||
NULL);
|
||||
if (!ring_descriptor->memory_descriptor_list) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, IoAllocateMdl, STATUS_NO_MEMORY);
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -224,6 +228,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
ring_descriptor->base_address = MmMapLockedPagesSpecifyCache(
|
||||
ring_descriptor->memory_descriptor_list, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
|
||||
if (!ring_descriptor->base_address) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -244,14 +249,15 @@ Done:
|
|||
}
|
||||
}
|
||||
|
||||
return ring_descriptor;
|
||||
EBPF_RETURN_POINTER(ebpf_ring_descriptor_t*, ring_descriptor);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (!ring) {
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
MmUnmapLockedPages(ring->base_address, ring->memory_descriptor_list);
|
||||
|
@ -259,6 +265,7 @@ ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
|
|||
IoFreeMdl(ring->memory_descriptor_list);
|
||||
ebpf_unmap_memory(ring->memory);
|
||||
ebpf_free(ring);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -274,6 +281,7 @@ ebpf_ring_map_readonly_user(_In_ ebpf_ring_descriptor_t* ring)
|
|||
return MmMapLockedPagesSpecifyCache(
|
||||
ring->memory_descriptor_list, UserMode, MmCached, NULL, FALSE, NormalPagePriority | MdlMappingNoWrite);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -306,11 +314,16 @@ ebpf_get_code_integrity_state(_Out_ ebpf_code_integrity_state_t* state)
|
|||
status = NtQuerySystemInformation(
|
||||
SystemCodeIntegrityInformation, &code_integrity_information, system_information_length, &returned_length);
|
||||
if (NT_SUCCESS(status)) {
|
||||
*state = (code_integrity_information.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED) != 0
|
||||
? EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE
|
||||
: EBPF_CODE_INTEGRITY_DEFAULT;
|
||||
if ((code_integrity_information.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED) != 0) {
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity enabled");
|
||||
*state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
|
||||
} else {
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity disabled");
|
||||
*state = EBPF_CODE_INTEGRITY_DEFAULT;
|
||||
}
|
||||
return EBPF_SUCCESS;
|
||||
} else {
|
||||
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NtQuerySystemInformation, status);
|
||||
return EBPF_OPERATION_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +577,7 @@ ebpf_log_function(_In_ void* context, _In_z_ const char* format_string, ...)
|
|||
|
||||
status = RtlStringCchVPrintfA(buffer, sizeof(buffer), format_string, arg_start);
|
||||
if (NT_SUCCESS(status)) {
|
||||
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "eBPF: context: %s\n", buffer));
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_ERROR, buffer);
|
||||
}
|
||||
|
||||
va_end(arg_start);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <ntddk.h>
|
||||
#include <netioddk.h>
|
||||
#include <stdint.h>
|
||||
#include <wdm.h>
|
||||
|
||||
#define bool BOOLEAN
|
||||
#define true 1
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<ClCompile Include="..\ebpf_async.c" />
|
||||
<ClCompile Include="..\ebpf_epoch.c" />
|
||||
<ClCompile Include="..\ebpf_error.c" />
|
||||
<ClCompile Include="..\ebpf_etw.c" />
|
||||
<ClCompile Include="..\ebpf_hash_table.c" />
|
||||
<ClCompile Include="..\ebpf_object.c" />
|
||||
<ClCompile Include="..\ebpf_pinning_table.c" />
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
<ClCompile Include="..\ebpf_error.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ebpf_etw.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\ebpf_epoch.h">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
typedef struct _ebpf_extension_client
|
||||
{
|
||||
GUID npi_id;
|
||||
GUID client_id;
|
||||
GUID interface_id;
|
||||
void* extension_client_context;
|
||||
|
@ -41,6 +42,7 @@ ebpf_extension_load(
|
|||
_Outptr_opt_ const ebpf_extension_dispatch_table_t** provider_dispatch_table,
|
||||
_In_opt_ ebpf_extension_change_callback_t extension_changed)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state = 0;
|
||||
ebpf_extension_provider_t* local_extension_provider = NULL;
|
||||
|
@ -76,6 +78,8 @@ ebpf_extension_load(
|
|||
return_value =
|
||||
ebpf_hash_table_find(_ebpf_provider_table, (const uint8_t*)interface_id, (uint8_t**)&hash_table_find_result);
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Provider not found", *interface_id);
|
||||
return_value = EBPF_INVALID_ARGUMENT;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -87,6 +91,8 @@ ebpf_extension_load(
|
|||
(const uint8_t*)&local_extension_client,
|
||||
EBPF_HASH_TABLE_OPERATION_INSERT);
|
||||
if (return_value != EBPF_SUCCESS) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "ebpf_hash_table_update failed", return_value);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
|
@ -122,19 +128,20 @@ Done:
|
|||
}
|
||||
|
||||
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_extension_provider_t** hash_table_find_result = NULL;
|
||||
ebpf_extension_provider_t* local_extension_provider = NULL;
|
||||
|
||||
if (!client_context)
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
state = ebpf_lock_lock(&_ebpf_provider_table_lock);
|
||||
|
||||
|
@ -158,6 +165,7 @@ ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
|
|||
Done:
|
||||
ebpf_free(client_context);
|
||||
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -171,6 +179,13 @@ ebpf_extension_get_client_context(_In_ const void* extension_client_binding_cont
|
|||
return local_extension_client_context;
|
||||
}
|
||||
|
||||
GUID
|
||||
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context)
|
||||
{
|
||||
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)extension_client_binding_context;
|
||||
return local_client_context->npi_id;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6101) // ebpf_free at exit
|
||||
ebpf_result_t
|
||||
|
@ -184,6 +199,7 @@ ebpf_provider_load(
|
|||
_In_opt_ ebpf_provider_client_attach_callback_t client_attach_callback,
|
||||
_In_opt_ ebpf_provider_client_detach_callback_t client_detach_callback)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_extension_provider_t* local_extension_provider = NULL;
|
||||
|
@ -206,6 +222,9 @@ ebpf_provider_load(
|
|||
ebpf_hash_table_find(_ebpf_provider_table, (const uint8_t*)interface_id, (uint8_t**)&local_extension_provider);
|
||||
if (return_value == EBPF_SUCCESS) {
|
||||
return_value = EBPF_OBJECT_ALREADY_EXISTS;
|
||||
EBPF_LOG_MESSAGE_GUID(
|
||||
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Provider already loaded", *interface_id);
|
||||
|
||||
local_extension_provider = NULL;
|
||||
goto Done;
|
||||
}
|
||||
|
@ -251,20 +270,21 @@ ebpf_provider_load(
|
|||
Done:
|
||||
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
|
||||
ebpf_free(local_extension_provider);
|
||||
return return_value;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
void
|
||||
ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_extension_provider_t* local_extension_provider = NULL;
|
||||
GUID next_key;
|
||||
|
||||
if (!provider_context)
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
state = ebpf_lock_lock(&_ebpf_provider_table_lock);
|
||||
|
||||
|
@ -283,4 +303,5 @@ ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context
|
|||
Done:
|
||||
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
|
||||
ebpf_free(local_extension_provider);
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
|
|
@ -16,28 +16,32 @@ static bool _ebpf_handle_table_initiated = false;
|
|||
ebpf_result_t
|
||||
ebpf_handle_table_initiate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_lock_create(&_ebpf_handle_table_lock);
|
||||
memset(_ebpf_handle_table, 0, sizeof(_ebpf_handle_table));
|
||||
_ebpf_handle_table_initiated = true;
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_handle_table_terminate()
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_handle_t handle;
|
||||
if (!_ebpf_handle_table_initiated)
|
||||
return;
|
||||
EBPF_RETURN_VOID();
|
||||
|
||||
for (handle = 0; handle < EBPF_COUNT_OF(_ebpf_handle_table); handle++) {
|
||||
ebpf_handle_close(handle);
|
||||
}
|
||||
_ebpf_handle_table_initiated = false;
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ebpf_handle_t new_handle;
|
||||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state;
|
||||
|
@ -60,12 +64,13 @@ ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
|
|||
Done:
|
||||
ebpf_lock_unlock(&_ebpf_handle_table_lock, state);
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(return_value);
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_handle_close(ebpf_handle_t handle)
|
||||
{
|
||||
// High volume call - Skip entry/exit logging.
|
||||
ebpf_lock_state_t state;
|
||||
ebpf_result_t return_value;
|
||||
state = ebpf_lock_lock(&_ebpf_handle_table_lock);
|
||||
|
@ -85,8 +90,10 @@ ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_
|
|||
ebpf_result_t return_value;
|
||||
ebpf_lock_state_t state;
|
||||
|
||||
if (handle >= EBPF_COUNT_OF(_ebpf_handle_table))
|
||||
if (handle >= EBPF_COUNT_OF(_ebpf_handle_table)) {
|
||||
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_CRITICAL, EBPF_TRACELOG_KEYWORD_BASE, "Invalid handle", handle);
|
||||
return EBPF_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
state = ebpf_lock_lock(&_ebpf_handle_table_lock);
|
||||
if ((_ebpf_handle_table[handle] != NULL) &&
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <TraceLoggingProvider.h>
|
||||
#include <winmeta.h>
|
||||
|
||||
// Global variables used to override behavior for testing.
|
||||
// Permit the test to simulate both Hyper-V Code Integrity.
|
||||
|
@ -19,37 +18,28 @@ bool _ebpf_platform_code_integrity_enabled = false;
|
|||
// Permit the test to simulate non-preemptible execution.
|
||||
bool _ebpf_platform_is_preemptible = true;
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
ebpf_tracelog_provider,
|
||||
"EbpfForWindowsProvider",
|
||||
// {394f321c-5cf4-404c-aa34-4df1428a7f9c}
|
||||
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_platform_initiate()
|
||||
{
|
||||
ULONG result = TraceLoggingRegister(ebpf_tracelog_provider);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
return EBPF_NO_MEMORY;
|
||||
}
|
||||
return EBPF_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_platform_terminate()
|
||||
{
|
||||
TraceLoggingUnregister(ebpf_tracelog_provider);
|
||||
}
|
||||
{}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_get_code_integrity_state(_Out_ ebpf_code_integrity_state_t* state)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (_ebpf_platform_code_integrity_enabled) {
|
||||
*state = EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE;
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity enabled");
|
||||
*state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
|
||||
} else {
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity disabled");
|
||||
*state = EBPF_CODE_INTEGRITY_DEFAULT;
|
||||
}
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
|
||||
|
@ -122,6 +112,7 @@ ebpf_map_memory(size_t length)
|
|||
descriptor->length = length;
|
||||
|
||||
if (!descriptor->base) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc);
|
||||
free(descriptor);
|
||||
descriptor = nullptr;
|
||||
}
|
||||
|
@ -132,7 +123,9 @@ void
|
|||
ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
|
||||
{
|
||||
if (memory_descriptor) {
|
||||
VirtualFree(memory_descriptor->base, 0, MEM_RELEASE);
|
||||
if (!VirtualFree(memory_descriptor->base, 0, MEM_RELEASE)) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree);
|
||||
}
|
||||
free(memory_descriptor);
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +136,7 @@ ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
|
|||
_Ret_maybenull_ ebpf_ring_descriptor_t*
|
||||
ebpf_allocate_ring_buffer_memory(size_t length)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
bool result = false;
|
||||
HANDLE section = nullptr;
|
||||
SYSTEM_INFO sysInfo;
|
||||
|
@ -153,11 +147,17 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
|
||||
GetSystemInfo(&sysInfo);
|
||||
|
||||
if ((length % sysInfo.dwAllocationGranularity) != 0) {
|
||||
if (length == 0) {
|
||||
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Ring buffer length is zero");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
if ((length % sysInfo.dwAllocationGranularity) != 0) {
|
||||
EBPF_LOG_MESSAGE_UINT64(
|
||||
EBPF_TRACELOG_LEVEL_ERROR,
|
||||
EBPF_TRACELOG_KEYWORD_BASE,
|
||||
"Ring buffer length doesn't match allocation granularity",
|
||||
length);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -174,6 +174,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
VirtualAlloc2(nullptr, nullptr, 2 * length, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0));
|
||||
|
||||
if (placeholder1 == nullptr) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc2);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
@ -187,6 +188,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
//
|
||||
result = VirtualFree(placeholder1, length, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
||||
if (result == FALSE) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree);
|
||||
goto Exit;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
@ -198,6 +200,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
|
||||
section = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, static_cast<DWORD>(length), nullptr);
|
||||
if (section == nullptr) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, CreateFileMapping);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
@ -207,6 +210,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
view1 =
|
||||
MapViewOfFile3(section, nullptr, placeholder1, 0, length, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
|
||||
if (view1 == nullptr) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MapViewOfFile3);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
@ -221,6 +225,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
|
|||
view2 =
|
||||
MapViewOfFile3(section, nullptr, placeholder2, 0, length, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
|
||||
if (view2 == nullptr) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MapViewOfFile3);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
|
@ -261,17 +266,19 @@ Exit:
|
|||
UnmapViewOfFileEx(view2, 0);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
EBPF_RETURN_POINTER(ebpf_ring_descriptor_t*, descriptor);
|
||||
}
|
||||
|
||||
void
|
||||
ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
if (ring) {
|
||||
UnmapViewOfFile(ring->primary_view);
|
||||
UnmapViewOfFile(ring->secondary_view);
|
||||
ebpf_free(ring);
|
||||
}
|
||||
EBPF_RETURN_VOID();
|
||||
}
|
||||
|
||||
void*
|
||||
|
@ -283,12 +290,14 @@ ebpf_ring_descriptor_get_base_address(_In_ ebpf_ring_descriptor_t* ring_descript
|
|||
_Ret_maybenull_ void*
|
||||
ebpf_ring_map_readonly_user(_In_ ebpf_ring_descriptor_t* ring)
|
||||
{
|
||||
return ebpf_ring_descriptor_get_base_address(ring);
|
||||
EBPF_LOG_ENTRY();
|
||||
EBPF_RETURN_POINTER(void*, ebpf_ring_descriptor_get_base_address(ring));
|
||||
}
|
||||
|
||||
ebpf_result_t
|
||||
ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf_page_protection_t protection)
|
||||
{
|
||||
EBPF_LOG_ENTRY();
|
||||
ULONG mm_protection_state = 0;
|
||||
ULONG old_mm_protection_state = 0;
|
||||
switch (protection) {
|
||||
|
@ -302,15 +311,16 @@ ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf
|
|||
mm_protection_state = PAGE_EXECUTE_READ;
|
||||
break;
|
||||
default:
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
if (!VirtualProtect(
|
||||
memory_descriptor->base, memory_descriptor->length, mm_protection_state, &old_mm_protection_state)) {
|
||||
return EBPF_INVALID_ARGUMENT;
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualProtect);
|
||||
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
return EBPF_SUCCESS;
|
||||
EBPF_RETURN_RESULT(EBPF_SUCCESS);
|
||||
}
|
||||
|
||||
void*
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<ClCompile Include="..\ebpf_async.c" />
|
||||
<ClCompile Include="..\ebpf_epoch.c" />
|
||||
<ClCompile Include="..\ebpf_error.c" />
|
||||
<ClCompile Include="..\ebpf_etw.c" />
|
||||
<ClCompile Include="..\ebpf_hash_table.c" />
|
||||
<ClCompile Include="..\ebpf_object.c" />
|
||||
<ClCompile Include="..\ebpf_pinning_table.c" />
|
||||
|
|
|
@ -67,6 +67,9 @@
|
|||
<ClCompile Include="..\ebpf_error.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ebpf_etw.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\ebpf_program_types.idl">
|
||||
|
|
|
@ -201,7 +201,7 @@ function Import-ResultsFromVM
|
|||
|
||||
foreach($VM in $VMList) {
|
||||
$VMName = $VM.Name
|
||||
Write-Log "Importing Testlogs from $VMName"
|
||||
Write-Log "Importing TestLogs from $VMName"
|
||||
$TestCredential = New-Credential -Username $Admin -AdminPassword $AdminPassword
|
||||
$VMSession = New-PSSession -VMName $VMName -Credential $TestCredential
|
||||
if (!$VMSession) {
|
||||
|
@ -214,8 +214,15 @@ function Import-ResultsFromVM
|
|||
Write-Log ("Copy {0}_{1} from C:\eBPF on test VM to $pwd\TestLogs" -f $VMName, $LogFileName)
|
||||
Copy-Item -FromSession $VMSession ("C:\eBPF\{0}_{1}" -f $VMName, $LogFileName) -Destination ".\TestLogs" -Recurse -Force -ErrorAction Stop 2>&1 | Write-Log
|
||||
|
||||
# Move runner test logs to Testlogs folder.
|
||||
# Move runner test logs to TestLogs folder.
|
||||
Move-Item $LogFileName -Destination ".\TestLogs" -Force -ErrorAction Stop 2>&1 | Write-Log
|
||||
|
||||
# Copy ETL from Test VM.
|
||||
$EtlFile = $LogFileName.Substring(0, $LogFileName.IndexOf('.')) + ".etl"
|
||||
|
||||
Write-Log ("Copy {0}_{1} from C:\eBPF on test VM to $pwd\TestLogs" -f $VMName, $EtlFile)
|
||||
Copy-Item -FromSession $VMSession ("C:\eBPF\{0}_{1}" -f $VMName, $EtlFile) -Destination ".\TestLogs" -Recurse -Force -ErrorAction Stop 2>&1 | Write-Log
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation
|
||||
SPDX-License-Identifier: MIT
|
||||
-->
|
||||
<WindowsPerformanceRecorder Version="1.0" Author="Microsoft Corporation" Copyright="Microsoft Corporation" Company="Microsoft Corporation">
|
||||
<Profiles>
|
||||
<EventCollector Id="EventCollector_EbpfCoreProvider" Name="EbpfCoreProvider">
|
||||
<BufferSize Value="256" />
|
||||
<Buffers Value="1024" />
|
||||
</EventCollector>
|
||||
|
||||
<EventProvider Id="ExecutionContext" Name="394f321c-5cf4-404c-aa34-4df1428a7f9c" NonPagedMemory="true"/>
|
||||
|
||||
<Profile
|
||||
Id="EbpfForWindowsProvider.Verbose.File"
|
||||
Name="EbpfForWindowsProvider"
|
||||
Description="Traces for all eBPF for Windows providers"
|
||||
LoggingMode="File"
|
||||
DetailLevel="Verbose"
|
||||
Default="true">
|
||||
<Collectors>
|
||||
<EventCollectorId Value="EventCollector_EbpfCoreProvider">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="ExecutionContext"/>
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
</Profiles>
|
||||
</WindowsPerformanceRecorder>
|
|
@ -71,6 +71,9 @@ function Register-eBPFComponents
|
|||
#
|
||||
function Start-eBPFComponents
|
||||
{
|
||||
Write-Log "Starting ETW tracing"
|
||||
Start-Process -FilePath "wpr.exe" -ArgumentList @("-start", "EbpfForWindows.wprp", "-filemode") -NoNewWindow -Wait
|
||||
|
||||
# Start drivers.
|
||||
$EbpfDrivers.GetEnumerator() | ForEach-Object {
|
||||
Start-Service $_.Name -ErrorAction Stop | Write-Log
|
||||
|
@ -108,4 +111,8 @@ function Stop-eBPFComponents
|
|||
$EbpfDrivers.GetEnumerator() | ForEach-Object {
|
||||
Stop-Service $_.Name -ErrorAction Ignore 2>&1 | Write-Log
|
||||
}
|
||||
|
||||
$EtlFile = $LogFileName.Substring(0, $LogFileName.IndexOf('.')) + ".etl";
|
||||
Write-Log ("Stopping ETW tracing, creating file: " + $EtlFile)
|
||||
Start-Process -FilePath "wpr.exe" -ArgumentList @("-stop", $EtlFile) -NoNewWindow -Wait
|
||||
}
|
|
@ -82,6 +82,10 @@
|
|||
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
|
||||
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="..\ebpfforwindows.wprp">
|
||||
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
|
||||
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
|
||||
</CopyFileToFolders>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
|
|
Загрузка…
Ссылка в новой задаче