diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index 675192b77..d1b11848c 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -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 ` on the netsh prompt, where 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``` diff --git a/libs/execution_context/ebpf_core.c b/libs/execution_context/ebpf_core.c index 66123f2ce..74c24ec3b 100644 --- a/libs/execution_context/ebpf_core.c +++ b/libs/execution_context/ebpf_core.c @@ -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* diff --git a/libs/execution_context/ebpf_link.c b/libs/execution_context/ebpf_link.c index 8f85489b3..d68936e2d 100644 --- a/libs/execution_context/ebpf_link.c +++ b/libs/execution_context/ebpf_link.c @@ -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); } diff --git a/libs/execution_context/ebpf_maps.c b/libs/execution_context/ebpf_maps.c index 7c3f57a57..d67e775c8 100644 --- a/libs/execution_context/ebpf_maps.c +++ b/libs/execution_context/ebpf_maps.c @@ -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; } diff --git a/libs/execution_context/ebpf_program.c b/libs/execution_context/ebpf_program.c index c774a3bbf..96b486946 100644 --- a/libs/execution_context/ebpf_program.c +++ b/libs/execution_context/ebpf_program.c @@ -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); } diff --git a/libs/platform/ebpf_async.c b/libs/platform/ebpf_async.c index 8494254f2..2e66e05ac 100644 --- a/libs/platform/ebpf_async.c +++ b/libs/platform/ebpf_async.c @@ -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(); } diff --git a/libs/platform/ebpf_epoch.c b/libs/platform/ebpf_epoch.c index 726a696ba..a6236c054 100644 --- a/libs/platform/ebpf_epoch.c +++ b/libs/platform/ebpf_epoch.c @@ -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. diff --git a/libs/platform/ebpf_etw.c b/libs/platform/ebpf_etw.c new file mode 100644 index 000000000..478b27e19 --- /dev/null +++ b/libs/platform/ebpf_etw.c @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT + +#include "ebpf_platform.h" + +#include +#include + +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) diff --git a/libs/platform/ebpf_object.c b/libs/platform/ebpf_object.c index ecb3be152..c88cb1582 100644 --- a/libs/platform/ebpf_object.c +++ b/libs/platform/ebpf_object.c @@ -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); diff --git a/libs/platform/ebpf_pinning_table.c b/libs/platform/ebpf_pinning_table.c index 78a59570f..ed92b2ab5 100644 --- a/libs/platform/ebpf_pinning_table.c +++ b/libs/platform/ebpf_pinning_table.c @@ -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(); } diff --git a/libs/platform/ebpf_platform.h b/libs/platform/ebpf_platform.h index 160e63333..df5782f6e 100644 --- a/libs/platform/ebpf_platform.h +++ b/libs/platform/ebpf_platform.h @@ -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 diff --git a/libs/platform/ebpf_ring_buffer.c b/libs/platform/ebpf_ring_buffer.c index 50521e35b..1ba5ed738 100644 --- a/libs/platform/ebpf_ring_buffer.c +++ b/libs/platform/ebpf_ring_buffer.c @@ -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 diff --git a/libs/platform/ebpf_serialize.c b/libs/platform/ebpf_serialize.c index fdcf42914..27f1a7111 100644 --- a/libs/platform/ebpf_serialize.c +++ b/libs/platform/ebpf_serialize.c @@ -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); } diff --git a/libs/platform/ebpf_state.c b/libs/platform/ebpf_state.c index 681dae247..be63dbe26 100644 --- a/libs/platform/ebpf_state.c +++ b/libs/platform/ebpf_state.c @@ -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; diff --git a/libs/platform/ebpf_trampoline.c b/libs/platform/ebpf_trampoline.c index f7c7787e1..d44a79da6 100644 --- a/libs/platform/ebpf_trampoline.c +++ b/libs/platform/ebpf_trampoline.c @@ -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); } diff --git a/libs/platform/kernel/ebpf_extension_kernel.c b/libs/platform/kernel/ebpf_extension_kernel.c index 56c8a8e65..eaef7a2d7 100644 --- a/libs/platform/kernel/ebpf_extension_kernel.c +++ b/libs/platform/kernel/ebpf_extension_kernel.c @@ -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(); } diff --git a/libs/platform/kernel/ebpf_handle_kernel.c b/libs/platform/kernel/ebpf_handle_kernel.c index b4bfb34ba..0df973b85 100644 --- a/libs/platform/kernel/ebpf_handle_kernel.c +++ b/libs/platform/kernel/ebpf_handle_kernel.c @@ -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; } diff --git a/libs/platform/kernel/ebpf_platform_kernel.c b/libs/platform/kernel/ebpf_platform_kernel.c index 2e712923d..dfcacc1e1 100644 --- a/libs/platform/kernel/ebpf_platform_kernel.c +++ b/libs/platform/kernel/ebpf_platform_kernel.c @@ -8,13 +8,6 @@ #include "ebpf_platform.h" #include -#include -#include - -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); diff --git a/libs/platform/kernel/framework.h b/libs/platform/kernel/framework.h index dddfb4721..7eb8e92ee 100644 --- a/libs/platform/kernel/framework.h +++ b/libs/platform/kernel/framework.h @@ -11,6 +11,7 @@ #include #include #include +#include #define bool BOOLEAN #define true 1 diff --git a/libs/platform/kernel/platform_kernel.vcxproj b/libs/platform/kernel/platform_kernel.vcxproj index f9f3ab781..2c4520b0b 100644 --- a/libs/platform/kernel/platform_kernel.vcxproj +++ b/libs/platform/kernel/platform_kernel.vcxproj @@ -43,6 +43,7 @@ + diff --git a/libs/platform/kernel/platform_kernel.vcxproj.filters b/libs/platform/kernel/platform_kernel.vcxproj.filters index d243747f4..f03290bc4 100644 --- a/libs/platform/kernel/platform_kernel.vcxproj.filters +++ b/libs/platform/kernel/platform_kernel.vcxproj.filters @@ -61,6 +61,9 @@ Source Files + + Source Files + diff --git a/libs/platform/user/ebpf_extension_user.c b/libs/platform/user/ebpf_extension_user.c index 76cadc1d3..72dbf1074 100644 --- a/libs/platform/user/ebpf_extension_user.c +++ b/libs/platform/user/ebpf_extension_user.c @@ -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(); } diff --git a/libs/platform/user/ebpf_handle_user.c b/libs/platform/user/ebpf_handle_user.c index e960dfe55..f34d51cbe 100644 --- a/libs/platform/user/ebpf_handle_user.c +++ b/libs/platform/user/ebpf_handle_user.c @@ -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) && diff --git a/libs/platform/user/ebpf_platform_user.cpp b/libs/platform/user/ebpf_platform_user.cpp index 6379cdc70..4f6735c54 100644 --- a/libs/platform/user/ebpf_platform_user.cpp +++ b/libs/platform/user/ebpf_platform_user.cpp @@ -11,7 +11,6 @@ #include #include #include -#include // 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(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* diff --git a/libs/platform/user/platform_user.vcxproj b/libs/platform/user/platform_user.vcxproj index 66df280cc..f6569086b 100644 --- a/libs/platform/user/platform_user.vcxproj +++ b/libs/platform/user/platform_user.vcxproj @@ -27,6 +27,7 @@ + diff --git a/libs/platform/user/platform_user.vcxproj.filters b/libs/platform/user/platform_user.vcxproj.filters index 87a0f5562..3633bd80d 100644 --- a/libs/platform/user/platform_user.vcxproj.filters +++ b/libs/platform/user/platform_user.vcxproj.filters @@ -67,6 +67,9 @@ Source Files + + Source Files + diff --git a/scripts/config_test_vm.psm1 b/scripts/config_test_vm.psm1 index f3608a310..f20e1a5f6 100644 --- a/scripts/config_test_vm.psm1 +++ b/scripts/config_test_vm.psm1 @@ -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 + } } diff --git a/scripts/ebpfforwindows.wprp b/scripts/ebpfforwindows.wprp new file mode 100644 index 000000000..cefb082fd --- /dev/null +++ b/scripts/ebpfforwindows.wprp @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scripts/install_ebpf.psm1 b/scripts/install_ebpf.psm1 index cd0927938..d627fbbbe 100644 --- a/scripts/install_ebpf.psm1 +++ b/scripts/install_ebpf.psm1 @@ -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 } \ No newline at end of file diff --git a/scripts/setup_build/setup_build.vcxproj b/scripts/setup_build/setup_build.vcxproj index 50b8f4a7a..e1a227aee 100644 --- a/scripts/setup_build/setup_build.vcxproj +++ b/scripts/setup_build/setup_build.vcxproj @@ -82,6 +82,10 @@ true true + + true + true + 16.0