Instrument eBPF for Windows platform layer (#647)

* Instrument eBPF Core with tracing

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2021-11-03 09:33:40 -06:00 коммит произвёл GitHub
Родитель 65f3a545a5
Коммит 260a8d77dc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
30 изменённых файлов: 980 добавлений и 225 удалений

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

@ -188,3 +188,10 @@ This application tests various XDP functionalities. It has the following tests:
2. Load the test eBPF program by running the following commands: `netsh`, `ebpf`, `add program reflect_packet.o xdp` and note the ID.
3. From a remote host, run xdp_tests.exe and in `--remote-ip` parameter pass an IPv4 or IPv6 address of an Ethernet-like interface on the system under test in string format.
4. Unload the program from system under test by running `delete program <id>` on the netsh prompt, where <id> is the ID noted above.
### Capturing traces
eBPF for Windows uses ETW for tracing. To capture a trace use the following commands:
1) Start tracing: ```wpr.exe -start ebpfforwindows.wprp -filemode```
2) Run the scenario to be traced.
3) Stop tracing: ```wpr.exe -stop ebpfforwindows.etl```
4) Convert the traces to a human readable version: ```netsh trace convert ebpfforwindows.etl ebpfforwindows.csv csv```

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

@ -22,7 +22,7 @@ GUID ebpf_general_helper_function_interface_id = {/* 8d2a1d3f-9ce6-473d-b48e-17a
static ebpf_pinning_table_t* _ebpf_core_map_pinning_table = NULL;
// Assume enabled until we can query it.
static ebpf_code_integrity_state_t _ebpf_core_code_integrity_state = EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE;
static ebpf_code_integrity_state_t _ebpf_core_code_integrity_state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
// Map related helpers.
static void*
@ -85,6 +85,10 @@ ebpf_core_initiate()
if (return_value != EBPF_SUCCESS)
goto Done;
return_value = ebpf_trace_initiate();
if (return_value != EBPF_SUCCESS)
goto Done;
return_value = ebpf_epoch_initiate();
if (return_value != EBPF_SUCCESS)
goto Done;
@ -160,20 +164,27 @@ ebpf_core_terminate()
// Verify that all ebpf_object_t objects have been freed.
ebpf_object_tracking_terminate();
ebpf_trace_terminate();
ebpf_platform_terminate();
}
static ebpf_result_t
_ebpf_core_protocol_load_code(_In_ const ebpf_operation_load_code_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* program = NULL;
uint8_t* code = NULL;
size_t code_length = 0;
if (request->code_type == EBPF_CODE_NATIVE) {
if (_ebpf_core_code_integrity_state == EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE) {
if (_ebpf_core_code_integrity_state == EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE) {
retval = EBPF_BLOCKED_BY_POLICY;
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_CORE,
"code_type == EBPF_CODE_NATIVE blocked by EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE");
goto Done;
}
}
@ -191,7 +202,7 @@ _ebpf_core_protocol_load_code(_In_ const ebpf_operation_load_code_request_t* req
Done:
ebpf_object_release_reference((ebpf_object_t*)program);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -200,6 +211,7 @@ _ebpf_core_protocol_resolve_helper(
_Inout_ struct _ebpf_operation_resolve_helper_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_program_t* program = NULL;
ebpf_result_t return_value = EBPF_SUCCESS;
size_t count_of_helpers =
@ -245,7 +257,7 @@ Done:
ebpf_object_release_reference((ebpf_object_t*)program);
ebpf_free(request_helper_ids);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
static ebpf_result_t
@ -254,6 +266,7 @@ _ebpf_core_protocol_resolve_map(
_Inout_ struct _ebpf_operation_resolve_map_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_program_t* program = NULL;
uint32_t count_of_maps =
(request->header.length - EBPF_OFFSET_OF(ebpf_operation_resolve_map_request_t, map_handle)) /
@ -292,7 +305,7 @@ _ebpf_core_protocol_resolve_map(
Done:
ebpf_object_release_reference((ebpf_object_t*)program);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
static ebpf_result_t
@ -301,6 +314,7 @@ _ebpf_core_protocol_create_map(
_Inout_ struct _ebpf_operation_create_map_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
UNREFERENCED_PARAMETER(reply_length);
@ -327,7 +341,7 @@ _ebpf_core_protocol_create_map(
Done:
ebpf_object_release_reference(map_object);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -336,6 +350,7 @@ _ebpf_core_protocol_create_program(
_Inout_ ebpf_operation_create_program_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* program = NULL;
ebpf_program_parameters_t parameters;
@ -384,7 +399,7 @@ _ebpf_core_protocol_create_program(
Done:
ebpf_object_release_reference((ebpf_object_t*)program);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -393,6 +408,7 @@ _ebpf_core_protocol_map_find_element(
_Inout_ ebpf_operation_map_find_element_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
size_t value_length;
@ -427,12 +443,13 @@ _ebpf_core_protocol_map_find_element(
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_map_update_element(_In_ const epf_operation_map_update_element_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
size_t value_length;
@ -460,13 +477,14 @@ _ebpf_core_protocol_map_update_element(_In_ const epf_operation_map_update_eleme
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_map_update_element_with_handle(
_In_ const ebpf_operation_map_update_element_with_handle_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
size_t key_length;
@ -493,12 +511,13 @@ _ebpf_core_protocol_map_update_element_with_handle(
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_element_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
size_t key_length;
@ -516,7 +535,7 @@ _ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_elem
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -525,6 +544,7 @@ _ebpf_core_protocol_map_get_next_key(
_Inout_ ebpf_operation_map_get_next_key_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_map_t* map = NULL;
size_t previous_key_length;
@ -557,12 +577,13 @@ _ebpf_core_protocol_map_get_next_key(
Done:
ebpf_object_release_reference((ebpf_object_t*)map);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_get_next_handle(ebpf_handle_t previous_handle, ebpf_object_type_t type, ebpf_handle_t* next_handle)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_object_t* previous_object = NULL;
ebpf_object_t* next_object = NULL;
@ -586,7 +607,7 @@ Done:
ebpf_object_release_reference(previous_object);
ebpf_object_release_reference(next_object);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -595,8 +616,9 @@ _ebpf_core_protocol_get_next_map(
_Inout_ struct _ebpf_operation_get_next_map_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
UNREFERENCED_PARAMETER(reply_length);
return _ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_MAP, &reply->next_handle);
EBPF_RETURN_RESULT(_ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_MAP, &reply->next_handle));
}
static ebpf_result_t
@ -605,8 +627,9 @@ _ebpf_core_protocol_get_next_program(
_Inout_ struct _ebpf_operation_get_next_program_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
UNREFERENCED_PARAMETER(reply_length);
return _ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_PROGRAM, &reply->next_handle);
EBPF_RETURN_RESULT(_ebpf_core_get_next_handle(request->previous_handle, EBPF_OBJECT_PROGRAM, &reply->next_handle));
}
static ebpf_result_t
@ -615,12 +638,13 @@ _ebpf_core_protocol_query_map_definition(
_Inout_ struct _ebpf_operation_query_map_definition_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
UNREFERENCED_PARAMETER(reply_length);
ebpf_object_t* object;
ebpf_result_t result = ebpf_reference_object_by_handle(request->handle, EBPF_OBJECT_MAP, &object);
if (result != EBPF_SUCCESS) {
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_map_t* map = (ebpf_map_t*)object;
@ -629,7 +653,7 @@ _ebpf_core_protocol_query_map_definition(
ebpf_object_release_reference(object);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
static ebpf_result_t
@ -638,6 +662,7 @@ _ebpf_core_protocol_query_program_info(
_Inout_ struct _ebpf_operation_query_program_info_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* program = NULL;
size_t required_reply_length;
@ -678,12 +703,13 @@ _ebpf_core_protocol_query_program_info(
Done:
ebpf_object_release_reference((ebpf_object_t*)program);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_pinning_request* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
const ebpf_utf8_string_t path = {
(uint8_t*)request->path,
@ -708,7 +734,7 @@ _ebpf_core_protocol_update_pinning(_In_ const struct _ebpf_operation_update_map_
Done:
ebpf_object_release_reference((ebpf_object_t*)object);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -717,6 +743,7 @@ _ebpf_core_protocol_get_pinned_object(
_Inout_ struct _ebpf_operation_get_pinning_reply* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_object_t* object = NULL;
const ebpf_utf8_string_t path = {
@ -736,13 +763,14 @@ _ebpf_core_protocol_get_pinned_object(
Done:
ebpf_object_release_reference((ebpf_object_t*)object);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_link_program(
_In_ const ebpf_operation_link_program_request_t* request, _Inout_ ebpf_operation_link_program_reply_t* reply)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* program = NULL;
ebpf_link_t* link = NULL;
@ -773,12 +801,13 @@ Done:
}
ebpf_object_release_reference((ebpf_object_t*)program);
ebpf_object_release_reference((ebpf_object_t*)link);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_link_t* link = NULL;
@ -791,24 +820,26 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ
Done:
ebpf_object_release_reference((ebpf_object_t*)link);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
_ebpf_core_protocol_close_handle(_In_ const ebpf_operation_close_handle_request_t* request)
{
return ebpf_handle_close(request->handle);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(ebpf_handle_close(request->handle));
}
static uint64_t
_ebpf_core_protocol_get_ec_function(
_In_ const ebpf_operation_get_ec_function_request_t* request, _Inout_ ebpf_operation_get_ec_function_reply_t* reply)
{
EBPF_LOG_ENTRY();
if (request->function != EBPF_EC_FUNCTION_LOG)
return EBPF_INVALID_ARGUMENT;
reply->address = (uint64_t)ebpf_log_function;
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
// Get helper info for a program or program type. This is used by the jitter/verifier,
@ -820,6 +851,7 @@ _ebpf_core_protocol_get_program_info(
_Inout_ ebpf_operation_get_program_info_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* program = NULL;
ebpf_program_parameters_t program_parameters = {0};
@ -866,7 +898,7 @@ _ebpf_core_protocol_get_program_info(
Done:
ebpf_program_free_program_info(program_info);
ebpf_object_release_reference((ebpf_object_t*)program);
return retval;
EBPF_RETURN_RESULT(retval);
}
static ebpf_result_t
@ -959,6 +991,7 @@ _ebpf_core_protocol_get_map_info(
_In_ ebpf_operation_get_map_info_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
uint16_t entry_count = 0;
ebpf_pinning_entry_t* pinning_entries = NULL;
@ -992,7 +1025,7 @@ Exit:
ebpf_free(map_info);
ebpf_pinning_entries_release(entry_count, pinning_entries);
return result;
EBPF_RETURN_RESULT(result);
}
static ebpf_result_t
@ -1025,7 +1058,8 @@ _ebpf_core_protocol_get_map_handle_by_id(
_Out_ ebpf_operation_get_handle_by_id_reply_t* reply,
uint16_t reply_length)
{
return _get_handle_by_id(EBPF_OBJECT_MAP, request, reply, reply_length);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(_get_handle_by_id(EBPF_OBJECT_MAP, request, reply, reply_length));
}
static ebpf_result_t
@ -1034,7 +1068,8 @@ _ebpf_core_protocol_get_program_handle_by_id(
_Out_ ebpf_operation_get_handle_by_id_reply_t* reply,
uint16_t reply_length)
{
return _get_handle_by_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(_get_handle_by_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length));
}
static ebpf_result_t
@ -1057,7 +1092,7 @@ _get_next_id(
return EBPF_INVALID_ARGUMENT;
}
return ebpf_object_get_next_id(request->start_id, type, &reply->next_id);
EBPF_RETURN_RESULT(ebpf_object_get_next_id(request->start_id, type, &reply->next_id));
}
static ebpf_result_t
@ -1066,7 +1101,8 @@ _ebpf_core_protocol_get_next_link_id(
_Out_ ebpf_operation_get_next_id_reply_t* reply,
uint16_t reply_length)
{
return _get_next_id(EBPF_OBJECT_LINK, request, reply, reply_length);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_LINK, request, reply, reply_length));
}
static ebpf_result_t
@ -1075,7 +1111,8 @@ _ebpf_core_protocol_get_next_map_id(
_Out_ ebpf_operation_get_next_id_reply_t* reply,
uint16_t reply_length)
{
return _get_next_id(EBPF_OBJECT_MAP, request, reply, reply_length);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_MAP, request, reply, reply_length));
}
static ebpf_result_t
@ -1084,7 +1121,8 @@ _ebpf_core_protocol_get_next_program_id(
_Out_ ebpf_operation_get_next_id_reply_t* reply,
uint16_t reply_length)
{
return _get_next_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length);
EBPF_LOG_ENTRY();
EBPF_RETURN_RESULT(_get_next_id(EBPF_OBJECT_PROGRAM, request, reply, reply_length));
}
static ebpf_result_t
@ -1093,6 +1131,7 @@ _ebpf_core_protocol_get_next_pinned_program_path(
_Out_ ebpf_operation_get_next_pinned_path_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
ebpf_utf8_string_t start_path;
ebpf_utf8_string_t next_path;
@ -1109,12 +1148,13 @@ _ebpf_core_protocol_get_next_pinned_program_path(
reply->header.length =
(uint16_t)next_path.length + EBPF_OFFSET_OF(ebpf_operation_get_next_pinned_path_reply_t, next_path);
}
return result;
EBPF_RETURN_RESULT(result);
}
static ebpf_result_t
_ebpf_core_protocol_bind_map(_In_ const ebpf_operation_bind_map_request_t* request)
{
EBPF_LOG_ENTRY();
ebpf_result_t result;
ebpf_program_t* program = NULL;
ebpf_map_t* map = NULL;
@ -1138,7 +1178,7 @@ Done:
if (map) {
ebpf_object_release_reference((ebpf_object_t*)map);
}
return result;
EBPF_RETURN_RESULT(result);
}
static ebpf_result_t
@ -1147,6 +1187,7 @@ _ebpf_core_protocol_get_object_info(
_Out_ ebpf_operation_get_object_info_reply_t* reply,
uint16_t reply_length)
{
EBPF_LOG_ENTRY();
uint16_t info_size = reply_length - FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info);
ebpf_object_t* object;
@ -1174,7 +1215,7 @@ _ebpf_core_protocol_get_object_info(
reply->header.length = FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info) + info_size;
}
ebpf_object_release_reference(object);
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
@ -1184,6 +1225,7 @@ _ebpf_core_protocol_wait_for_map_change(
uint16_t output_buffer_length,
_In_ void* async_context)
{
EBPF_LOG_ENTRY();
UNREFERENCED_PARAMETER(reply);
UNREFERENCED_PARAMETER(output_buffer_length);
@ -1196,7 +1238,7 @@ _ebpf_core_protocol_wait_for_map_change(
result = ebpf_map_wait_for_update(map, async_context);
ebpf_object_release_reference((ebpf_object_t*)map);
return result;
EBPF_RETURN_RESULT(result);
}
static void*

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

@ -43,26 +43,28 @@ _ebpf_link_free(ebpf_object_t* object)
ebpf_result_t
ebpf_link_create(ebpf_link_t** link)
{
EBPF_LOG_ENTRY();
*link = ebpf_epoch_allocate(sizeof(ebpf_link_t));
if (*link == NULL)
return EBPF_NO_MEMORY;
EBPF_RETURN_RESULT(EBPF_NO_MEMORY);
memset(*link, 0, sizeof(ebpf_link_t));
ebpf_result_t result = ebpf_object_initialize(&(*link)->object, EBPF_OBJECT_LINK, _ebpf_link_free, NULL);
if (result != EBPF_SUCCESS) {
ebpf_epoch_free(link);
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_lock_create(&(*link)->attach_lock);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
ebpf_result_t
ebpf_link_initialize(
ebpf_link_t* link, ebpf_attach_type_t attach_type, const uint8_t* context_data, size_t context_data_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_extension_data_t* provider_data;
ebpf_attach_provider_data_t* attach_provider_data;
@ -91,11 +93,15 @@ ebpf_link_initialize(
NULL);
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "No providers support attach type", attach_type);
goto Exit;
}
if ((provider_data->version != EBPF_ATTACH_PROVIDER_DATA_VERSION) || (!provider_data->data) ||
(provider_data->size != sizeof(ebpf_attach_provider_data_t))) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "Provider version not supported", attach_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -105,12 +111,13 @@ ebpf_link_initialize(
link->attach_type = attach_type;
Exit:
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value = EBPF_SUCCESS;
ebpf_lock_state_t state;
state = ebpf_lock_lock(&link->attach_lock);
@ -121,6 +128,11 @@ ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
const ebpf_program_type_t* program_type = ebpf_program_type(program);
if (memcmp(program_type, &link->program_type, sizeof(link->program_type)) != 0) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_LINK,
"Attach failed due to incorrect program type",
*program_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -130,12 +142,13 @@ ebpf_link_attach_program(ebpf_link_t* link, ebpf_program_t* program)
Done:
ebpf_lock_unlock(&link->attach_lock, state);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_link_detach_program(_Inout_ ebpf_link_t* link)
{
EBPF_LOG_ENTRY();
ebpf_lock_state_t state;
ebpf_program_t* program;
@ -153,16 +166,21 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link)
ebpf_extension_unload(link->extension_client_context);
ebpf_free(link->client_data.data);
EBPF_RETURN_VOID();
}
static ebpf_result_t
_ebpf_link_instance_invoke(
_In_ const void* extension_client_binding_context, _In_ void* program_context, _Out_ uint32_t* result)
{
// No function entry exit traces as this is a high volume function.
ebpf_result_t return_value;
ebpf_link_t* link = (ebpf_link_t*)ebpf_extension_get_client_context(extension_client_binding_context);
if (link == NULL) {
GUID npi_id = ebpf_extension_get_provider_guid(extension_client_binding_context);
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_LINK, "Client context is null", npi_id);
return_value = EBPF_FAILED;
goto Exit;
}
@ -174,17 +192,18 @@ _ebpf_link_instance_invoke(
ebpf_epoch_exit();
Exit:
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_link_get_info(
_In_ const ebpf_link_t* link, _Out_writes_to_(*info_size, *info_size) uint8_t* buffer, _Inout_ uint16_t* info_size)
{
EBPF_LOG_ENTRY();
struct bpf_link_info* info = (struct bpf_link_info*)buffer;
if (*info_size < sizeof(*info)) {
return EBPF_INSUFFICIENT_BUFFER;
EBPF_RETURN_RESULT(EBPF_INSUFFICIENT_BUFFER);
}
info->id = link->object.id;
@ -195,5 +214,5 @@ ebpf_link_get_info(
info->attach_type = BPF_ATTACH_TYPE_UNSPEC; // TODO(#223): get actual integer, and also return attach_type_uuid
*info_size = sizeof(*info);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}

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

@ -1340,6 +1340,7 @@ _ebpf_map_signal_async_contexts(_In_ ebpf_core_map_t* map)
static void
_ebpf_map_delete(_In_ ebpf_object_t* object)
{
EBPF_LOG_ENTRY();
ebpf_map_t* map = (ebpf_map_t*)object;
if (map->inner_map_template != NULL) {
@ -1348,6 +1349,7 @@ _ebpf_map_delete(_In_ ebpf_object_t* object)
ebpf_free(map->name.value);
_ebpf_map_signal_async_contexts(map);
ebpf_map_function_tables[map->ebpf_map_definition.type].delete_map(map);
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -1357,6 +1359,7 @@ ebpf_map_create(
ebpf_handle_t inner_map_handle,
_Outptr_ ebpf_map_t** ebpf_map)
{
EBPF_LOG_ENTRY();
ebpf_map_t* local_map = NULL;
ebpf_object_t* inner_map_template_object = NULL;
ebpf_map_type_t type = ebpf_map_definition->type;
@ -1373,17 +1376,32 @@ ebpf_map_create(
break;
}
if ((type >= EBPF_COUNT_OF(ebpf_map_function_tables)) || (map_name->length >= BPF_OBJ_NAME_LEN)) {
if (type >= EBPF_COUNT_OF(ebpf_map_function_tables)) {
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Unsupported map type", type);
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (map_name->length >= BPF_OBJ_NAME_LEN) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Map name too long", map_name->length);
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (!ebpf_map_function_tables[type].create_map) {
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Unsupported map type", type);
result = EBPF_OPERATION_NOT_SUPPORTED;
goto Exit;
}
if (local_map_definition.size != sizeof(local_map_definition)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Unsupported map definition size",
local_map_definition.size,
sizeof(local_map_definition));
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -1392,6 +1410,8 @@ ebpf_map_create(
local_map_definition.type == BPF_MAP_TYPE_HASH_OF_MAPS) {
if (inner_map_handle == ebpf_handle_invalid) {
// Must have a valid inner_map_handle.
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Map in map must have a valid inner_map_handle");
result = EBPF_INVALID_FD;
goto Exit;
}
@ -1435,7 +1455,7 @@ Exit:
ebpf_epoch_free(local_map);
}
}
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
@ -1447,12 +1467,25 @@ ebpf_map_find_entry(
_Out_writes_(value_size) uint8_t* value,
int flags)
{
// High volume call - Skip entry/exit logging.
uint8_t* return_value = NULL;
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return EBPF_INVALID_ARGUMENT;
}
if (!(flags & EBPF_MAP_FLAG_HELPER) && (value_size != map->ebpf_map_definition.value_size)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map value size",
value_size,
map->ebpf_map_definition.value_size);
return EBPF_INVALID_ARGUMENT;
}
@ -1461,6 +1494,8 @@ ebpf_map_find_entry(
// Disallow reads to prog array maps from this helper call for now.
if (type == BPF_MAP_TYPE_PROG_ARRAY) {
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Find not supported on BPF_MAP_TYPE_PROG_ARRAY");
return EBPF_INVALID_ARGUMENT;
}
@ -1501,19 +1536,29 @@ ebpf_map_find_entry(
ebpf_result_t
ebpf_map_associate_program(_In_ ebpf_map_t* map, _In_ const ebpf_program_t* program)
{
EBPF_LOG_ENTRY();
if (ebpf_map_function_tables[map->ebpf_map_definition.type].associate_program)
return ebpf_map_function_tables[map->ebpf_map_definition.type].associate_program(map, program);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
_Ret_maybenull_ ebpf_program_t*
ebpf_map_get_program_from_entry(_In_ ebpf_map_t* map, size_t key_size, _In_reads_(key_size) const uint8_t* key)
{
// High volume call - Skip entry/exit logging.
if (key_size != map->ebpf_map_definition.key_size) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return NULL;
}
ebpf_map_type_t type = map->ebpf_map_definition.type;
if (type != BPF_MAP_TYPE_PROG_ARRAY) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Operation not supported on map", type);
return NULL;
}
@ -1533,17 +1578,35 @@ ebpf_map_update_entry(
ebpf_map_option_t option,
int flags)
{
// High volume call - Skip entry/exit logging.
ebpf_result_t result;
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return EBPF_INVALID_ARGUMENT;
}
if (!(flags & EBPF_MAP_FLAG_HELPER) && (value_size != map->ebpf_map_definition.value_size)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map value size",
value_size,
map->ebpf_map_definition.value_size);
return EBPF_INVALID_ARGUMENT;
}
if ((ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry == NULL) ||
(ebpf_map_function_tables[map->ebpf_map_definition.type].find_entry == NULL)) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"ebpf_map_update_entry not supported on map",
map->ebpf_map_definition.type);
return EBPF_INVALID_ARGUMENT;
}
@ -1567,11 +1630,23 @@ ebpf_map_update_entry_with_handle(
uintptr_t value_handle,
ebpf_map_option_t option)
{
// High volume call - Skip entry/exit logging.
if (key_size != map->ebpf_map_definition.key_size) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return EBPF_INVALID_ARGUMENT;
}
if (ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry_with_handle == NULL) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"ebpf_map_update_entry_with_handle not supported on map",
map->ebpf_map_definition.type);
return EBPF_OPERATION_NOT_SUPPORTED;
}
return ebpf_map_function_tables[map->ebpf_map_definition.type].update_entry_with_handle(
@ -1581,7 +1656,14 @@ ebpf_map_update_entry_with_handle(
ebpf_result_t
ebpf_map_delete_entry(_In_ ebpf_map_t* map, size_t key_size, _In_reads_(key_size) const uint8_t* key, int flags)
{
// High volume call - Skip entry/exit logging.
if (!(flags & EBPF_MAP_FLAG_HELPER) && (key_size != map->ebpf_map_definition.key_size)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return EBPF_INVALID_ARGUMENT;
}
ebpf_result_t result = ebpf_map_function_tables[map->ebpf_map_definition.type].delete_entry(map, key);
@ -1598,7 +1680,14 @@ ebpf_map_next_key(
_In_reads_opt_(key_size) const uint8_t* previous_key,
_Out_writes_(key_size) uint8_t* next_key)
{
// High volume call - Skip entry/exit logging.
if (key_size != map->ebpf_map_definition.key_size) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"Incorrect map key size",
key_size,
map->ebpf_map_definition.key_size);
return EBPF_INVALID_ARGUMENT;
}
return ebpf_map_function_tables[map->ebpf_map_definition.type].next_key(map, previous_key, next_key);
@ -1608,9 +1697,16 @@ ebpf_result_t
ebpf_map_get_info(
_In_ const ebpf_map_t* map, _Out_writes_to_(*info_size, *info_size) uint8_t* buffer, _Inout_ uint16_t* info_size)
{
// High volume call - Skip entry/exit logging.
struct bpf_map_info* info = (struct bpf_map_info*)buffer;
if (*info_size < sizeof(*info)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,
"ebpf_map_get_info buffer too small",
*info_size,
sizeof(*info));
return EBPF_INSUFFICIENT_BUFFER;
}

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

@ -80,11 +80,13 @@ ebpf_program_terminate()
static void
_ebpf_program_detach_links(_Inout_ ebpf_program_t* program)
{
EBPF_LOG_ENTRY();
while (!ebpf_list_is_empty(&program->links)) {
ebpf_list_entry_t* entry = program->links.Flink;
ebpf_object_t* object = CONTAINING_RECORD(entry, ebpf_object_t, object_list_entry);
ebpf_link_detach_program((ebpf_link_t*)object);
}
EBPF_RETURN_VOID();
}
static void
@ -93,6 +95,7 @@ _ebpf_program_program_info_provider_changed(
_In_ const void* provider_binding_context,
_In_opt_ const ebpf_extension_data_t* provider_data)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_program_t* program = (ebpf_program_t*)client_binding_context;
uint32_t* provider_helper_function_ids = NULL;
@ -105,6 +108,11 @@ _ebpf_program_program_info_provider_changed(
ebpf_program_data_t* program_data = (ebpf_program_data_t*)provider_data->data;
if (program_data == NULL) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"An extension cannot have empty program_data",
program->parameters.program_type);
// An extension cannot have empty program_data.
goto Exit;
}
@ -112,20 +120,37 @@ _ebpf_program_program_info_provider_changed(
helper_function_addresses = program_data->helper_function_addresses;
if ((program->provider_helper_function_count > 0) &&
(helper_function_addresses->helper_function_count != program->provider_helper_function_count))
(helper_function_addresses->helper_function_count != program->provider_helper_function_count)) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"A program info provider cannot modify helper function count upon reload",
program->parameters.program_type);
// A program info provider cannot modify helper function count upon reload.
goto Exit;
}
if (helper_function_addresses != NULL) {
ebpf_program_info_t* program_info = program_data->program_info;
ebpf_helper_function_prototype_t* helper_prototypes = NULL;
ebpf_assert(program_info != NULL);
if (program_info->count_of_helpers != helper_function_addresses->helper_function_count) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"A program info provider cannot modify helper function count upon reload",
program->parameters.program_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Exit;
}
helper_prototypes = program_info->helper_prototype;
if (helper_prototypes == NULL) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"program_info->helper_prototype can not be NULL",
program->parameters.program_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -169,6 +194,7 @@ _ebpf_program_program_info_provider_changed(
Exit:
ebpf_free(provider_helper_function_ids);
program->program_invalidated = (program->program_info_provider_data == NULL);
EBPF_RETURN_VOID();
}
/**
@ -180,11 +206,11 @@ Exit:
static void
_ebpf_program_free(ebpf_object_t* object)
{
EBPF_LOG_ENTRY();
size_t index;
ebpf_program_t* program = (ebpf_program_t*)object;
if (!program) {
return;
}
if (!program)
EBPF_RETURN_VOID();
// Detach from all the attach points.
_ebpf_program_detach_links(program);
@ -194,6 +220,7 @@ _ebpf_program_free(ebpf_object_t* object)
ebpf_object_release_reference((ebpf_object_t*)program->maps[index]);
ebpf_epoch_schedule_work_item(program->cleanup_work_item);
EBPF_RETURN_VOID();
}
static const ebpf_program_type_t*
@ -212,6 +239,7 @@ _ebpf_program_get_program_type(_In_ const ebpf_object_t* object)
static void
_ebpf_program_epoch_free(void* context)
{
EBPF_LOG_ENTRY();
ebpf_program_t* program = (ebpf_program_t*)context;
ebpf_lock_destroy(&program->lock);
@ -242,11 +270,13 @@ _ebpf_program_epoch_free(void* context)
ebpf_free(program->cleanup_work_item);
ebpf_free(program);
EBPF_RETURN_VOID();
}
static ebpf_result_t
ebpf_program_load_providers(ebpf_program_t* program)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
void* provider_binding_context;
ebpf_program_data_t* general_helper_program_data = NULL;
@ -264,16 +294,32 @@ ebpf_program_load_providers(ebpf_program_t* program)
&program->general_helper_provider_dispatch_table,
NULL);
if (return_value != EBPF_SUCCESS)
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"Failed to load general helper functions",
ebpf_general_helper_function_interface_id);
goto Done;
}
if (program->general_helper_provider_data == NULL) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"program->general_helper_provider_data can not be NULL",
ebpf_general_helper_function_interface_id);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
general_helper_program_data = (ebpf_program_data_t*)program->general_helper_provider_data->data;
if (general_helper_program_data->helper_function_addresses == NULL) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"general_helper_program_data->helper_function_addresses can not be NULL",
ebpf_general_helper_function_interface_id);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -289,15 +335,23 @@ ebpf_program_load_providers(ebpf_program_t* program)
NULL,
_ebpf_program_program_info_provider_changed);
if (return_value != EBPF_SUCCESS)
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"Failed to load program information provider",
program->parameters.program_type);
goto Done;
}
Done:
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_program_create(ebpf_program_t** program)
{
EBPF_LOG_ENTRY();
ebpf_result_t retval;
ebpf_program_t* local_program;
@ -332,19 +386,33 @@ Done:
if (local_program)
_ebpf_program_epoch_free(local_program);
return retval;
EBPF_RETURN_RESULT(retval);
}
ebpf_result_t
ebpf_program_initialize(ebpf_program_t* program, const ebpf_program_parameters_t* program_parameters)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_utf8_string_t local_program_name = {NULL, 0};
ebpf_utf8_string_t local_section_name = {NULL, 0};
ebpf_utf8_string_t local_file_name = {NULL, 0};
if ((program->parameters.code_type != EBPF_CODE_NONE) ||
(program_parameters->program_name.length >= BPF_OBJ_NAME_LEN)) {
if (program->parameters.code_type != EBPF_CODE_NONE) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"ebpf_program_initialize program->parameters.code_type must be EBPF_CODE_NONE",
program->parameters.code_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
if (program_parameters->program_name.length >= BPF_OBJ_NAME_LEN) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"Program name must be less than BPF_OBJ_NAME_LEN",
program_parameters->program_name.length);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -383,7 +451,7 @@ Done:
ebpf_free(local_program_name.value);
ebpf_free(local_section_name.value);
ebpf_free(local_file_name.value);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
_Ret_notnull_ const ebpf_program_parameters_t*
@ -401,10 +469,11 @@ ebpf_program_type(_In_ const ebpf_program_t* program)
ebpf_result_t
ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map)
{
EBPF_LOG_ENTRY();
// First make sure the map can be associated.
ebpf_result_t result = ebpf_map_associate_program(map, program);
if (result != EBPF_SUCCESS) {
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_lock_state_t state = ebpf_lock_lock(&program->lock);
@ -425,12 +494,13 @@ ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map)
Done:
ebpf_lock_unlock(&program->lock, state);
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t maps_count)
{
EBPF_LOG_ENTRY();
size_t index;
ebpf_map_t** program_maps = ebpf_allocate(maps_count * sizeof(ebpf_map_t*));
if (!program_maps)
@ -446,7 +516,7 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t
result = ebpf_map_associate_program(map, program);
if (result != EBPF_SUCCESS) {
ebpf_free(program_maps);
return result;
EBPF_RETURN_RESULT(result);
}
}
@ -457,18 +527,24 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t
ebpf_object_acquire_reference((ebpf_object_t*)program_maps[index]);
}
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
static ebpf_result_t
_ebpf_program_load_machine_code(
_Inout_ ebpf_program_t* program, _In_ const uint8_t* machine_code, size_t machine_code_size)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
uint8_t* local_machine_code = NULL;
ebpf_memory_descriptor_t* local_code_memory_descriptor = NULL;
if (program->parameters.code_type != EBPF_CODE_NATIVE) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"_ebpf_program_load_machine_code program->parameters.code_type must be EBPF_CODE_NATIVE",
program->parameters.code_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -496,12 +572,13 @@ _ebpf_program_load_machine_code(
Done:
ebpf_unmap_memory(local_code_memory_descriptor);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
static ebpf_result_t
_ebpf_program_register_helpers(ebpf_program_t* program)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
size_t index = 0;
ebpf_program_data_t* general_helper_program_data =
@ -534,23 +611,31 @@ _ebpf_program_register_helpers(ebpf_program_t* program)
continue;
if (ubpf_register(program->code_or_vm.vm, (unsigned int)index, NULL, (void*)helper) < 0) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, "ubpf_register failed", index);
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
}
Exit:
return result;
EBPF_RETURN_RESULT(result);
}
static ebpf_result_t
_ebpf_program_load_byte_code(
_Inout_ ebpf_program_t* program, _In_ const ebpf_instruction_t* instructions, size_t instruction_count)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
char* error_message = NULL;
if (program->parameters.code_type != EBPF_CODE_EBPF) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"_ebpf_program_load_byte_code program->parameters.code_type must be EBPF_CODE_EBPF",
program->parameters.code_type);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -576,6 +661,8 @@ _ebpf_program_load_byte_code(
instructions,
(uint32_t)(instruction_count * sizeof(ebpf_instruction_t)),
&error_message) != 0) {
EBPF_LOG_MESSAGE_STRING(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, "ubpf_load failed", error_message);
ebpf_free(error_message);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
@ -587,13 +674,14 @@ Done:
program->code_or_vm.vm = NULL;
}
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_program_load_code(
_Inout_ ebpf_program_t* program, ebpf_code_type_t code_type, _In_ const uint8_t* code, size_t code_size)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
program->parameters.code_type = code_type;
if (program->parameters.code_type == EBPF_CODE_NATIVE)
@ -601,9 +689,16 @@ ebpf_program_load_code(
else if (program->parameters.code_type == EBPF_CODE_EBPF)
result = _ebpf_program_load_byte_code(
program, (const ebpf_instruction_t*)code, code_size / sizeof(ebpf_instruction_t));
else
else {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"ebpf_program_load_code unknown program->parameters.code_type",
program->parameters.code_type);
result = EBPF_INVALID_ARGUMENT;
return result;
}
EBPF_RETURN_RESULT(result);
}
typedef struct _ebpf_program_tail_call_state
@ -615,6 +710,7 @@ typedef struct _ebpf_program_tail_call_state
ebpf_result_t
ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program)
{
// High volume call - Skip entry/exit logging.
ebpf_result_t result;
ebpf_program_tail_call_state_t* state = NULL;
result = ebpf_state_load(_ebpf_program_state_index, (uintptr_t*)&state);
@ -636,6 +732,7 @@ ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program)
void
ebpf_program_invoke(_In_ const ebpf_program_t* program, _In_ void* context, _Out_ uint32_t* result)
{
// High volume call - Skip entry/exit logging.
ebpf_program_tail_call_state_t state = {0};
const ebpf_program_t* current_program = program;
@ -684,6 +781,7 @@ static ebpf_result_t
_ebpf_program_get_helper_function_address(
_In_ const ebpf_program_t* program, const uint32_t helper_function_id, uint64_t* address)
{
EBPF_LOG_ENTRY();
if (helper_function_id > EBPF_MAX_GENERAL_HELPER_FUNCTION) {
void* function_address;
ebpf_result_t return_value;
@ -691,7 +789,7 @@ _ebpf_program_get_helper_function_address(
return_value =
ebpf_get_trampoline_function(program->trampoline_table, trampoline_table_index, &function_address);
if (return_value != EBPF_SUCCESS)
return return_value;
EBPF_RETURN_RESULT(return_value);
*address = (uint64_t)function_address;
} else {
@ -709,13 +807,14 @@ _ebpf_program_get_helper_function_address(
*address = general_helper_function_addresses->helper_function_address[helper_function_id];
}
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
ebpf_result_t
ebpf_program_get_helper_function_addresses(
_In_ const ebpf_program_t* program, size_t addresses_count, _Out_writes_(addresses_count) uint64_t* addresses)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
if (program->helper_function_count > addresses_count) {
@ -731,7 +830,7 @@ ebpf_program_get_helper_function_addresses(
}
Exit:
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
@ -740,9 +839,15 @@ ebpf_program_set_helper_function_ids(
const size_t helper_function_count,
_In_reads_(helper_function_count) const uint32_t* helper_function_ids)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
if (program->helper_function_ids != NULL) {
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_PROGRAM,
"ebpf_program_set_helper_function_ids - helper function IDs already set");
// Helper function IDs already set.
result = EBPF_INVALID_ARGUMENT;
goto Exit;
@ -762,12 +867,13 @@ ebpf_program_set_helper_function_ids(
program->helper_function_ids[index] = helper_function_ids[index];
Exit:
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_program_info_t** program_info)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
ebpf_program_data_t* program_data = NULL;
ebpf_program_data_t* general_helper_program_data = NULL;
@ -845,7 +951,7 @@ Exit:
ebpf_program_free_program_info(local_program_info);
}
return result;
EBPF_RETURN_RESULT(result);
}
void
@ -860,6 +966,7 @@ ebpf_program_free_program_info(_In_opt_ _Post_invalid_ ebpf_program_info_t* prog
void
ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* link)
{
EBPF_LOG_ENTRY();
// Acquire "attach" reference on the link object.
ebpf_object_acquire_reference((ebpf_object_t*)link);
@ -869,11 +976,13 @@ ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l
ebpf_list_insert_tail(&program->links, &((ebpf_object_t*)link)->object_list_entry);
program->link_count++;
ebpf_lock_unlock(&program->lock, state);
EBPF_RETURN_VOID();
}
void
ebpf_program_detach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* link)
{
EBPF_LOG_ENTRY();
// Remove the link from the attach list.
ebpf_lock_state_t state;
state = ebpf_lock_lock(&program->lock);
@ -883,6 +992,7 @@ ebpf_program_detach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l
// Release the "attach" reference.
ebpf_object_release_reference((ebpf_object_t*)link);
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -891,9 +1001,10 @@ ebpf_program_get_info(
_Out_writes_to_(*info_size, *info_size) uint8_t* buffer,
_Inout_ uint16_t* info_size)
{
EBPF_LOG_ENTRY();
struct bpf_prog_info* info = (struct bpf_prog_info*)buffer;
if (*info_size < sizeof(*info)) {
return EBPF_INSUFFICIENT_BUFFER;
EBPF_RETURN_RESULT(EBPF_INSUFFICIENT_BUFFER);
}
info->id = program->object.id;
@ -909,5 +1020,5 @@ ebpf_program_get_info(
info->link_count = program->link_count;
*info_size = sizeof(*info);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}

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

@ -37,7 +37,7 @@ ebpf_async_terminate()
ebpf_assert(ebpf_hash_table_key_count(_ebpf_async_tracker_table) == 0);
ebpf_hash_table_destroy(_ebpf_async_tracker_table);
_ebpf_async_tracker_table = NULL;
EBPF_LOG_EXIT();
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -91,17 +91,15 @@ ebpf_async_cancel(_In_ void* context)
{
EBPF_LOG_ENTRY();
ebpf_async_tracker_t* tracker = _tracker_from_context(context);
if (!tracker) {
EBPF_LOG_EXIT();
return false;
}
if (!tracker)
EBPF_RETURN_BOOL(false);
void* cancellation_context = tracker->cancellation_context;
void (*on_cancellation)(_In_ void* context) = tracker->on_cancel;
if (on_cancellation)
on_cancellation(cancellation_context);
EBPF_LOG_EXIT();
return true;
EBPF_RETURN_BOOL(true);
}
void
@ -111,16 +109,15 @@ ebpf_async_complete(_In_ void* context, ebpf_result_t result)
ebpf_async_tracker_t* tracker = _tracker_from_context(context);
if (!tracker) {
ebpf_assert(!"Async action was double completed");
EBPF_LOG_EXIT();
return;
EBPF_RETURN_VOID();
}
void (*on_complete)(_In_ void* context, ebpf_result_t result) = tracker->on_complete;
if (!_remove_tracker(context)) {
ebpf_assert(!"Async action was double completed");
EBPF_LOG_EXIT();
EBPF_RETURN_VOID();
return;
}
if (on_complete)
on_complete(context, result);
EBPF_LOG_EXIT();
EBPF_RETURN_VOID();
}

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

@ -128,6 +128,7 @@ _ebpf_epoch_update_thread_state(uint32_t cpu_id, uintptr_t thread_id, int64_t cu
ebpf_result_t
ebpf_epoch_initiate()
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value = EBPF_SUCCESS;
uint32_t cpu_id;
uint32_t cpu_count;
@ -176,12 +177,13 @@ ebpf_epoch_initiate()
Error:
ebpf_epoch_terminate();
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_epoch_terminate()
{
EBPF_LOG_ENTRY();
uint32_t cpu_id;
ebpf_free_timer_work_item(_ebpf_flush_timer);
@ -198,6 +200,7 @@ ebpf_epoch_terminate()
_ebpf_epoch_cpu_count = 0;
ebpf_free_cache_aligned(_ebpf_epoch_cpu_table);
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -249,6 +252,8 @@ ebpf_epoch_flush()
int64_t released_epoch;
ebpf_result_t return_value = _ebpf_epoch_get_release_epoch(&released_epoch);
if (return_value == EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_EPOCH, "_ebpf_release_epoch updated", released_epoch);
_ebpf_release_epoch = released_epoch;
}
}
@ -426,6 +431,11 @@ _ebpf_epoch_get_release_epoch(_Out_ int64_t* release_epoch)
uint32_t cpu_id;
ebpf_lock_state_t lock_state;
ebpf_result_t return_value;
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_VERBOSE,
EBPF_TRACELOG_KEYWORD_EPOCH,
"Captured value of _ebpf_current_epoch",
lowest_epoch);
for (cpu_id = 0; cpu_id < _ebpf_epoch_cpu_count; cpu_id++) {
ebpf_epoch_state_t* thread_epoch_state = NULL;
@ -526,6 +536,7 @@ _ebpf_epoch_update_thread_state(uint32_t cpu_id, uintptr_t thread_id, int64_t cu
if (enter) {
goto Exit;
}
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_EPOCH, "Thread state not found on current CPU");
// If this is an exit call and the current CPU doesn't have the active entry
// then scan all CPUs until we find it.

34
libs/platform/ebpf_etw.c Normal file
Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#include "ebpf_platform.h"
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DEFINE_PROVIDER(
ebpf_tracelog_provider,
"EbpfForWindowsProvider",
// {394f321c-5cf4-404c-aa34-4df1428a7f9c}
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
ebpf_result_t
ebpf_trace_initiate()
{
TLG_STATUS status = TraceLoggingRegister(ebpf_tracelog_provider);
if (status != 0) {
return EBPF_NO_MEMORY;
} else {
return EBPF_SUCCESS;
}
}
// Prevent tail call optimization of the call to TraceLoggingUnregister to resolve verifier stop C4/DD
// "An attempt was made to unload a driver without calling EtwUnregister".
#pragma optimize("", off)
void
ebpf_trace_terminate()
{
TraceLoggingUnregister(ebpf_tracelog_provider);
}
#pragma optimize("", on)

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

@ -140,6 +140,8 @@ ebpf_object_initialize(
ebpf_free_object_t free_function,
ebpf_object_get_program_type_t get_program_type_function)
{
EBPF_LOG_MESSAGE_POINTER_ENUM(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object initialized", object, object_type);
object->marker = _ebpf_object_marker;
object->reference_count = 1;
object->type = object_type;
@ -172,6 +174,9 @@ _Requires_lock_held_(&_ebpf_object_tracking_list_lock) void _ebpf_object_release
new_ref_count = ebpf_interlocked_decrement_int32(&object->reference_count);
if (new_ref_count == 0) {
EBPF_LOG_MESSAGE_POINTER_ENUM(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object terminated", object, object->type);
_ebpf_object_tracking_list_remove(object);
object->marker = ~object->marker;
object->free_function(object);
@ -192,6 +197,8 @@ ebpf_object_release_reference(ebpf_object_t* object)
new_ref_count = ebpf_interlocked_decrement_int32(&object->reference_count);
if (new_ref_count == 0) {
EBPF_LOG_MESSAGE_POINTER_ENUM(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object terminated", object, object->type);
ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock);
_ebpf_object_tracking_list_remove(object);
ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state);

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

@ -48,6 +48,7 @@ _ebpf_pinning_entry_free(ebpf_pinning_entry_t* pinning_entry)
ebpf_result_t
ebpf_pinning_table_allocate(ebpf_pinning_table_t** pinning_table)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
*pinning_table = ebpf_allocate(sizeof(ebpf_pinning_table_t));
if (*pinning_table == NULL) {
@ -80,12 +81,13 @@ Done:
ebpf_free(*pinning_table);
}
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_pinning_table_free(ebpf_pinning_table_t* pinning_table)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_utf8_string_t* key = NULL;
@ -99,24 +101,26 @@ ebpf_pinning_table_free(ebpf_pinning_table_t* pinning_table)
ebpf_hash_table_destroy(pinning_table->hash_table);
ebpf_free(pinning_table);
EBPF_RETURN_VOID();
}
ebpf_result_t
ebpf_pinning_table_insert(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path, ebpf_object_t* object)
{
EBPF_LOG_ENTRY();
ebpf_lock_state_t state;
ebpf_result_t return_value;
ebpf_utf8_string_t* new_key;
ebpf_pinning_entry_t* new_pinning_entry;
if (path->length >= EBPF_MAX_PIN_PATH_LENGTH || path->length == 0) {
return EBPF_INVALID_ARGUMENT;
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
// Block embedded null terminators
for (size_t index = 0; index < path->length; index++) {
if (path->value[index] == 0) {
return EBPF_INVALID_ARGUMENT;
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
}
@ -152,13 +156,17 @@ ebpf_pinning_table_insert(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_s
Done:
_ebpf_pinning_entry_free(new_pinning_entry);
if (return_value == EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UTF8_STRING(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "Pinned object", *path);
}
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_pinning_table_find(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path, ebpf_object_t** object)
{
EBPF_LOG_ENTRY();
ebpf_lock_state_t state;
ebpf_result_t return_value;
const ebpf_utf8_string_t* existing_key = path;
@ -175,12 +183,13 @@ ebpf_pinning_table_find(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_str
ebpf_lock_unlock(&pinning_table->lock, state);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_pinning_table_delete(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_string_t* path)
{
EBPF_LOG_ENTRY();
ebpf_lock_state_t state;
ebpf_result_t return_value;
const ebpf_utf8_string_t* existing_key = path;
@ -199,7 +208,10 @@ ebpf_pinning_table_delete(ebpf_pinning_table_t* pinning_table, const ebpf_utf8_s
}
ebpf_lock_unlock(&pinning_table->lock, state);
return return_value;
if (return_value == EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UTF8_STRING(EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "Unpinned object", *path);
}
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
@ -209,6 +221,7 @@ ebpf_pinning_table_enumerate_entries(
_Out_ uint16_t* entry_count,
_Outptr_result_buffer_maybenull_(*entry_count) ebpf_pinning_entry_t** pinning_entries)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
ebpf_lock_state_t state = 0;
bool lock_held = FALSE;
@ -297,7 +310,7 @@ Exit:
*entry_count = local_entry_count;
*pinning_entries = local_pinning_entries;
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
@ -307,8 +320,9 @@ ebpf_pinning_table_get_next_path(
_In_ const ebpf_utf8_string_t* start_path,
_Inout_ ebpf_utf8_string_t* next_path)
{
EBPF_LOG_ENTRY();
if ((pinning_table == NULL) || (start_path == NULL) || (next_path == NULL)) {
return EBPF_INVALID_ARGUMENT;
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
const uint8_t* previous_key = (start_path->length == 0) ? NULL : (const uint8_t*)&start_path;
@ -342,15 +356,16 @@ ebpf_pinning_table_get_next_path(
}
ebpf_lock_unlock(&pinning_table->lock, state);
return result;
EBPF_RETURN_RESULT(result);
}
void
ebpf_pinning_entries_release(uint16_t entry_count, _In_opt_count_(entry_count) ebpf_pinning_entry_t* pinning_entries)
{
EBPF_LOG_ENTRY();
uint16_t index;
if (!pinning_entries)
return;
EBPF_RETURN_VOID();
for (index = 0; index < entry_count; index++) {
ebpf_pinning_entry_t* entry = &pinning_entries[index];
@ -359,4 +374,5 @@ ebpf_pinning_entries_release(uint16_t entry_count, _In_opt_count_(entry_count) e
ebpf_object_release_reference(entry->object);
}
ebpf_free(pinning_entries);
EBPF_RETURN_VOID();
}

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

@ -49,7 +49,7 @@ extern "C"
typedef enum _ebpf_code_integrity_state
{
EBPF_CODE_INTEGRITY_DEFAULT = 0,
EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE = 1
EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE = 1
} ebpf_code_integrity_state_t;
typedef struct _ebpf_non_preemptible_work_item ebpf_non_preemptible_work_item_t;
@ -717,6 +717,9 @@ extern "C"
void*
ebpf_extension_get_client_context(_In_ const void* extension_client_binding_context);
GUID
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context);
/**
* @brief Unload an extension.
*
@ -959,53 +962,217 @@ extern "C"
TRACELOGGING_DECLARE_PROVIDER(ebpf_tracelog_provider);
#define EBPF_EVENT_SUCCESS "EbpfSuccess"
#define EBPF_EVENT_GENERIC_ERROR "EbpfGenericError"
#define EBPF_EVENT_GENERIC_MESSAGE "EbpfGenericMessage"
ebpf_result_t
ebpf_trace_initiate();
#define EBPF_LOG_FUNCTION_SUCCESS() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_EVENT_SUCCESS, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
void
ebpf_trace_terminate();
#define EBPF_TRACELOG_EVENT_SUCCESS "EbpfSuccess"
#define EBPF_TRACELOG_EVENT_GENERIC_ERROR "EbpfGenericError"
#define EBPF_TRACELOG_EVENT_GENERIC_MESSAGE "EbpfGenericMessage"
#define EBPF_TRACELOG_EVENT_API_ERROR "EbpfApiError"
#define EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT 0x1
#define EBPF_TRACELOG_KEYWORD_BASE 0x2
#define EBPF_TRACELOG_KEYWORD_ERROR 0x4
#define EBPF_TRACELOG_KEYWORD_EPOCH 0x8
#define EBPF_TRACELOG_KEYWORD_CORE 0x10
#define EBPF_TRACELOG_KEYWORD_LINK 0x20
#define EBPF_TRACELOG_KEYWORD_MAP 0x40
#define EBPF_TRACELOG_KEYWORD_PROGRAM 0x80
#define EBPF_TRACELOG_LEVEL_LOG_ALWAYS WINEVENT_LEVEL_LOG_ALWAYS
#define EBPF_TRACELOG_LEVEL_CRITICAL WINEVENT_LEVEL_CRITICAL
#define EBPF_TRACELOG_LEVEL_ERROR WINEVENT_LEVEL_ERROR
#define EBPF_TRACELOG_LEVEL_WARNING WINEVENT_LEVEL_WARNING
#define EBPF_TRACELOG_LEVEL_INFO WINEVENT_LEVEL_INFO
#define EBPF_TRACELOG_LEVEL_VERBOSE WINEVENT_LEVEL_VERBOSE
#define EBPF_LOG_FUNCTION_SUCCESS() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_SUCCESS, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_BASE), \
TraceLoggingString(__FUNCTION__ "returned success", "Message"));
#define EBPF_LOG_FUNCTION_ERROR(Result) \
#define EBPF_LOG_FUNCTION_ERROR(result) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_EVENT_GENERIC_ERROR, \
EBPF_TRACELOG_EVENT_GENERIC_ERROR, \
TraceLoggingLevel(WINEVENT_LEVEL_ERROR), \
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_ERROR), \
TraceLoggingString(__FUNCTION__ " returned error", "ErrorMessage"), \
TraceLoggingLong(Result, "Error"));
TraceLoggingLong(result, "Error"));
#define EBPF_LOG_ENTRY() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
TraceLoggingOpcode(WINEVENT_OPCODE_START), \
#define EBPF_LOG_ENTRY() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT), \
TraceLoggingOpcode(WINEVENT_OPCODE_START), \
TraceLoggingString(__FUNCTION__, "<=="));
#define EBPF_LOG_EXIT() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
TraceLoggingOpcode(WINEVENT_OPCODE_STOP), \
#define EBPF_LOG_EXIT() \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), \
TraceLoggingKeyword(EBPF_TRACELOG_KEYWORD_FUNCTION_ENTRY_EXIT), \
TraceLoggingOpcode(WINEVENT_OPCODE_STOP), \
TraceLoggingString(__FUNCTION__, "==>"));
#define EBPF_RETURN_RESULT(status) \
do { \
ebpf_result_t result = (status); \
if (result == EBPF_SUCCESS) { \
EBPF_LOG_FUNCTION_SUCCESS(); \
} else { \
EBPF_LOG_FUNCTION_ERROR(result); \
} \
EBPF_LOG_EXIT(); \
return result; \
#define EBPF_RETURN_RESULT(status) \
do { \
ebpf_result_t local_result = (status); \
if (local_result == EBPF_SUCCESS) { \
EBPF_LOG_FUNCTION_SUCCESS(); \
} else { \
EBPF_LOG_FUNCTION_ERROR(local_result); \
} \
EBPF_LOG_EXIT(); \
return local_result; \
} while (false);
#define EBPF_RETURN_NTSTATUS(status) \
do { \
ebpf_result_t local_result = (status); \
if (!NT_SUCCESS(status)) { \
EBPF_LOG_FUNCTION_SUCCESS(); \
} else { \
EBPF_LOG_FUNCTION_ERROR(local_result); \
} \
EBPF_LOG_EXIT(); \
return local_result; \
} while (false);
#define EBPF_RETURN_POINTER(type, pointer) \
do { \
type local_result = (type)(pointer); \
if (local_result != NULL) { \
EBPF_LOG_FUNCTION_SUCCESS(); \
} else { \
EBPF_LOG_FUNCTION_ERROR(EBPF_NO_MEMORY); \
} \
EBPF_LOG_EXIT(); \
return local_result; \
} while (false);
#define EBPF_RETURN_BOOL(flag) \
do { \
bool local_result = (flag); \
if (local_result) { \
EBPF_LOG_FUNCTION_SUCCESS(); \
} else { \
EBPF_LOG_FUNCTION_ERROR(EBPF_FAILED); \
} \
EBPF_LOG_EXIT(); \
return local_result; \
} while (false);
#define EBPF_RETURN_VOID() \
do { \
EBPF_LOG_EXIT(); \
return; \
} while (false);
#define EBPF_LOG_MESSAGE(trace_level, keyword, message) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(trace_level), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString(message, "Message"));
#define EBPF_LOG_MESSAGE_UTF8_STRING(trace_level, keyword, message, string) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(trace_level), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString(message, "Message"), \
TraceLoggingCountedUtf8String((const char*)(string).value, (ULONG)(string).length, #string));
#define EBPF_LOG_MESSAGE_UINT64(trace_level, keyword, message, value) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel((trace_level)), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString((message), "Message"), \
TraceLoggingUInt64((value), (#value)));
#define EBPF_LOG_MESSAGE_UINT64_UINT64(trace_level, keyword, message, value1, value2) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel((trace_level)), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString((message), "Message"), \
TraceLoggingUInt64((value1), (#value1)), \
TraceLoggingUInt64((value2), (#value2)));
#define EBPF_LOG_MESSAGE_POINTER_ENUM(trace_level, keyword, message, pointer, enum) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel((trace_level)), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString((message), "Message"), \
TraceLoggingPointer((pointer), (#pointer)), \
TraceLoggingUInt32((enum), (#enum)));
#define EBPF_LOG_MESSAGE_GUID(trace_level, keyword, message, guid) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel((trace_level)), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString((message), "Message"), \
TraceLoggingGuid((guid), (#guid)));
#define EBPF_LOG_MESSAGE_GUID_GUID(trace_level, keyword, message, guid1, guid2) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel((trace_level)), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString((message), "Message"), \
TraceLoggingGuid((guid1), (#guid1)), \
TraceLoggingGuid((guid2), (#guid2)));
#define EBPF_LOG_MESSAGE_STRING(trace_level, keyword, message, string) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(trace_level), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString(message, "Message"), \
TraceLoggingString(string, #string));
#define EBPF_LOG_WIN32_API_FAILURE(keyword, api) \
do { \
DWORD last_error = GetLastError(); \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_API_ERROR, \
TraceLoggingLevel(EBPF_TRACELOG_LEVEL_ERROR), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString(#api, "Api"), \
TraceLoggingWinError(last_error)); \
} while (false);
#define EBPF_LOG_NTSTATUS_API_FAILURE(keyword, api, status) \
TraceLoggingWrite( \
ebpf_tracelog_provider, \
EBPF_TRACELOG_EVENT_GENERIC_MESSAGE, \
TraceLoggingLevel(EBPF_TRACELOG_LEVEL_ERROR), \
TraceLoggingKeyword((keyword)), \
TraceLoggingString(#api, "api"), \
TraceLoggingNTStatus(status));
#ifdef __cplusplus
}
#endif

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

@ -70,6 +70,7 @@ _ring_buffer_acquire_record(_Inout_ ebpf_ring_buffer_t* ring, size_t requested_l
ebpf_result_t
ebpf_ring_buffer_create(_Outptr_ ebpf_ring_buffer_t** ring, size_t capacity)
{
EBPF_LOG_ENTRY();
ebpf_result_t result;
ebpf_ring_buffer_t* local_ring_buffer = ebpf_epoch_allocate(sizeof(ebpf_ring_buffer_t));
if (!local_ring_buffer) {
@ -98,16 +99,18 @@ ebpf_ring_buffer_create(_Outptr_ ebpf_ring_buffer_t** ring, size_t capacity)
Error:
ebpf_ring_buffer_destroy(local_ring_buffer);
local_ring_buffer = NULL;
return result;
EBPF_RETURN_RESULT(result);
}
void
ebpf_ring_buffer_destroy(_Frees_ptr_opt_ ebpf_ring_buffer_t* ring)
{
EBPF_LOG_ENTRY();
if (ring) {
ebpf_free_ring_buffer_memory(ring->ring_descriptor);
ebpf_epoch_free(ring);
}
EBPF_RETURN_VOID();
}
ebpf_result_t

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

@ -45,6 +45,7 @@ typedef struct _ebpf_serialized_helper_function_prototype_array
void
ebpf_map_info_array_free(uint16_t map_count, _In_opt_count_(map_count) _Post_ptr_invalid_ ebpf_map_info_t* map_info)
{
EBPF_LOG_ENTRY();
uint16_t map_index;
if (map_info != NULL) {
@ -54,6 +55,7 @@ ebpf_map_info_array_free(uint16_t map_count, _In_opt_count_(map_count) _Post_ptr
}
ebpf_free(map_info);
}
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -65,6 +67,7 @@ ebpf_serialize_internal_map_info_array(
_Out_ size_t* serialized_data_length,
_Out_ size_t* required_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
uint16_t map_index;
uint8_t* current = NULL;
@ -88,6 +91,12 @@ ebpf_serialize_internal_map_info_array(
// Output buffer too small.
if (output_buffer_length < *required_length) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Output buffer is too small",
output_buffer_length,
*required_length);
result = EBPF_INSUFFICIENT_BUFFER;
goto Exit;
}
@ -120,7 +129,7 @@ ebpf_serialize_internal_map_info_array(
}
Exit:
return result;
EBPF_RETURN_RESULT(result);
}
#pragma warning(push)
@ -132,6 +141,7 @@ ebpf_deserialize_map_info_array(
uint16_t map_count,
_Outptr_result_buffer_maybenull_(map_count) ebpf_map_info_t** map_info)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
uint16_t map_index;
size_t out_map_size;
@ -164,6 +174,12 @@ ebpf_deserialize_map_info_array(
// Check if sufficient input buffer remaining.
if (buffer_left < sizeof(ebpf_serialized_map_info_t)) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Insufficient input buffer remaining",
buffer_left,
sizeof(ebpf_serialized_map_info_t));
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -185,6 +201,12 @@ ebpf_deserialize_map_info_array(
// Check if sufficient input buffer remaining.
if (buffer_left < source->pin_path_length) {
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Insufficient input buffer remaining",
buffer_left,
source->pin_path_length);
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -217,13 +239,14 @@ ebpf_deserialize_map_info_array(
Exit:
ebpf_map_info_array_free(map_count, out_map_info);
return result;
EBPF_RETURN_RESULT(result);
}
#pragma warning(pop)
void
ebpf_program_info_free(_In_opt_ _Post_invalid_ ebpf_program_info_t* program_info)
{
EBPF_LOG_ENTRY();
if (program_info != NULL) {
ebpf_free(program_info->program_type_descriptor.context_descriptor);
ebpf_free((void*)program_info->program_type_descriptor.name);
@ -235,6 +258,7 @@ ebpf_program_info_free(_In_opt_ _Post_invalid_ ebpf_program_info_t* program_info
ebpf_free(program_info->helper_prototype);
ebpf_free(program_info);
}
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -245,6 +269,7 @@ ebpf_serialize_program_info(
_Out_ size_t* serialized_data_length,
_Out_ size_t* required_length)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
uint8_t* current = NULL;
const ebpf_program_type_descriptor_t* program_type_descriptor;
@ -261,6 +286,8 @@ ebpf_serialize_program_info(
program_type_descriptor = &program_info->program_type_descriptor;
if (program_type_descriptor->name == NULL) {
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_BASE, "program_type_descriptor->name is NULL");
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -268,12 +295,19 @@ ebpf_serialize_program_info(
helper_prototype_array = program_info->helper_prototype;
if (helper_prototype_array != NULL) {
if (program_info->count_of_helpers == 0) {
EBPF_LOG_MESSAGE(
EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_BASE, "program_info->count_of_helpers 0");
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
for (helper_prototype_index = 0; helper_prototype_index < program_info->count_of_helpers;
helper_prototype_index++) {
if (helper_prototype_array[helper_prototype_index].name == NULL) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"helper_prototype_array[helper_prototype_index].name is null",
helper_prototype_index);
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -343,6 +377,12 @@ ebpf_serialize_program_info(
if (output_buffer_length < *required_length) {
// Output buffer too small.
EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Output buffer is too small",
output_buffer_length,
*required_length);
result = EBPF_INSUFFICIENT_BUFFER;
goto Exit;
}
@ -404,7 +444,7 @@ ebpf_serialize_program_info(
}
Exit:
return result;
EBPF_RETURN_RESULT(result);
}
ebpf_result_t
@ -413,6 +453,7 @@ ebpf_deserialize_program_info(
_In_reads_bytes_(input_buffer_length) const uint8_t* input_buffer,
_Outptr_ ebpf_program_info_t** program_info)
{
EBPF_LOG_ENTRY();
ebpf_result_t result = EBPF_SUCCESS;
ebpf_program_info_t* local_program_info;
const uint8_t* current;
@ -598,5 +639,5 @@ Exit:
ebpf_program_info_free(local_program_info);
}
return result;
EBPF_RETURN_RESULT(result);
}

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

@ -23,6 +23,7 @@ static uint32_t _ebpf_state_cpu_table_size = 0;
ebpf_result_t
ebpf_state_initiate()
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value = EBPF_SUCCESS;
_ebpf_state_next_index = 0;
@ -50,11 +51,11 @@ ebpf_state_initiate()
goto Error;
}
return return_value;
EBPF_RETURN_RESULT(return_value);
Error:
ebpf_state_terminate();
return return_value;
EBPF_RETURN_RESULT(return_value);
}
/**
@ -64,24 +65,28 @@ Error:
void
ebpf_state_terminate()
{
EBPF_LOG_ENTRY();
ebpf_hash_table_destroy(_ebpf_state_thread_table);
ebpf_free_cache_aligned(_ebpf_state_cpu_table);
EBPF_RETURN_VOID();
}
ebpf_result_t
ebpf_state_allocate_index(_Out_ size_t* new_index)
{
EBPF_LOG_ENTRY();
if (_ebpf_state_next_index >= EBPF_MAX_STATE_ENTRIES) {
return EBPF_NO_MEMORY;
EBPF_RETURN_RESULT(EBPF_NO_MEMORY);
}
*new_index = ebpf_interlocked_increment_int64(&_ebpf_state_next_index) - 1;
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
ebpf_result_t
_ebpf_state_get_entry(_Out_ ebpf_state_entry_t** entry)
{
// High frequency call, don't log entry/exit.
ebpf_state_entry_t* local_entry = NULL;
if (!ebpf_is_non_preemptible_work_item_supported() || ebpf_is_preemptible()) {
@ -121,6 +126,7 @@ _ebpf_state_get_entry(_Out_ ebpf_state_entry_t** entry)
ebpf_result_t
ebpf_state_store(size_t index, uintptr_t value)
{
// High frequency call, don't log entry/exit.
ebpf_state_entry_t* entry = NULL;
ebpf_result_t return_value;
@ -134,6 +140,7 @@ ebpf_state_store(size_t index, uintptr_t value)
ebpf_result_t
ebpf_state_load(size_t index, _Out_ uintptr_t* value)
{
// High frequency call, don't log entry/exit.
ebpf_state_entry_t* entry = NULL;
ebpf_result_t return_value;

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

@ -25,6 +25,7 @@ typedef struct _ebpf_trampoline_table
ebpf_result_t
ebpf_allocate_trampoline_table(size_t entry_count, _Outptr_ ebpf_trampoline_table_t** trampoline_table)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_trampoline_table_t* local_trampoline_table = NULL;
@ -48,16 +49,18 @@ Exit:
ebpf_free_trampoline_table(local_trampoline_table);
// Set local_trampoline_table to satisfy the static analyzer.
local_trampoline_table = NULL;
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_free_trampoline_table(_Frees_ptr_opt_ ebpf_trampoline_table_t* trampoline_table)
{
EBPF_LOG_ENTRY();
if (trampoline_table) {
ebpf_unmap_memory(trampoline_table->memory_descriptor);
ebpf_free(trampoline_table);
}
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -67,6 +70,7 @@ ebpf_update_trampoline_table(
_In_reads_(helper_function_count) const uint32_t* helper_function_ids,
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses)
{
EBPF_LOG_ENTRY();
#if defined(_AMD64_)
size_t function_count = helper_function_addresses->helper_function_count;
@ -108,17 +112,18 @@ ebpf_update_trampoline_table(
Exit:
return_value = ebpf_protect_memory(trampoline_table->memory_descriptor, EBPF_PAGE_PROTECT_READ_EXECUTE);
return return_value;
EBPF_RETURN_RESULT(return_value);
#elif
UNREFERENCED_PARAMETER(trampoline_table);
UNREFERENCED_PARAMETER(dispatch_table);
return EBPF_OPERATION_NOT_SUPPORTED;
EBPF_RETURN_RESULT(EBPF_OPERATION_NOT_SUPPORTED);
#endif
}
ebpf_result_t
ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function)
{
EBPF_LOG_ENTRY();
ebpf_trampoline_entry_t* local_entries;
ebpf_result_t return_value;
@ -138,13 +143,14 @@ ebpf_get_trampoline_function(_In_ const ebpf_trampoline_table_t* trampoline_tabl
return_value = EBPF_SUCCESS;
Exit:
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_get_trampoline_helper_address(
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** helper_address)
{
EBPF_LOG_ENTRY();
ebpf_trampoline_entry_t* local_entries;
ebpf_result_t return_value;
@ -164,5 +170,5 @@ ebpf_get_trampoline_helper_address(
return_value = EBPF_SUCCESS;
Exit:
return return_value;
EBPF_RETURN_RESULT(return_value);
}

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

@ -3,6 +3,9 @@
#include "ebpf_platform.h"
// EBPF_RETURN_NTSTATUS(STATUS_SUCCESS) and similar macro invocations trigger C4127.
#pragma warning(disable : 4127) // conditional expression is constant
struct _ebpf_extension_client_binding_context;
typedef struct _ebpf_extension_client
@ -55,24 +58,33 @@ static void
_ebpf_extension_client_notify_change(
ebpf_extension_client_t* client_context, ebpf_extension_client_binding_context_t* client_binding_context)
{
EBPF_LOG_ENTRY();
if (client_context->extension_change_callback)
client_context->extension_change_callback(
client_context->extension_client_context,
client_binding_context->provider_binding_context,
client_binding_context->provider_data);
EBPF_RETURN_VOID();
}
NTSTATUS
_ebpf_extension_client_attach_provider(
HANDLE nmr_binding_handle, void* client_context, const NPI_REGISTRATION_INSTANCE* provider_registration_instance)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)client_context;
ebpf_extension_client_binding_context_t* local_client_binding_context = NULL;
// Only permit one provider to attach.
if (local_client_context->client_binding_context != NULL) {
return STATUS_NOINTERFACE;
status = STATUS_NOINTERFACE;
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Client already attached to provider",
*provider_registration_instance->NpiId)
goto Done;
}
// Check that the interface matches.
@ -80,7 +92,14 @@ _ebpf_extension_client_attach_provider(
provider_registration_instance->NpiId,
&local_client_context->npi_id,
sizeof(local_client_context->npi_id)) != 0) {
return STATUS_NOINTERFACE;
status = STATUS_NOINTERFACE;
EBPF_LOG_MESSAGE_GUID_GUID(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Interface doesn't match",
*provider_registration_instance->NpiId,
local_client_context->npi_id);
goto Done;
}
local_client_binding_context =
@ -109,14 +128,17 @@ _ebpf_extension_client_attach_provider(
if (NT_SUCCESS(status))
_ebpf_extension_client_notify_change(local_client_context, local_client_binding_context);
else
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrClientAttachProvider, status);
Done:
return status;
EBPF_RETURN_NTSTATUS(status);
}
NTSTATUS
_ebpf_extension_client_detach_provider(void* client_binding_context)
{
EBPF_LOG_ENTRY();
ebpf_extension_client_binding_context_t* local_client_binding_context =
(ebpf_extension_client_binding_context_t*)client_binding_context;
ebpf_extension_client_t* local_client_context = local_client_binding_context->extension_client;
@ -130,13 +152,15 @@ _ebpf_extension_client_detach_provider(void* client_binding_context)
ebpf_free(local_client_binding_context);
local_client_context->client_binding_context = NULL;
return STATUS_SUCCESS;
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
}
void
_ebpf_extension_client_cleanup_binding_context(void* client_binding_context)
{
EBPF_LOG_ENTRY();
UNREFERENCED_PARAMETER(client_binding_context);
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -151,6 +175,7 @@ ebpf_extension_load(
_Outptr_opt_ const ebpf_extension_dispatch_table_t** provider_dispatch_table,
_In_opt_ ebpf_extension_change_callback_t extension_changed)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_extension_client_t* local_client_context = NULL;
ebpf_extension_client_binding_context_t* local_client_binding_context = NULL;
@ -202,6 +227,7 @@ ebpf_extension_load(
status = NmrRegisterClient(client_characteristics, local_client_context, &local_client_context->nmr_client_handle);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrRegisterClient, status);
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
goto Done;
}
@ -209,6 +235,11 @@ ebpf_extension_load(
local_client_binding_context = local_client_context->client_binding_context;
if (local_client_binding_context == NULL) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"local_client_context->client_binding_context is NULL",
*interface_id);
ebpf_extension_unload(local_client_context);
local_client_context = NULL;
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
@ -216,6 +247,11 @@ ebpf_extension_load(
}
if (!local_client_binding_context->provider_is_attached) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"local_client_binding_context->provider_is_attached is FALSE",
*interface_id);
ebpf_extension_unload(local_client_context);
local_client_context = NULL;
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
@ -238,26 +274,34 @@ Done:
ebpf_free(local_client_context->client_binding_context);
ebpf_free(local_client_context);
local_client_context = NULL;
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
if (client_context) {
status = NmrDeregisterClient(client_context->nmr_client_handle);
if (status == STATUS_PENDING)
NmrWaitForClientDeregisterComplete(client_context->nmr_client_handle);
if (status == STATUS_PENDING) {
status = NmrWaitForClientDeregisterComplete(client_context->nmr_client_handle);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrWaitForClientDeregisterComplete, status);
}
} else
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrDeregisterClient, status);
}
if (client_context != NULL)
ebpf_free(client_context->client_binding_context);
ebpf_free(client_context);
EBPF_RETURN_VOID();
}
void*
ebpf_extension_get_client_context(_In_ const void* extension_client_binding_context)
{
EBPF_LOG_ENTRY();
void* local_extension_client_context = NULL;
ebpf_extension_client_binding_context_t* local_client_binding_context =
(ebpf_extension_client_binding_context_t*)extension_client_binding_context;
@ -265,7 +309,14 @@ ebpf_extension_get_client_context(_In_ const void* extension_client_binding_cont
if (local_client_context != NULL)
local_extension_client_context = local_client_context->extension_client_context;
return local_extension_client_context;
EBPF_RETURN_POINTER(void*, local_extension_client_context);
}
GUID
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context)
{
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)extension_client_binding_context;
return local_client_context->npi_id;
}
NTSTATUS
@ -278,6 +329,7 @@ _ebpf_extension_provider_attach_client(
void** provider_binding_context,
const void** provider_dispatch)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
ebpf_result_t return_value;
ebpf_extension_provider_t* local_provider_context = (ebpf_extension_provider_t*)provider_context;
@ -288,6 +340,13 @@ _ebpf_extension_provider_attach_client(
client_registration_instance->NpiId,
&local_provider_context->npi_id,
sizeof(local_provider_context->npi_id)) != 0) {
EBPF_LOG_MESSAGE_GUID_GUID(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"Interface doesn't match",
*client_registration_instance->NpiId,
local_provider_context->npi_id);
status = STATUS_NOINTERFACE;
goto Done;
}
@ -313,6 +372,11 @@ _ebpf_extension_provider_attach_client(
(const ebpf_extension_dispatch_table_t*)client_dispatch);
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_WARNING,
EBPF_TRACELOG_KEYWORD_BASE,
"client_attach_callback return failure",
return_value);
status = STATUS_NOINTERFACE;
goto Done;
}
@ -325,12 +389,13 @@ _ebpf_extension_provider_attach_client(
Done:
ebpf_free(local_provider_binding_context);
return status;
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
}
NTSTATUS
_ebpf_extension_provider_detach_client(void* provider_binding_context)
{
EBPF_LOG_ENTRY();
ebpf_extension_provider_binding_context* local_provider_binding_context =
(ebpf_extension_provider_binding_context*)provider_binding_context;
@ -338,13 +403,15 @@ _ebpf_extension_provider_detach_client(void* provider_binding_context)
local_provider_binding_context->client_detach_callback(
local_provider_binding_context->callback_context, &local_provider_binding_context->client_id);
return STATUS_SUCCESS;
EBPF_RETURN_NTSTATUS(STATUS_SUCCESS);
}
void
_ebpf_extension_provider_cleanup_binding_context(void* provider_binding_context)
{
EBPF_LOG_ENTRY();
ebpf_free(provider_binding_context);
EBPF_RETURN_VOID();
}
ebpf_result_t
@ -358,6 +425,7 @@ ebpf_provider_load(
_In_opt_ ebpf_provider_client_attach_callback_t client_attach_callback,
_In_opt_ ebpf_provider_client_detach_callback_t client_detach_callback)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_extension_provider_t* local_provider_context;
NPI_PROVIDER_CHARACTERISTICS* provider_characteristics;
@ -409,6 +477,7 @@ ebpf_provider_load(
provider_characteristics, local_provider_context, &local_provider_context->nmr_provider_handle);
if (!NT_SUCCESS(status)) {
return_value = EBPF_EXTENSION_FAILED_TO_LOAD;
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrRegisterProvider, status);
goto Done;
}
@ -419,18 +488,24 @@ ebpf_provider_load(
Done:
ebpf_free(local_provider_context);
local_provider_context = NULL;
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
if (provider_context) {
status = NmrDeregisterProvider(provider_context->nmr_provider_handle);
if (status == STATUS_PENDING)
NmrWaitForProviderDeregisterComplete(provider_context->nmr_provider_handle);
if (status == STATUS_PENDING) {
status = NmrWaitForProviderDeregisterComplete(provider_context->nmr_provider_handle);
if (!NT_SUCCESS(status))
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrWaitForProviderDeregisterComplete, status);
} else
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NmrDeregisterProvider, status);
}
ebpf_free(provider_context);
EBPF_RETURN_VOID();
}

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

@ -20,6 +20,7 @@ ebpf_handle_table_terminate()
ebpf_result_t
ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
HANDLE file_handle = 0;
OBJECT_ATTRIBUTES object_attributes;
@ -46,12 +47,14 @@ ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
0);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ZwCreateFile, status);
return_value = EBPF_OPERATION_NOT_SUPPORTED;
goto Done;
}
status = ObReferenceObjectByHandle(file_handle, 0, NULL, UserMode, &file_object, NULL);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObReferenceObjectByHandle, status);
return_value = EBPF_OPERATION_NOT_SUPPORTED;
goto Done;
}
@ -69,16 +72,19 @@ Done:
if (file_handle)
ObCloseHandle(file_handle, UserMode);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_handle_close(ebpf_handle_t handle)
{
if (!NT_SUCCESS(ObCloseHandle((HANDLE)handle, UserMode)))
return EBPF_INVALID_OBJECT;
else
return EBPF_SUCCESS;
EBPF_LOG_ENTRY();
NTSTATUS status = ObCloseHandle((HANDLE)handle, UserMode);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObCloseHandle, status);
EBPF_RETURN_RESULT(EBPF_INVALID_OBJECT);
} else
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
ebpf_result_t
@ -91,6 +97,7 @@ ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_
status = ObReferenceObjectByHandle((HANDLE)handle, 0, NULL, UserMode, &file_object, NULL);
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, ObReferenceObjectByHandle, status);
return_value = EBPF_INVALID_OBJECT;
goto Done;
}

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

@ -8,13 +8,6 @@
#include "ebpf_platform.h"
#include <ntstrsafe.h>
#include <wdm.h>
#include <TraceLoggingProvider.h>
TRACELOGGING_DEFINE_PROVIDER(
ebpf_tracelog_provider,
"EbpfForWindowsProvider",
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
typedef struct _ebpf_memory_descriptor
{
@ -40,23 +33,14 @@ static KDEFERRED_ROUTINE _ebpf_timer_routine;
ebpf_result_t
ebpf_platform_initiate()
{
TLG_STATUS status = TraceLoggingRegister(ebpf_tracelog_provider);
if (!NT_SUCCESS(status)) {
return EBPF_NO_MEMORY;
}
return EBPF_SUCCESS;
}
// Prevent tail call optimization of the call to TraceLoggingUnregister to resolve verifier stop C4/DD
// "An attempt was made to unload a driver without calling EtwUnregister".
#pragma optimize("", off)
void
ebpf_platform_terminate()
{
KeFlushQueuedDpcs();
TraceLoggingUnregister(ebpf_tracelog_provider);
}
#pragma optimize("", on)
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
_Post_writable_byte_size_(size) void* ebpf_allocate(size_t size)
@ -106,6 +90,7 @@ ebpf_free_cache_aligned(_Frees_ptr_opt_ void* memory)
ebpf_memory_descriptor_t*
ebpf_map_memory(size_t length)
{
EBPF_LOG_ENTRY();
MDL* memory_descriptor_list = NULL;
PHYSICAL_ADDRESS start_address;
PHYSICAL_ADDRESS end_address;
@ -120,29 +105,35 @@ ebpf_map_memory(size_t length)
void* address =
MmMapLockedPagesSpecifyCache(memory_descriptor_list, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
if (!address) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
MmFreePagesFromMdl(memory_descriptor_list);
ExFreePool(memory_descriptor_list);
memory_descriptor_list = NULL;
}
} else {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmAllocatePagesForMdlEx, STATUS_NO_MEMORY);
}
return (ebpf_memory_descriptor_t*)memory_descriptor_list;
EBPF_RETURN_POINTER(ebpf_memory_descriptor_t*, memory_descriptor_list);
}
void
ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
{
EBPF_LOG_ENTRY();
if (!memory_descriptor)
return;
EBPF_RETURN_VOID();
MmUnmapLockedPages(
ebpf_memory_descriptor_get_base_address(memory_descriptor), &memory_descriptor->memory_descriptor_list);
MmFreePagesFromMdl(&memory_descriptor->memory_descriptor_list);
ExFreePool(memory_descriptor);
EBPF_RETURN_VOID();
}
ebpf_result_t
ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf_page_protection_t protection)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
ULONG mm_protection_state = 0;
switch (protection) {
@ -156,25 +147,32 @@ ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf
mm_protection_state = PAGE_EXECUTE_READ;
break;
default:
return EBPF_INVALID_ARGUMENT;
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
status = MmProtectMdlSystemAddress((MDL*)&memory_descriptor->memory_descriptor_list, mm_protection_state);
if (!NT_SUCCESS(status))
return EBPF_INVALID_ARGUMENT;
if (!NT_SUCCESS(status)) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmProtectMdlSystemAddress, status);
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
void*
ebpf_memory_descriptor_get_base_address(ebpf_memory_descriptor_t* memory_descriptor)
{
return MmGetSystemAddressForMdlSafe(&memory_descriptor->memory_descriptor_list, NormalPagePriority);
void* address = MmGetSystemAddressForMdlSafe(&memory_descriptor->memory_descriptor_list, NormalPagePriority);
if (!address) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmGetSystemAddressForMdlSafe, STATUS_NO_MEMORY);
}
return address;
}
_Ret_maybenull_ ebpf_ring_descriptor_t*
ebpf_allocate_ring_buffer_memory(size_t length)
{
EBPF_LOG_ENTRY();
NTSTATUS status;
size_t requested_page_count = length / PAGE_SIZE;
@ -188,6 +186,11 @@ ebpf_allocate_ring_buffer_memory(size_t length)
if (length % PAGE_SIZE != 0 || length > MAXUINT32 / 2) {
status = STATUS_NO_MEMORY;
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_BASE,
"Ring buffer length doesn't match allocation granularity",
length);
goto Done;
}
@ -207,6 +210,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
FALSE,
NULL);
if (!ring_descriptor->memory_descriptor_list) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, IoAllocateMdl, STATUS_NO_MEMORY);
status = STATUS_NO_MEMORY;
goto Done;
}
@ -224,6 +228,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
ring_descriptor->base_address = MmMapLockedPagesSpecifyCache(
ring_descriptor->memory_descriptor_list, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
if (!ring_descriptor->base_address) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
status = STATUS_NO_MEMORY;
goto Done;
}
@ -244,14 +249,15 @@ Done:
}
}
return ring_descriptor;
EBPF_RETURN_POINTER(ebpf_ring_descriptor_t*, ring_descriptor);
}
void
ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
{
EBPF_LOG_ENTRY();
if (!ring) {
return;
EBPF_RETURN_VOID();
}
MmUnmapLockedPages(ring->base_address, ring->memory_descriptor_list);
@ -259,6 +265,7 @@ ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
IoFreeMdl(ring->memory_descriptor_list);
ebpf_unmap_memory(ring->memory);
ebpf_free(ring);
EBPF_RETURN_VOID();
}
void*
@ -274,6 +281,7 @@ ebpf_ring_map_readonly_user(_In_ ebpf_ring_descriptor_t* ring)
return MmMapLockedPagesSpecifyCache(
ring->memory_descriptor_list, UserMode, MmCached, NULL, FALSE, NormalPagePriority | MdlMappingNoWrite);
} __except (EXCEPTION_EXECUTE_HANDLER) {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MmMapLockedPagesSpecifyCache, STATUS_NO_MEMORY);
return NULL;
}
}
@ -306,11 +314,16 @@ ebpf_get_code_integrity_state(_Out_ ebpf_code_integrity_state_t* state)
status = NtQuerySystemInformation(
SystemCodeIntegrityInformation, &code_integrity_information, system_information_length, &returned_length);
if (NT_SUCCESS(status)) {
*state = (code_integrity_information.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED) != 0
? EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE
: EBPF_CODE_INTEGRITY_DEFAULT;
if ((code_integrity_information.CodeIntegrityOptions & CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED) != 0) {
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity enabled");
*state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
} else {
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity disabled");
*state = EBPF_CODE_INTEGRITY_DEFAULT;
}
return EBPF_SUCCESS;
} else {
EBPF_LOG_NTSTATUS_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, NtQuerySystemInformation, status);
return EBPF_OPERATION_NOT_SUPPORTED;
}
}
@ -564,7 +577,7 @@ ebpf_log_function(_In_ void* context, _In_z_ const char* format_string, ...)
status = RtlStringCchVPrintfA(buffer, sizeof(buffer), format_string, arg_start);
if (NT_SUCCESS(status)) {
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "eBPF: context: %s\n", buffer));
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_ERROR, buffer);
}
va_end(arg_start);

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

@ -11,6 +11,7 @@
#include <ntddk.h>
#include <netioddk.h>
#include <stdint.h>
#include <wdm.h>
#define bool BOOLEAN
#define true 1

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

@ -43,6 +43,7 @@
<ClCompile Include="..\ebpf_async.c" />
<ClCompile Include="..\ebpf_epoch.c" />
<ClCompile Include="..\ebpf_error.c" />
<ClCompile Include="..\ebpf_etw.c" />
<ClCompile Include="..\ebpf_hash_table.c" />
<ClCompile Include="..\ebpf_object.c" />
<ClCompile Include="..\ebpf_pinning_table.c" />

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

@ -61,6 +61,9 @@
<ClCompile Include="..\ebpf_error.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_etw.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\ebpf_epoch.h">

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

@ -7,6 +7,7 @@
typedef struct _ebpf_extension_client
{
GUID npi_id;
GUID client_id;
GUID interface_id;
void* extension_client_context;
@ -41,6 +42,7 @@ ebpf_extension_load(
_Outptr_opt_ const ebpf_extension_dispatch_table_t** provider_dispatch_table,
_In_opt_ ebpf_extension_change_callback_t extension_changed)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_lock_state_t state = 0;
ebpf_extension_provider_t* local_extension_provider = NULL;
@ -76,6 +78,8 @@ ebpf_extension_load(
return_value =
ebpf_hash_table_find(_ebpf_provider_table, (const uint8_t*)interface_id, (uint8_t**)&hash_table_find_result);
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Provider not found", *interface_id);
return_value = EBPF_INVALID_ARGUMENT;
goto Done;
}
@ -87,6 +91,8 @@ ebpf_extension_load(
(const uint8_t*)&local_extension_client,
EBPF_HASH_TABLE_OPERATION_INSERT);
if (return_value != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "ebpf_hash_table_update failed", return_value);
goto Done;
}
@ -122,19 +128,20 @@ Done:
}
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
void
ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_lock_state_t state;
ebpf_extension_provider_t** hash_table_find_result = NULL;
ebpf_extension_provider_t* local_extension_provider = NULL;
if (!client_context)
return;
EBPF_RETURN_VOID();
state = ebpf_lock_lock(&_ebpf_provider_table_lock);
@ -158,6 +165,7 @@ ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context)
Done:
ebpf_free(client_context);
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
EBPF_RETURN_VOID();
}
void*
@ -171,6 +179,13 @@ ebpf_extension_get_client_context(_In_ const void* extension_client_binding_cont
return local_extension_client_context;
}
GUID
ebpf_extension_get_provider_guid(_In_ const void* extension_client_binding_context)
{
ebpf_extension_client_t* local_client_context = (ebpf_extension_client_t*)extension_client_binding_context;
return local_client_context->npi_id;
}
#pragma warning(push)
#pragma warning(disable : 6101) // ebpf_free at exit
ebpf_result_t
@ -184,6 +199,7 @@ ebpf_provider_load(
_In_opt_ ebpf_provider_client_attach_callback_t client_attach_callback,
_In_opt_ ebpf_provider_client_detach_callback_t client_detach_callback)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_lock_state_t state;
ebpf_extension_provider_t* local_extension_provider = NULL;
@ -206,6 +222,9 @@ ebpf_provider_load(
ebpf_hash_table_find(_ebpf_provider_table, (const uint8_t*)interface_id, (uint8_t**)&local_extension_provider);
if (return_value == EBPF_SUCCESS) {
return_value = EBPF_OBJECT_ALREADY_EXISTS;
EBPF_LOG_MESSAGE_GUID(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Provider already loaded", *interface_id);
local_extension_provider = NULL;
goto Done;
}
@ -251,20 +270,21 @@ ebpf_provider_load(
Done:
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
ebpf_free(local_extension_provider);
return return_value;
EBPF_RETURN_RESULT(return_value);
}
#pragma warning(pop)
void
ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context)
{
EBPF_LOG_ENTRY();
ebpf_result_t return_value;
ebpf_lock_state_t state;
ebpf_extension_provider_t* local_extension_provider = NULL;
GUID next_key;
if (!provider_context)
return;
EBPF_RETURN_VOID();
state = ebpf_lock_lock(&_ebpf_provider_table_lock);
@ -283,4 +303,5 @@ ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context
Done:
ebpf_lock_unlock(&_ebpf_provider_table_lock, state);
ebpf_free(local_extension_provider);
EBPF_RETURN_VOID();
}

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

@ -16,28 +16,32 @@ static bool _ebpf_handle_table_initiated = false;
ebpf_result_t
ebpf_handle_table_initiate()
{
EBPF_LOG_ENTRY();
ebpf_lock_create(&_ebpf_handle_table_lock);
memset(_ebpf_handle_table, 0, sizeof(_ebpf_handle_table));
_ebpf_handle_table_initiated = true;
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
void
ebpf_handle_table_terminate()
{
EBPF_LOG_ENTRY();
ebpf_handle_t handle;
if (!_ebpf_handle_table_initiated)
return;
EBPF_RETURN_VOID();
for (handle = 0; handle < EBPF_COUNT_OF(_ebpf_handle_table); handle++) {
ebpf_handle_close(handle);
}
_ebpf_handle_table_initiated = false;
EBPF_RETURN_VOID();
}
ebpf_result_t
ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
{
EBPF_LOG_ENTRY();
ebpf_handle_t new_handle;
ebpf_result_t return_value;
ebpf_lock_state_t state;
@ -60,12 +64,13 @@ ebpf_handle_create(ebpf_handle_t* handle, ebpf_object_t* object)
Done:
ebpf_lock_unlock(&_ebpf_handle_table_lock, state);
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(return_value);
}
ebpf_result_t
ebpf_handle_close(ebpf_handle_t handle)
{
// High volume call - Skip entry/exit logging.
ebpf_lock_state_t state;
ebpf_result_t return_value;
state = ebpf_lock_lock(&_ebpf_handle_table_lock);
@ -85,8 +90,10 @@ ebpf_reference_object_by_handle(ebpf_handle_t handle, ebpf_object_type_t object_
ebpf_result_t return_value;
ebpf_lock_state_t state;
if (handle >= EBPF_COUNT_OF(_ebpf_handle_table))
if (handle >= EBPF_COUNT_OF(_ebpf_handle_table)) {
EBPF_LOG_MESSAGE_UINT64(EBPF_TRACELOG_LEVEL_CRITICAL, EBPF_TRACELOG_KEYWORD_BASE, "Invalid handle", handle);
return EBPF_INVALID_OBJECT;
}
state = ebpf_lock_lock(&_ebpf_handle_table_lock);
if ((_ebpf_handle_table[handle] != NULL) &&

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

@ -11,7 +11,6 @@
#include <stdint.h>
#include <vector>
#include <TraceLoggingProvider.h>
#include <winmeta.h>
// Global variables used to override behavior for testing.
// Permit the test to simulate both Hyper-V Code Integrity.
@ -19,37 +18,28 @@ bool _ebpf_platform_code_integrity_enabled = false;
// Permit the test to simulate non-preemptible execution.
bool _ebpf_platform_is_preemptible = true;
TRACELOGGING_DEFINE_PROVIDER(
ebpf_tracelog_provider,
"EbpfForWindowsProvider",
// {394f321c-5cf4-404c-aa34-4df1428a7f9c}
(0x394f321c, 0x5cf4, 0x404c, 0xaa, 0x34, 0x4d, 0xf1, 0x42, 0x8a, 0x7f, 0x9c));
ebpf_result_t
ebpf_platform_initiate()
{
ULONG result = TraceLoggingRegister(ebpf_tracelog_provider);
if (result != ERROR_SUCCESS) {
return EBPF_NO_MEMORY;
}
return EBPF_SUCCESS;
}
void
ebpf_platform_terminate()
{
TraceLoggingUnregister(ebpf_tracelog_provider);
}
{}
ebpf_result_t
ebpf_get_code_integrity_state(_Out_ ebpf_code_integrity_state_t* state)
{
EBPF_LOG_ENTRY();
if (_ebpf_platform_code_integrity_enabled) {
*state = EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE;
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity enabled");
*state = EBPF_CODE_INTEGRITY_HYPERVISOR_KERNEL_MODE;
} else {
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_BASE, "Code integrity disabled");
*state = EBPF_CODE_INTEGRITY_DEFAULT;
}
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
@ -122,6 +112,7 @@ ebpf_map_memory(size_t length)
descriptor->length = length;
if (!descriptor->base) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc);
free(descriptor);
descriptor = nullptr;
}
@ -132,7 +123,9 @@ void
ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
{
if (memory_descriptor) {
VirtualFree(memory_descriptor->base, 0, MEM_RELEASE);
if (!VirtualFree(memory_descriptor->base, 0, MEM_RELEASE)) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree);
}
free(memory_descriptor);
}
}
@ -143,6 +136,7 @@ ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
_Ret_maybenull_ ebpf_ring_descriptor_t*
ebpf_allocate_ring_buffer_memory(size_t length)
{
EBPF_LOG_ENTRY();
bool result = false;
HANDLE section = nullptr;
SYSTEM_INFO sysInfo;
@ -153,11 +147,17 @@ ebpf_allocate_ring_buffer_memory(size_t length)
GetSystemInfo(&sysInfo);
if ((length % sysInfo.dwAllocationGranularity) != 0) {
if (length == 0) {
EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_BASE, "Ring buffer length is zero");
return nullptr;
}
if (length == 0) {
if ((length % sysInfo.dwAllocationGranularity) != 0) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_BASE,
"Ring buffer length doesn't match allocation granularity",
length);
return nullptr;
}
@ -174,6 +174,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
VirtualAlloc2(nullptr, nullptr, 2 * length, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, nullptr, 0));
if (placeholder1 == nullptr) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc2);
goto Exit;
}
@ -187,6 +188,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
//
result = VirtualFree(placeholder1, length, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
if (result == FALSE) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree);
goto Exit;
}
#pragma warning(pop)
@ -198,6 +200,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
section = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, static_cast<DWORD>(length), nullptr);
if (section == nullptr) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, CreateFileMapping);
goto Exit;
}
@ -207,6 +210,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
view1 =
MapViewOfFile3(section, nullptr, placeholder1, 0, length, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
if (view1 == nullptr) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MapViewOfFile3);
goto Exit;
}
@ -221,6 +225,7 @@ ebpf_allocate_ring_buffer_memory(size_t length)
view2 =
MapViewOfFile3(section, nullptr, placeholder2, 0, length, MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
if (view2 == nullptr) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, MapViewOfFile3);
goto Exit;
}
@ -261,17 +266,19 @@ Exit:
UnmapViewOfFileEx(view2, 0);
}
return descriptor;
EBPF_RETURN_POINTER(ebpf_ring_descriptor_t*, descriptor);
}
void
ebpf_free_ring_buffer_memory(_Frees_ptr_opt_ ebpf_ring_descriptor_t* ring)
{
EBPF_LOG_ENTRY();
if (ring) {
UnmapViewOfFile(ring->primary_view);
UnmapViewOfFile(ring->secondary_view);
ebpf_free(ring);
}
EBPF_RETURN_VOID();
}
void*
@ -283,12 +290,14 @@ ebpf_ring_descriptor_get_base_address(_In_ ebpf_ring_descriptor_t* ring_descript
_Ret_maybenull_ void*
ebpf_ring_map_readonly_user(_In_ ebpf_ring_descriptor_t* ring)
{
return ebpf_ring_descriptor_get_base_address(ring);
EBPF_LOG_ENTRY();
EBPF_RETURN_POINTER(void*, ebpf_ring_descriptor_get_base_address(ring));
}
ebpf_result_t
ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf_page_protection_t protection)
{
EBPF_LOG_ENTRY();
ULONG mm_protection_state = 0;
ULONG old_mm_protection_state = 0;
switch (protection) {
@ -302,15 +311,16 @@ ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf
mm_protection_state = PAGE_EXECUTE_READ;
break;
default:
return EBPF_INVALID_ARGUMENT;
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
if (!VirtualProtect(
memory_descriptor->base, memory_descriptor->length, mm_protection_state, &old_mm_protection_state)) {
return EBPF_INVALID_ARGUMENT;
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualProtect);
EBPF_RETURN_RESULT(EBPF_INVALID_ARGUMENT);
}
return EBPF_SUCCESS;
EBPF_RETURN_RESULT(EBPF_SUCCESS);
}
void*

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

@ -27,6 +27,7 @@
<ClCompile Include="..\ebpf_async.c" />
<ClCompile Include="..\ebpf_epoch.c" />
<ClCompile Include="..\ebpf_error.c" />
<ClCompile Include="..\ebpf_etw.c" />
<ClCompile Include="..\ebpf_hash_table.c" />
<ClCompile Include="..\ebpf_object.c" />
<ClCompile Include="..\ebpf_pinning_table.c" />

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

@ -67,6 +67,9 @@
<ClCompile Include="..\ebpf_error.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ebpf_etw.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Midl Include="..\ebpf_program_types.idl">

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

@ -201,7 +201,7 @@ function Import-ResultsFromVM
foreach($VM in $VMList) {
$VMName = $VM.Name
Write-Log "Importing Testlogs from $VMName"
Write-Log "Importing TestLogs from $VMName"
$TestCredential = New-Credential -Username $Admin -AdminPassword $AdminPassword
$VMSession = New-PSSession -VMName $VMName -Credential $TestCredential
if (!$VMSession) {
@ -214,8 +214,15 @@ function Import-ResultsFromVM
Write-Log ("Copy {0}_{1} from C:\eBPF on test VM to $pwd\TestLogs" -f $VMName, $LogFileName)
Copy-Item -FromSession $VMSession ("C:\eBPF\{0}_{1}" -f $VMName, $LogFileName) -Destination ".\TestLogs" -Recurse -Force -ErrorAction Stop 2>&1 | Write-Log
# Move runner test logs to Testlogs folder.
# Move runner test logs to TestLogs folder.
Move-Item $LogFileName -Destination ".\TestLogs" -Force -ErrorAction Stop 2>&1 | Write-Log
# Copy ETL from Test VM.
$EtlFile = $LogFileName.Substring(0, $LogFileName.IndexOf('.')) + ".etl"
Write-Log ("Copy {0}_{1} from C:\eBPF on test VM to $pwd\TestLogs" -f $VMName, $EtlFile)
Copy-Item -FromSession $VMSession ("C:\eBPF\{0}_{1}" -f $VMName, $EtlFile) -Destination ".\TestLogs" -Recurse -Force -ErrorAction Stop 2>&1 | Write-Log
}
}

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

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: MIT
-->
<WindowsPerformanceRecorder Version="1.0" Author="Microsoft Corporation" Copyright="Microsoft Corporation" Company="Microsoft Corporation">
<Profiles>
<EventCollector Id="EventCollector_EbpfCoreProvider" Name="EbpfCoreProvider">
<BufferSize Value="256" />
<Buffers Value="1024" />
</EventCollector>
<EventProvider Id="ExecutionContext" Name="394f321c-5cf4-404c-aa34-4df1428a7f9c" NonPagedMemory="true"/>
<Profile
Id="EbpfForWindowsProvider.Verbose.File"
Name="EbpfForWindowsProvider"
Description="Traces for all eBPF for Windows providers"
LoggingMode="File"
DetailLevel="Verbose"
Default="true">
<Collectors>
<EventCollectorId Value="EventCollector_EbpfCoreProvider">
<EventProviders>
<EventProviderId Value="ExecutionContext"/>
</EventProviders>
</EventCollectorId>
</Collectors>
</Profile>
</Profiles>
</WindowsPerformanceRecorder>

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

@ -71,6 +71,9 @@ function Register-eBPFComponents
#
function Start-eBPFComponents
{
Write-Log "Starting ETW tracing"
Start-Process -FilePath "wpr.exe" -ArgumentList @("-start", "EbpfForWindows.wprp", "-filemode") -NoNewWindow -Wait
# Start drivers.
$EbpfDrivers.GetEnumerator() | ForEach-Object {
Start-Service $_.Name -ErrorAction Stop | Write-Log
@ -108,4 +111,8 @@ function Stop-eBPFComponents
$EbpfDrivers.GetEnumerator() | ForEach-Object {
Stop-Service $_.Name -ErrorAction Ignore 2>&1 | Write-Log
}
$EtlFile = $LogFileName.Substring(0, $LogFileName.IndexOf('.')) + ".etl";
Write-Log ("Stopping ETW tracing, creating file: " + $EtlFile)
Start-Process -FilePath "wpr.exe" -ArgumentList @("-stop", $EtlFile) -NoNewWindow -Wait
}

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

@ -82,6 +82,10 @@
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</CopyFileToFolders>
<CopyFileToFolders Include="..\ebpfforwindows.wprp">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</CopyFileToFolders>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>