diff --git a/libs/execution_context/ebpf_core.c b/libs/execution_context/ebpf_core.c index 68b93a473..e97b16c02 100644 --- a/libs/execution_context/ebpf_core.c +++ b/libs/execution_context/ebpf_core.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_CORE + #include "ebpf_async.h" #include "ebpf_core.h" #include "ebpf_epoch.h" @@ -278,7 +280,7 @@ ebpf_core_load_code( EBPF_LOG_ENTRY(); ebpf_result_t retval; ebpf_program_t* program = NULL; - retval = ebpf_object_reference_by_handle(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (retval != EBPF_SUCCESS) { goto Done; } @@ -289,7 +291,7 @@ ebpf_core_load_code( } Done: - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); EBPF_RETURN_RESULT(retval); } @@ -345,7 +347,7 @@ ebpf_core_resolve_helper( EBPF_LOG_ENTRY(); ebpf_program_t* program = NULL; ebpf_result_t return_value = - ebpf_object_reference_by_handle(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (return_value != EBPF_SUCCESS) { goto Done; } @@ -361,7 +363,7 @@ ebpf_core_resolve_helper( } Done: - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); EBPF_RETURN_RESULT(return_value); } @@ -427,7 +429,7 @@ ebpf_core_resolve_maps( uint32_t map_index = 0; ebpf_result_t return_value = - ebpf_object_reference_by_handle(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (return_value != EBPF_SUCCESS) { goto Done; } @@ -435,7 +437,7 @@ ebpf_core_resolve_maps( for (map_index = 0; map_index < count_of_maps; map_index++) { ebpf_map_t* map; return_value = - ebpf_object_reference_by_handle(map_handles[map_index], EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + EBPF_OBJECT_REFERENCE_BY_HANDLE(map_handles[map_index], EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (return_value != EBPF_SUCCESS) { goto Done; @@ -449,10 +451,10 @@ ebpf_core_resolve_maps( Done: // Release our reference only after the map has been associated with the program. for (uint32_t map_index2 = 0; map_index2 < map_index; map_index2++) { - ebpf_object_release_reference((ebpf_core_object_t*)map_addresses[map_index2]); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map_addresses[map_index2]); } - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); EBPF_RETURN_RESULT(return_value); } @@ -518,7 +520,7 @@ ebpf_core_create_map( retval = EBPF_SUCCESS; Done: - ebpf_object_release_reference(map_object); + EBPF_OBJECT_RELEASE_REFERENCE(map_object); EBPF_RETURN_RESULT(retval); } @@ -727,7 +729,7 @@ _ebpf_core_protocol_map_find_element( size_t value_length; size_t key_length; - retval = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (retval != EBPF_SUCCESS) { goto Done; } @@ -759,7 +761,7 @@ _ebpf_core_protocol_map_find_element( reply->header.length = reply_length; Done: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(retval); } @@ -772,7 +774,7 @@ _ebpf_core_protocol_map_update_element(_In_ const ebpf_operation_map_update_elem size_t value_length; size_t key_length; - retval = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (retval != EBPF_SUCCESS) { goto Done; } @@ -796,7 +798,7 @@ _ebpf_core_protocol_map_update_element(_In_ const ebpf_operation_map_update_elem map, key_length, request->data, value_length, request->data + key_length, request->option, 0); Done: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(retval); } @@ -809,7 +811,7 @@ _ebpf_core_protocol_map_update_element_with_handle( ebpf_map_t* map = NULL; size_t key_length; - retval = ebpf_object_reference_by_handle(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (retval != EBPF_SUCCESS) { goto Done; } @@ -825,7 +827,7 @@ _ebpf_core_protocol_map_update_element_with_handle( retval = ebpf_map_update_entry_with_handle(map, key_length, request->key, request->value_handle, request->option); Done: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(retval); } @@ -837,7 +839,7 @@ _ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_elem ebpf_map_t* map = NULL; size_t key_length; - retval = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (retval != EBPF_SUCCESS) { goto Done; } @@ -851,7 +853,7 @@ _ebpf_core_protocol_map_delete_element(_In_ const ebpf_operation_map_delete_elem retval = ebpf_map_delete_entry(map, key_length, request->key, 0); Done: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(retval); } @@ -867,7 +869,7 @@ _ebpf_core_protocol_map_get_next_key( size_t previous_key_length; size_t next_key_length; - retval = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (retval != EBPF_SUCCESS) { goto Done; } @@ -904,7 +906,7 @@ _ebpf_core_protocol_map_get_next_key( reply->header.length = reply_length; Done: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(retval); } @@ -938,7 +940,7 @@ _ebpf_core_protocol_program_test_run_complete( } ebpf_async_complete(async_context, reply->header.length, result); - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); ebpf_free((void*)options); } @@ -971,7 +973,7 @@ _ebpf_core_protocol_program_test_run( } retval = - ebpf_object_reference_by_handle(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (retval != EBPF_SUCCESS) { goto Done; } @@ -1002,7 +1004,7 @@ _ebpf_core_protocol_program_test_run( Done: if (retval != EBPF_PENDING) { ebpf_free(options); - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); } EBPF_RETURN_RESULT(retval); } @@ -1021,7 +1023,7 @@ _ebpf_core_protocol_query_program_info( ebpf_utf8_string_t section_name = {0}; ebpf_code_type_t code_type; - retval = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (retval != EBPF_SUCCESS) { goto Done; } @@ -1068,7 +1070,7 @@ Done: ebpf_utf8_string_free(&file_name); ebpf_utf8_string_free(§ion_name); - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); EBPF_RETURN_RESULT(retval); } @@ -1084,7 +1086,7 @@ ebpf_core_update_pinning(const ebpf_handle_t handle, _In_ const ebpf_utf8_string retval = ebpf_pinning_table_delete(_ebpf_core_map_pinning_table, path); goto Done; } else { - retval = ebpf_object_reference_by_handle(handle, EBPF_OBJECT_UNKNOWN, (ebpf_core_object_t**)&object); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(handle, EBPF_OBJECT_UNKNOWN, (ebpf_core_object_t**)&object); if (retval != EBPF_SUCCESS) { goto Done; } @@ -1092,7 +1094,7 @@ ebpf_core_update_pinning(const ebpf_handle_t handle, _In_ const ebpf_utf8_string retval = ebpf_pinning_table_insert(_ebpf_core_map_pinning_table, path, (ebpf_core_object_t*)object); } Done: - ebpf_object_release_reference((ebpf_core_object_t*)object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object); EBPF_RETURN_RESULT(retval); } @@ -1135,7 +1137,7 @@ ebpf_core_get_pinned_object(_In_ const ebpf_utf8_string_t* path, _Out_ ebpf_hand retval = ebpf_handle_create(handle, (ebpf_base_object_t*)object); Done: - ebpf_object_release_reference((ebpf_core_object_t*)object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object); EBPF_RETURN_RESULT(retval); } @@ -1162,7 +1164,7 @@ _ebpf_core_protocol_get_pinned_object( retval = ebpf_core_get_pinned_object(&path, &reply->handle); Done: - ebpf_object_release_reference((ebpf_core_object_t*)object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object); EBPF_RETURN_RESULT(retval); } @@ -1177,7 +1179,7 @@ _ebpf_core_protocol_link_program( ebpf_code_type_t code_type; retval = - ebpf_object_reference_by_handle(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (retval != EBPF_SUCCESS) { goto Done; } @@ -1214,8 +1216,8 @@ Done: if (retval != EBPF_SUCCESS && link) { ebpf_link_detach_program(link); } - ebpf_object_release_reference((ebpf_core_object_t*)program); - ebpf_object_release_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link); EBPF_RETURN_RESULT(retval); } @@ -1246,9 +1248,9 @@ _ebpf_core_find_matching_link( // Enumerate all link objects starting with previous_object. while (TRUE) { struct bpf_link_info info = {0}; - ebpf_object_reference_next_object(previous_object, EBPF_OBJECT_LINK, (ebpf_core_object_t**)&local_link); + EBPF_OBJECT_REFERENCE_NEXT_OBJECT(previous_object, EBPF_OBJECT_LINK, (ebpf_core_object_t**)&local_link); if (previous_object != NULL) { - ebpf_object_release_reference(previous_object); + EBPF_OBJECT_RELEASE_REFERENCE(previous_object); } if (local_link == NULL) { // No more links. @@ -1275,15 +1277,15 @@ _ebpf_core_find_matching_link( // Compare program id. if (program_handle != ebpf_handle_invalid) { ebpf_core_object_t* program = NULL; - result = ebpf_object_reference_by_handle(program_handle, EBPF_OBJECT_PROGRAM, &program); + result = EBPF_OBJECT_REFERENCE_BY_HANDLE(program_handle, EBPF_OBJECT_PROGRAM, &program); if (result != EBPF_SUCCESS) { break; } if (info.prog_id != program->id) { - ebpf_object_release_reference(program); + EBPF_OBJECT_RELEASE_REFERENCE(program); continue; } - ebpf_object_release_reference(program); + EBPF_OBJECT_RELEASE_REFERENCE(program); } match_found = TRUE; @@ -1306,7 +1308,7 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ ebpf_link_t* link = NULL; if (request->link_handle != ebpf_handle_invalid) { - retval = ebpf_object_reference_by_handle(request->link_handle, EBPF_OBJECT_LINK, (ebpf_core_object_t**)&link); + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->link_handle, EBPF_OBJECT_LINK, (ebpf_core_object_t**)&link); if (retval != EBPF_SUCCESS) { goto Done; } @@ -1345,7 +1347,7 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ } Done: - ebpf_object_release_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link); EBPF_RETURN_RESULT(retval); } @@ -1394,7 +1396,7 @@ _ebpf_core_protocol_get_program_info( goto Done; } } else { - retval = ebpf_object_reference_by_handle( + retval = EBPF_OBJECT_REFERENCE_BY_HANDLE( request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (retval != EBPF_SUCCESS) { goto Done; @@ -1422,7 +1424,7 @@ _ebpf_core_protocol_get_program_info( Done: ebpf_program_free_program_info(program_info); - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); EBPF_RETURN_RESULT(retval); } @@ -1555,13 +1557,13 @@ ebpf_core_get_handle_by_id(ebpf_object_type_t type, ebpf_id_t id, _Out_ ebpf_han { EBPF_LOG_ENTRY(); ebpf_core_object_t* object; - ebpf_result_t result = ebpf_object_reference_by_id(id, type, &object); + ebpf_result_t result = EBPF_OBJECT_REFERENCE_BY_ID(id, type, &object); if (result != EBPF_SUCCESS) { return result; } result = ebpf_handle_create(handle, (ebpf_base_object_t*)object); - ebpf_object_release_reference(object); + EBPF_OBJECT_RELEASE_REFERENCE(object); EBPF_RETURN_RESULT(result); } @@ -1676,12 +1678,12 @@ _ebpf_core_protocol_bind_map(_In_ const ebpf_operation_bind_map_request_t* reque ebpf_map_t* map = NULL; result = - ebpf_object_reference_by_handle(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (result != EBPF_SUCCESS) { goto Done; } - result = ebpf_object_reference_by_handle(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + result = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (result != EBPF_SUCCESS) { goto Done; } @@ -1690,10 +1692,10 @@ _ebpf_core_protocol_bind_map(_In_ const ebpf_operation_bind_map_request_t* reque Done: if (program) { - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); } if (map) { - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); } EBPF_RETURN_RESULT(result); } @@ -1708,7 +1710,7 @@ _ebpf_core_protocol_get_object_info( uint16_t info_size = reply_length - FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info); ebpf_core_object_t* object; - ebpf_result_t result = ebpf_object_reference_by_handle(request->handle, EBPF_OBJECT_UNKNOWN, &object); + ebpf_result_t result = EBPF_OBJECT_REFERENCE_BY_HANDLE(request->handle, EBPF_OBJECT_UNKNOWN, &object); if (result != EBPF_SUCCESS) { return result; } @@ -1729,7 +1731,7 @@ _ebpf_core_protocol_get_object_info( if (result == EBPF_SUCCESS) { reply->header.length = FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info) + info_size; } - ebpf_object_release_reference(object); + EBPF_OBJECT_RELEASE_REFERENCE(object); EBPF_RETURN_RESULT(result); } @@ -1742,7 +1744,7 @@ _ebpf_core_protocol_ring_buffer_map_query_buffer( ebpf_map_t* map = NULL; ebpf_result_t result = - ebpf_object_reference_by_handle(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + EBPF_OBJECT_REFERENCE_BY_HANDLE(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (result != EBPF_SUCCESS) { goto Exit; } @@ -1755,7 +1757,7 @@ _ebpf_core_protocol_ring_buffer_map_query_buffer( result = ebpf_ring_buffer_map_query_buffer(map, (uint8_t**)(uintptr_t*)&reply->buffer_address); Exit: - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); EBPF_RETURN_RESULT(result); } @@ -1772,7 +1774,7 @@ _ebpf_core_protocol_ring_buffer_map_async_query( bool reference_taken = FALSE; ebpf_result_t result = - ebpf_object_reference_by_handle(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); + EBPF_OBJECT_REFERENCE_BY_HANDLE(request->map_handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map); if (result != EBPF_SUCCESS) { goto Exit; } @@ -1795,7 +1797,7 @@ _ebpf_core_protocol_ring_buffer_map_async_query( Exit: if (reference_taken) { - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); } return result; } @@ -2494,7 +2496,7 @@ ebpf_core_close_context(_In_opt_ void* context) ebpf_epoch_state_t* epoch_state = ebpf_epoch_enter(); ebpf_core_object_t* object = (ebpf_core_object_t*)context; - object->base.release_reference(object); + EBPF_OBJECT_RELEASE_REFERENCE_INDIRECT((&object->base)); ebpf_epoch_exit(epoch_state); } diff --git a/libs/execution_context/ebpf_link.c b/libs/execution_context/ebpf_link.c index 7b534a8d4..721bbfef8 100644 --- a/libs/execution_context/ebpf_link.c +++ b/libs/execution_context/ebpf_link.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_LINK + #include "ebpf_core.h" #include "ebpf_epoch.h" #include "ebpf_handle.h" @@ -136,7 +138,7 @@ ebpf_link_create( // Note: This must be the last thing done in this function as it inserts the object into the global list. // After this point, the object can be accessed by other threads. - ebpf_result_t result = ebpf_object_initialize(&local_link->object, EBPF_OBJECT_LINK, _ebpf_link_free, NULL); + ebpf_result_t result = EBPF_OBJECT_INITIALIZE(&local_link->object, EBPF_OBJECT_LINK, _ebpf_link_free, NULL); if (result != EBPF_SUCCESS) { retval = EBPF_NO_MEMORY; goto Exit; @@ -310,7 +312,7 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link) ebpf_program_t* program = NULL; bool link_is_detaching = false; - ebpf_object_acquire_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_ACQUIRE_REFERENCE((ebpf_core_object_t*)link); state = ebpf_lock_lock(&link->attach_lock); @@ -351,7 +353,7 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link) ebpf_lock_unlock(&link->attach_lock, state); Done: - ebpf_object_release_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link); EBPF_RETURN_VOID(); } diff --git a/libs/execution_context/ebpf_maps.c b/libs/execution_context/ebpf_maps.c index 3f2172651..c4a0b15d5 100644 --- a/libs/execution_context/ebpf_maps.c +++ b/libs/execution_context/ebpf_maps.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_MAPS + #include "ebpf_async.h" #include "ebpf_bitmap.h" #include "ebpf_epoch.h" @@ -454,7 +456,7 @@ _associate_inner_map(_Inout_ ebpf_core_object_map_t* object_map, ebpf_handle_t i } // Convert value handle to an object pointer. - result = ebpf_object_reference_by_handle(inner_map_handle, EBPF_OBJECT_MAP, &inner_map_template_object); + result = EBPF_OBJECT_REFERENCE_BY_HANDLE(inner_map_handle, EBPF_OBJECT_MAP, &inner_map_template_object); if (result != EBPF_SUCCESS) { EBPF_LOG_MESSAGE_NTSTATUS( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Get object ref by handle failed.", result); @@ -469,7 +471,7 @@ _associate_inner_map(_Inout_ ebpf_core_object_map_t* object_map, ebpf_handle_t i Exit: if (inner_map_template_object) { - ebpf_object_release_reference(inner_map_template_object); + EBPF_OBJECT_RELEASE_REFERENCE(inner_map_template_object); } return result; @@ -482,7 +484,7 @@ _delete_object_array_map(_Inout_ _Post_invalid_ ebpf_core_map_t* map, ebpf_objec for (uint32_t i = 0; i < map->ebpf_map_definition.max_entries; i++) { ebpf_id_t id = *(ebpf_id_t*)&map->data[i * map->ebpf_map_definition.value_size]; if (id) { - ebpf_assert_success(ebpf_object_release_id_reference(id, value_type)); + ebpf_assert_success(EBPF_OBJECT_RELEASE_ID_REFERENCE(id, value_type)); } } @@ -659,7 +661,7 @@ _update_array_map_entry_with_handle( ebpf_core_object_t* value_object = NULL; if (value_handle != (uintptr_t)ebpf_handle_invalid) { - result = ebpf_object_reference_by_handle(value_handle, value_type, &value_object); + result = EBPF_OBJECT_REFERENCE_BY_HANDLE(value_handle, value_type, &value_object); if (result != EBPF_SUCCESS) { EBPF_LOG_MESSAGE_UINT64_UINT64( EBPF_TRACELOG_LEVEL_ERROR, @@ -696,7 +698,7 @@ _update_array_map_entry_with_handle( // Release the reference on the old ID's id table entry. The object may have been already deleted, so an // error return value of 'stale id' is ok. - result = ebpf_object_release_id_reference(old_id, value_type); + result = EBPF_OBJECT_RELEASE_ID_REFERENCE(old_id, value_type); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID); if (result == EBPF_STALE_ID) { result = EBPF_SUCCESS; @@ -707,7 +709,7 @@ _update_array_map_entry_with_handle( // Acquire a reference to the id table entry for the new incoming id. This operation _cannot_ fail as we // already have a valid pointer to the object. A failure here is indicative of a fatal internal error. - ebpf_assert_success(ebpf_object_acquire_id_reference(value_object->id, value_type)); + ebpf_assert_success(EBPF_OBJECT_ACQUIRE_ID_REFERENCE(value_object->id, value_type)); } // Note that this could be an 'update to erase' operation where we don't have a valid (incoming) object. In this @@ -724,7 +726,7 @@ Done: // use the id to get to the object, as and when required. Note that this is with the explicit understanding // that the object may well have been since destroyed by the time we actually need to use this id. This is // perfectly valid and something we need to be prepared for. - ebpf_object_release_reference((ebpf_core_object_t*)value_object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)value_object); } if (locked) { @@ -764,7 +766,7 @@ _delete_array_map_entry_with_reference( if (id) { // The object may have been already deleted, so an error return value of 'stale id' is ok. - result = ebpf_object_release_id_reference(id, value_type); + result = EBPF_OBJECT_RELEASE_ID_REFERENCE(id, value_type); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID); if (result == EBPF_STALE_ID) { result = EBPF_SUCCESS; @@ -819,7 +821,7 @@ _get_object_from_array_map_entry(_Inout_ ebpf_core_map_t* map, _In_ const uint8_ // Note that this call might fail and that's fine. The id might be valid, but the object might have been // since deleted. - (void)ebpf_object_reference_by_id(id, value_type, &object); + (void)EBPF_OBJECT_REFERENCE_BY_ID(id, value_type, &object); } } @@ -921,7 +923,7 @@ _delete_object_hash_map(_In_ _Post_invalid_ ebpf_core_map_t* map) if (id) { // The object may have been already deleted, so an error return value of 'stale id' is ok. - result = ebpf_object_release_id_reference(id, EBPF_OBJECT_MAP); + result = EBPF_OBJECT_RELEASE_ID_REFERENCE(id, EBPF_OBJECT_MAP); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID); if (result == EBPF_STALE_ID) { result = EBPF_SUCCESS; @@ -1300,7 +1302,7 @@ _get_object_from_hash_map_entry(_In_ ebpf_core_map_t* map, _In_ const uint8_t* k uint8_t* value = NULL; if (_find_hash_map_entry(map, key, false, &value) == EBPF_SUCCESS) { ebpf_id_t id = *(ebpf_id_t*)value; - (void)ebpf_object_reference_by_id(id, EBPF_OBJECT_MAP, &object); + (void)EBPF_OBJECT_REFERENCE_BY_ID(id, EBPF_OBJECT_MAP, &object); } ebpf_lock_unlock(&object_map->lock, lock_state); @@ -1390,7 +1392,7 @@ _update_hash_map_entry_with_handle( ebpf_core_object_map_t* object_map = EBPF_FROM_FIELD(ebpf_core_object_map_t, core_map, map); ebpf_core_object_t* value_object = NULL; - result = ebpf_object_reference_by_handle(value_handle, value_type, &value_object); + result = EBPF_OBJECT_REFERENCE_BY_HANDLE(value_handle, value_type, &value_object); if (result != EBPF_SUCCESS) { EBPF_LOG_MESSAGE_UINT64_UINT64( EBPF_TRACELOG_LEVEL_ERROR, @@ -1428,7 +1430,7 @@ _update_hash_map_entry_with_handle( // Release the reference on the old ID's id table entry. The object may already have been deleted, so an // error return value of 'stale id' is ok. - result = ebpf_object_release_id_reference(old_id, value_type); + result = EBPF_OBJECT_RELEASE_ID_REFERENCE(old_id, value_type); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID); if (result == EBPF_STALE_ID) { result = EBPF_SUCCESS; @@ -1446,11 +1448,11 @@ _update_hash_map_entry_with_handle( // Acquire a reference to the id table entry for the new incoming id. This operation _cannot_ fail as we already // have a valid pointer to the object. A failure here is indicative of a fatal internal error. - ebpf_assert_success(ebpf_object_acquire_id_reference(value_object->id, value_type)); + ebpf_assert_success(EBPF_OBJECT_ACQUIRE_ID_REFERENCE(value_object->id, value_type)); Done: if (value_object != NULL) { - ebpf_object_release_reference((ebpf_core_object_t*)value_object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)value_object); } ebpf_lock_unlock(&object_map->lock, lock_state); return result; @@ -1480,7 +1482,7 @@ _delete_map_hash_map_entry(_Inout_ ebpf_core_map_t* map, _In_ const uint8_t* key if (id) { // The object may have been already deleted, so an error return value of 'stale id' is ok. - result = ebpf_object_release_id_reference(id, EBPF_OBJECT_MAP); + result = EBPF_OBJECT_RELEASE_ID_REFERENCE(id, EBPF_OBJECT_MAP); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID); if (result == EBPF_STALE_ID) { result = EBPF_SUCCESS; @@ -2289,7 +2291,7 @@ ebpf_map_create( const ebpf_map_metadata_table_t* table = &ebpf_map_metadata_tables[local_map->ebpf_map_definition.type]; ebpf_object_get_program_type_t get_program_type = (table->get_object_from_entry) ? _get_map_program_type : NULL; - result = ebpf_object_initialize(&local_map->object, EBPF_OBJECT_MAP, _ebpf_map_delete, get_program_type); + result = EBPF_OBJECT_INITIALIZE(&local_map->object, EBPF_OBJECT_MAP, _ebpf_map_delete, get_program_type); if (result != EBPF_SUCCESS) { goto Exit; } @@ -2360,7 +2362,7 @@ ebpf_map_find_entry( // Release the extra reference obtained. // REVIEW: is this safe? if (object) { - ebpf_object_release_reference(object); + EBPF_OBJECT_RELEASE_REFERENCE(object); return_value = (uint8_t*)object; } } else { diff --git a/libs/execution_context/ebpf_native.c b/libs/execution_context/ebpf_native.c index 812e4f24c..621f8326a 100644 --- a/libs/execution_context/ebpf_native.c +++ b/libs/execution_context/ebpf_native.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_NATIVE + #include "ebpf_core.h" #include "ebpf_handle.h" #include "ebpf_native.h" @@ -202,10 +204,10 @@ _ebpf_native_clean_up_programs( for (uint32_t i = 0; i < count_of_programs; i++) { if (programs[i].handle != ebpf_handle_invalid) { ebpf_program_t* program_object = NULL; - ebpf_assert_success(ebpf_object_reference_by_handle( + ebpf_assert_success(EBPF_OBJECT_REFERENCE_BY_HANDLE( programs[i].handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program_object)); ebpf_assert_success(ebpf_program_register_for_helper_changes(program_object, NULL, NULL)); - ebpf_object_release_reference((ebpf_core_object_t*)program_object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program_object); if (close_handles) { ebpf_assert_success(ebpf_handle_close(programs[i].handle)); programs[i].handle = ebpf_handle_invalid; @@ -377,6 +379,23 @@ ebpf_native_terminate() EBPF_RETURN_VOID(); } +void +ebpf_object_update_reference_history(void* object, bool acquire, uint32_t file_id, uint32_t line); + +static void +_ebpf_native_acquire_reference_internal(void* base_object, ebpf_file_id_t file_id, uint32_t line) +{ + ebpf_object_update_reference_history(base_object, true, file_id, line); + ebpf_native_acquire_reference(base_object); +} + +static void +_ebpf_native_release_reference_internal(void* base_object, ebpf_file_id_t file_id, uint32_t line) +{ + ebpf_object_update_reference_history(base_object, false, file_id, line); + ebpf_native_release_reference(base_object); +} + static NTSTATUS _ebpf_native_provider_attach_client_callback( HANDLE nmr_binding_handle, @@ -438,8 +457,8 @@ _ebpf_native_provider_attach_client_callback( ebpf_lock_create(&client_context->lock); client_context->base.marker = _ebpf_native_marker; - client_context->base.acquire_reference = ebpf_native_acquire_reference; - client_context->base.release_reference = ebpf_native_release_reference; + client_context->base.acquire_reference = _ebpf_native_acquire_reference_internal; + client_context->base.release_reference = _ebpf_native_release_reference_internal; // Acquire "attach" reference. Released when detach is called for this module. client_context->base.reference_count = 1; client_context->client_module_id = *client_module_id; @@ -702,7 +721,7 @@ _ebpf_native_validate_map(_In_ const ebpf_native_map_t* map, ebpf_handle_t origi ebpf_core_object_t* object; ebpf_handle_t inner_map_handle = ebpf_handle_invalid; uint16_t info_size = (uint16_t)sizeof(info); - ebpf_result_t result = ebpf_object_reference_by_handle(original_map_handle, EBPF_OBJECT_MAP, &object); + ebpf_result_t result = EBPF_OBJECT_REFERENCE_BY_HANDLE(original_map_handle, EBPF_OBJECT_MAP, &object); if (result != EBPF_SUCCESS) { goto Exit; } @@ -743,7 +762,7 @@ _ebpf_native_validate_map(_In_ const ebpf_native_map_t* map, ebpf_handle_t origi } Exit: - ebpf_object_release_reference(object); + EBPF_OBJECT_RELEASE_REFERENCE(object); EBPF_RETURN_RESULT(result); } @@ -1163,7 +1182,7 @@ _ebpf_native_load_programs(_Inout_ ebpf_native_module_t* module) context->native_program = native_program; ebpf_program_t* program_object = NULL; - result = ebpf_object_reference_by_handle( + result = EBPF_OBJECT_REFERENCE_BY_HANDLE( native_program->handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program_object); if (result != EBPF_SUCCESS) { ebpf_free(context); @@ -1172,7 +1191,7 @@ _ebpf_native_load_programs(_Inout_ ebpf_native_module_t* module) result = ebpf_program_register_for_helper_changes(program_object, _ebpf_native_helper_address_changed, context); - ebpf_object_release_reference((ebpf_core_object_t*)program_object); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program_object); if (result != EBPF_SUCCESS) { ebpf_free(context); diff --git a/libs/execution_context/ebpf_program.c b/libs/execution_context/ebpf_program.c index 06c412a45..30993c1fa 100644 --- a/libs/execution_context/ebpf_program.c +++ b/libs/execution_context/ebpf_program.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_PROGRAM + #include "bpf_helpers.h" #include "ebpf_async.h" #include "ebpf_core.h" @@ -252,7 +254,7 @@ _ebpf_program_free(_In_opt_ _Post_invalid_ ebpf_core_object_t* object) ebpf_assert(ebpf_list_is_empty(&program->links)); for (index = 0; index < program->count_of_maps; index++) { - ebpf_object_release_reference((ebpf_core_object_t*)program->maps[index]); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program->maps[index]); } ebpf_epoch_work_item_t* cleanup_work_item = program->cleanup_work_item; @@ -530,7 +532,7 @@ ebpf_program_create(_In_ const ebpf_program_parameters_t* program_parameters, _O // Note: This is performed after initializing the program as it inserts the program into the global list. // From this point on, the program can be found by other threads. - retval = ebpf_object_initialize( + retval = EBPF_OBJECT_INITIALIZE( &local_program->object, EBPF_OBJECT_PROGRAM, _ebpf_program_free, _ebpf_program_get_program_type); if (retval != EBPF_SUCCESS) { goto Done; @@ -589,7 +591,7 @@ ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map) goto Done; } - ebpf_object_acquire_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_ACQUIRE_REFERENCE((ebpf_core_object_t*)map); program_maps[map_count - 1] = map; program->maps = program_maps; program->count_of_maps = map_count; @@ -631,7 +633,7 @@ ebpf_program_associate_maps(ebpf_program_t* program, ebpf_map_t** maps, uint32_t program_maps = NULL; program->count_of_maps = maps_count; for (index = 0; index < maps_count; index++) { - ebpf_object_acquire_reference((ebpf_core_object_t*)program->maps[index]); + EBPF_OBJECT_ACQUIRE_REFERENCE((ebpf_core_object_t*)program->maps[index]); } ebpf_lock_unlock(&program->lock, state); @@ -1147,7 +1149,7 @@ ebpf_program_invoke( } if (state.count != 0) { - ebpf_object_release_reference((ebpf_core_object_t*)current_program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)current_program); current_program = NULL; } @@ -1447,7 +1449,7 @@ ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l { EBPF_LOG_ENTRY(); // Acquire "attach" reference on the link object. - ebpf_object_acquire_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_ACQUIRE_REFERENCE((ebpf_core_object_t*)link); // Insert the link in the attach list. ebpf_lock_state_t state; @@ -1470,7 +1472,7 @@ ebpf_program_detach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l ebpf_lock_unlock(&program->lock, state); // Release the "attach" reference. - ebpf_object_release_reference((ebpf_core_object_t*)link); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link); EBPF_RETURN_VOID(); } @@ -1549,7 +1551,7 @@ ebpf_program_create_and_initialize( } Done: - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); return retval; } diff --git a/libs/execution_context/unit/execution_context_unit_test.cpp b/libs/execution_context/unit/execution_context_unit_test.cpp index db058aa87..627e29cb0 100644 --- a/libs/execution_context/unit/execution_context_unit_test.cpp +++ b/libs/execution_context/unit/execution_context_unit_test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_EXECUTION_CONTEXT_UNIT_TESTS + #include "catch_wrapper.hpp" #include "ebpf_async.h" #include "ebpf_core.h" @@ -101,7 +103,7 @@ template class ebpf_object_deleter void operator()(T* object) { - ebpf_object_release_reference(reinterpret_cast(object)); + EBPF_OBJECT_RELEASE_REFERENCE(reinterpret_cast(object)); } }; diff --git a/libs/platform/ebpf_handle.h b/libs/platform/ebpf_handle.h index ce7dd9fc7..c4618fa50 100644 --- a/libs/platform/ebpf_handle.h +++ b/libs/platform/ebpf_handle.h @@ -57,6 +57,8 @@ extern "C" * * @param[in] handle Handle to find in table. * @param[out] object Pointer to memory that contains object success. + * @param[in] file_id File ID of the caller. + * @param[in] line Line number of the caller. * @retval EBPF_SUCCESS The operation was successful. * @retval EBPF_INVALID_OBJECT The provided handle is not valid. */ @@ -64,7 +66,9 @@ extern "C" ebpf_handle_t handle, _In_opt_ ebpf_compare_object_t compare_function, _In_opt_ const void* context, - _Outptr_ struct _ebpf_base_object** object); + _Outptr_ struct _ebpf_base_object** object, + uint32_t file_id, + uint32_t line); #ifdef __cplusplus } diff --git a/libs/platform/ebpf_object.c b/libs/platform/ebpf_object.c index 225be66c3..ad9397357 100644 --- a/libs/platform/ebpf_object.c +++ b/libs/platform/ebpf_object.c @@ -74,6 +74,70 @@ typedef struct _ebpf_id_entry // case this becomes a hash table. static _Guarded_by_(_ebpf_object_tracking_list_lock) ebpf_id_entry_t _ebpf_id_table[1024]; +/** + * @brief An enum of operations that can be performed on an object reference. + */ +typedef enum _ebpf_object_reference_operationEBPF_OBJECT_INITIALIZE +{ + EBPF_OBJECT_CREATE, + EBPF_OBJECT_ACQUIRE, + EBPF_OBJECT_RELEASE, + EBPF_OBJECT_DESTROY, +} ebpf_object_reference_operation_t; + +/** + * @brief A history of object references. This is used to track + * down the source of a reference leak and use after free bugs. + * This is a circular buffer of the last 1024 references with the + * next index to write to stored in _ebpf_object_reference_history_index. + */ +static _Guarded_by_(_ebpf_object_reference_history_lock) struct _ebpf_object_reference_entry +{ + uintptr_t object : 64; + ebpf_file_id_t file_id : 16; + unsigned int line : 32; + ebpf_object_reference_operation_t operation : 16; +} _ebpf_object_reference_history[1024]; + +/** + * @brief The index of the next entry to write to in the reference history. + * This is updated atomically using interlocked operations and should be used + * modulo count of _ebpf_object_reference_history. + */ +static _Guarded_by_(_ebpf_object_reference_history_lock) size_t _ebpf_object_reference_history_index = 0; + +static ebpf_lock_t _ebpf_object_reference_history_lock = {0}; + +static inline void +_update_reference_history(void* object, ebpf_object_reference_operation_t operation, uint32_t file_id, uint32_t line) +{ + ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_reference_history_lock); + + size_t index = _ebpf_object_reference_history_index++; + index %= EBPF_COUNT_OF(_ebpf_object_reference_history); + + _ebpf_object_reference_history[index].object = (uintptr_t)object; + _ebpf_object_reference_history[index].operation = operation; + _ebpf_object_reference_history[index].file_id = file_id; + _ebpf_object_reference_history[index].line = line; + + ebpf_lock_unlock(&_ebpf_object_reference_history_lock, state); +} + +/** + * @brief Add an entry to the reference history. + * + * @param[in] object Object being referenced. + * @param[in] acquire True if this is an acquire reference, false if it is a release reference. + * @param[in] file_id Id of the file where the reference was acquired or released. + * @param[in] line Line number in the file where the reference was acquired or released. + */ +void +ebpf_object_update_reference_history(void* object, bool acquire, uint32_t file_id, uint32_t line) +{ + _update_reference_history(object, acquire ? EBPF_OBJECT_ACQUIRE : EBPF_OBJECT_RELEASE, file_id, line); +} + // Get the ID last stored at a given index. static inline ebpf_id_t _get_id_from_index(uint32_t index) @@ -102,7 +166,7 @@ _get_index_from_id(ebpf_id_t id, _Out_ uint32_t* index) } static ebpf_result_t -_ebpf_object_tracking_list_insert(_Inout_ ebpf_core_object_t* object) +_ebpf_object_tracking_list_insert(_Inout_ ebpf_core_object_t* object, ebpf_file_id_t file_id, uint32_t line) { int new_index; ebpf_result_t return_value; @@ -122,6 +186,7 @@ _ebpf_object_tracking_list_insert(_Inout_ ebpf_core_object_t* object) _ebpf_id_table[new_index].counter++; _ebpf_id_table[new_index].reference_count = 1; _ebpf_id_table[new_index].object = object; + _update_reference_history(&_ebpf_id_table[new_index], EBPF_OBJECT_CREATE, file_id, line); object->id = _get_id_from_index(new_index); return_value = EBPF_SUCCESS; @@ -133,7 +198,7 @@ Done: } _Requires_lock_held_(&_ebpf_object_tracking_list_lock) static void _ebpf_object_tracking_list_remove( - _In_ const ebpf_core_object_t* object) + _In_ const ebpf_core_object_t* object, ebpf_file_id_t file_id, uint32_t line) { uint32_t index; ebpf_result_t return_value = _get_index_from_id(object->id, &index); @@ -144,6 +209,7 @@ _Requires_lock_held_(&_ebpf_object_tracking_list_lock) static void _ebpf_object_ // Under lock, so un-protected access is ok. _ebpf_id_table[index].reference_count--; + _update_reference_history(&_ebpf_id_table[index], EBPF_OBJECT_RELEASE, file_id, line); ebpf_assert(_ebpf_id_table[index].reference_count >= 0); _ebpf_id_table[index].object = NULL; } @@ -153,6 +219,8 @@ ebpf_object_tracking_initiate() { ebpf_lock_create(&_ebpf_object_tracking_list_lock); memset(_ebpf_id_table, 0, sizeof(_ebpf_id_table)); + memset(_ebpf_object_reference_history, 0, sizeof(_ebpf_object_reference_history)); + _ebpf_object_reference_history_index = 0; } void @@ -169,7 +237,9 @@ ebpf_object_initialize( _Inout_ ebpf_core_object_t* object, ebpf_object_type_t object_type, ebpf_free_object_t free_function, - ebpf_object_get_program_type_t get_program_type_function) + ebpf_object_get_program_type_t get_program_type_function, + ebpf_file_id_t file_id, + uint32_t line) { EBPF_LOG_MESSAGE_POINTER_ENUM( EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object initialized", object, object_type); @@ -181,13 +251,15 @@ ebpf_object_initialize( object->free_function = free_function; object->get_program_type = get_program_type_function; ebpf_list_initialize(&object->object_list_entry); + _update_reference_history(object, EBPF_OBJECT_CREATE, file_id, line); - return _ebpf_object_tracking_list_insert(object); + return _ebpf_object_tracking_list_insert(object, file_id, line); } void -ebpf_object_acquire_reference(_Inout_ ebpf_core_object_t* object) +ebpf_object_acquire_reference(_Inout_ ebpf_core_object_t* object, uint32_t file_id, uint32_t line) { + _update_reference_history(object, EBPF_OBJECT_ACQUIRE, file_id, line); if (object->base.marker != _ebpf_object_marker) { __fastfail(FAST_FAIL_INVALID_ARG); } @@ -206,7 +278,7 @@ ebpf_object_acquire_reference(_Inout_ ebpf_core_object_t* object) * @retval false Reference was not acquired. */ static bool -_ebpf_object_try_acquire_reference(_Inout_ ebpf_base_object_t* object) +_ebpf_object_try_acquire_reference(_Inout_ ebpf_base_object_t* object, uint32_t file_id, uint32_t line) { if (object->marker != _ebpf_object_marker) { __fastfail(FAST_FAIL_INVALID_ARG); @@ -224,15 +296,17 @@ _ebpf_object_try_acquire_reference(_Inout_ ebpf_base_object_t* object) if (ebpf_interlocked_compare_exchange_int64(&object->reference_count, new_ref_count + 1, new_ref_count) == new_ref_count) { + _update_reference_history(object, EBPF_OBJECT_ACQUIRE, file_id, line); return true; } } } void -ebpf_object_release_reference(_Inout_opt_ ebpf_core_object_t* object) +ebpf_object_release_reference(_Inout_opt_ ebpf_core_object_t* object, uint32_t file_id, uint32_t line) { int64_t new_ref_count; + _update_reference_history(object, EBPF_OBJECT_RELEASE, file_id, line); if (!object) { return; @@ -254,12 +328,13 @@ ebpf_object_release_reference(_Inout_opt_ ebpf_core_object_t* object) ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock); 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); + _ebpf_object_tracking_list_remove(object, file_id, line); ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); } // Free the object outside the lock. if (new_ref_count == 0) { + _update_reference_history(object, EBPF_OBJECT_DESTROY, file_id, line); object->base.marker = ~object->base.marker; object->free_function(object); } @@ -340,7 +415,9 @@ void ebpf_object_reference_next_object( _In_opt_ const ebpf_core_object_t* previous_object, ebpf_object_type_t type, - _Outptr_result_maybenull_ ebpf_core_object_t** next_object) + _Outptr_result_maybenull_ ebpf_core_object_t** next_object, + uint32_t file_id, + uint32_t line) { ebpf_result_t return_value = EBPF_SUCCESS; ebpf_lock_state_t state; @@ -362,7 +439,7 @@ ebpf_object_reference_next_object( if (_ebpf_id_table[index].object == NULL) { continue; } - if (!_ebpf_object_try_acquire_reference(&_ebpf_id_table[index].object->base)) { + if (!_ebpf_object_try_acquire_reference(&_ebpf_id_table[index].object->base, file_id, line)) { continue; } *next_object = _ebpf_id_table[index].object; @@ -370,10 +447,14 @@ ebpf_object_reference_next_object( } ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); + if (*next_object != NULL) { + _update_reference_history(*next_object, EBPF_OBJECT_ACQUIRE, file_id, line); + } } _Must_inspect_result_ ebpf_result_t -ebpf_object_reference_by_id(ebpf_id_t id, ebpf_object_type_t object_type, _Outptr_ ebpf_core_object_t** object) +ebpf_object_reference_by_id( + ebpf_id_t id, ebpf_object_type_t object_type, _Outptr_ ebpf_core_object_t** object, uint32_t file_id, uint32_t line) { ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock); @@ -385,7 +466,7 @@ ebpf_object_reference_by_id(ebpf_id_t id, ebpf_object_type_t object_type, _Outpt } else { ebpf_core_object_t* found = _ebpf_id_table[index].object; if ((found != NULL) && (found->type == object_type)) { - if (_ebpf_object_try_acquire_reference(&found->base)) { + if (_ebpf_object_try_acquire_reference(&found->base, file_id, line)) { *object = found; } else { return_value = EBPF_KEY_NOT_FOUND; @@ -397,6 +478,9 @@ ebpf_object_reference_by_id(ebpf_id_t id, ebpf_object_type_t object_type, _Outpt } ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); + if (return_value == EBPF_SUCCESS) { + _update_reference_history(*object, EBPF_OBJECT_ACQUIRE, file_id, line); + } return return_value; } @@ -421,10 +505,14 @@ _ebpf_object_compare(_In_ const ebpf_base_object_t* object, _In_ const void* con ebpf_result_t ebpf_object_reference_by_handle( - ebpf_handle_t handle, ebpf_object_type_t object_type, _Outptr_ ebpf_core_object_t** object) + ebpf_handle_t handle, + ebpf_object_type_t object_type, + _Outptr_ ebpf_core_object_t** object, + uint32_t file_id, + uint32_t line) { return ebpf_reference_base_object_by_handle( - handle, _ebpf_object_compare, &object_type, (ebpf_base_object_t**)object); + handle, _ebpf_object_compare, &object_type, (ebpf_base_object_t**)object, file_id, line); } _Must_inspect_result_ char* @@ -440,7 +528,7 @@ ebpf_duplicate_string(_In_z_ const char* source) } _Must_inspect_result_ ebpf_result_t -ebpf_object_acquire_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) +ebpf_object_acquire_id_reference(ebpf_id_t id, ebpf_object_type_t object_type, uint32_t file_id, uint32_t line) { ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock); @@ -451,20 +539,8 @@ ebpf_object_acquire_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) } ebpf_id_entry_t* entry = &_ebpf_id_table[index]; - ebpf_assert(entry->reference_count); - if (entry->reference_count == 0) { - if (entry->object == NULL) { - - // Do not allow access to entries that are not in use. - result = EBPF_INVALID_ARGUMENT; - } else { - - // This can _never_ happen. If the object pointer is not null, the ref-count HAS TO BE _at_ _least_ 1. - // This conditon is indicative of a severe internal error. - ebpf_assert(0); - result = EBPF_FAILED; - } - goto Done; + if (entry->reference_count <= 0) { + __fastfail(FAST_FAIL_INVALID_REFERENCE_COUNT); } // ref count is non-zero @@ -487,6 +563,7 @@ ebpf_object_acquire_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) // We're under lock so un-protected access is ok. entry->reference_count++; result = EBPF_SUCCESS; + _update_reference_history(entry, EBPF_OBJECT_ACQUIRE, file_id, line); Done: ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); @@ -494,7 +571,7 @@ Done: } _Must_inspect_result_ ebpf_result_t -ebpf_object_release_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) +ebpf_object_release_id_reference(ebpf_id_t id, ebpf_object_type_t object_type, uint32_t file_id, uint32_t line) { ebpf_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock); @@ -505,19 +582,8 @@ ebpf_object_release_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) } ebpf_id_entry_t* entry = &_ebpf_id_table[index]; - ebpf_assert(entry->reference_count); - if (entry->reference_count == 0) { - if (entry->object == NULL) { - - // Do not allow access to entries that are not in use. - result = EBPF_INVALID_ARGUMENT; - } else { - - // This can _never_ happen. If the object pointer is not null, the ref-count HAS TO BE _at_ _least_ 1. - // This condition is indicative of a severe internal error. - result = EBPF_FAILED; - } - goto Done; + if (entry->reference_count <= 0) { + __fastfail(FAST_FAIL_INVALID_REFERENCE_COUNT); } // ref count is non-zero @@ -537,8 +603,10 @@ ebpf_object_release_id_reference(ebpf_id_t id, ebpf_object_type_t object_type) entry->reference_count--; ebpf_assert(entry->reference_count >= 0); result = EBPF_SUCCESS; + _update_reference_history(entry, EBPF_OBJECT_RELEASE, file_id, line); Done: ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); + return result; } diff --git a/libs/platform/ebpf_object.h b/libs/platform/ebpf_object.h index 2371035ef..aac114ac4 100644 --- a/libs/platform/ebpf_object.h +++ b/libs/platform/ebpf_object.h @@ -9,6 +9,100 @@ extern "C" { #endif + /** + * @brief Identifier for the file that is referencing the object. Each file that references an object is assigned + * a unique identifier. This identifier is used to track the reference count of the object. The file identifier is + * recorded in the _ebpf_object_reference_history table along with the line number of the reference. This allows + * for tracking down use-after-free bugs and leaks of objects. + */ + typedef enum _ebpf_file_id + { + EBPF_FILE_ID_UNKNOWN, + EBPF_FILE_ID_CORE, + EBPF_FILE_ID_MAPS, + EBPF_FILE_ID_LINK, + EBPF_FILE_ID_PROGRAM, + EBPF_FILE_ID_NATIVE, + EBPF_FILE_ID_PINNING_TABLE, + EBPF_FILE_ID_HANDLE, + EBPF_FILE_ID_EXECUTION_CONTEXT_UNIT_TESTS, + EBPF_FILE_ID_PLATFORM_UNIT_TESTS, + EBPF_FILE_ID_PERFORMANCE_TESTS, + EBPF_FILE_ID_CORE_HELPER_FUZZER, + } ebpf_file_id_t; + +/** + * @brief Macro to acquire a reference on an object and record the file and line number of the reference. + */ +#define EBPF_OBJECT_ACQUIRE_REFERENCE(object) ebpf_object_acquire_reference(object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to release a reference on an object and record the file and line number of the reference. + */ +#define EBPF_OBJECT_RELEASE_REFERENCE(object) ebpf_object_release_reference(object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to locate the next object in the object list and acquire a reference on it and record the file and + * line number of the reference. + */ +#define EBPF_OBJECT_REFERENCE_NEXT_OBJECT(object, type, next_object) \ + ebpf_object_reference_next_object(object, type, next_object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to locate an object by its ID and acquire a reference on it and record the file and line number of + * the reference. + */ +#define EBPF_OBJECT_REFERENCE_BY_ID(object_id, type, object) \ + ebpf_object_reference_by_id(object_id, type, object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to locate an object by its handle and acquire a reference on it and record the file and line number + * of the reference. + */ +#define EBPF_OBJECT_REFERENCE_BY_HANDLE(object_handle, type, object) \ + ebpf_object_reference_by_handle(object_handle, type, object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to acquire a reference on an object ID and record the file and line number of the reference. + * + */ +#define EBPF_OBJECT_ACQUIRE_ID_REFERENCE(object_id, type) \ + ebpf_object_acquire_id_reference(object_id, type, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to release a reference on an object ID and record the file and line number of the reference. + * + */ +#define EBPF_OBJECT_RELEASE_ID_REFERENCE(object_id, type) \ + ebpf_object_release_id_reference(object_id, type, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to acquire a reference on an object via it's function pointers and record the file and line number + * of the reference. + */ +#define EBPF_OBJECT_ACQUIRE_REFERENCE_INDIRECT(base_object) \ + base_object->acquire_reference(base_object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to release a reference on an object via it's function pointers and record the file and line number + * of the reference. + */ +#define EBPF_OBJECT_RELEASE_REFERENCE_INDIRECT(base_object) \ + base_object->release_reference(base_object, EBPF_FILE_ID, __LINE__) + +/** + * @brief Macro to initialize an object and record the file and line number of the reference. + *EBPF_OBJECT_INITIALIZE + */ +#define EBPF_OBJECT_INITIALIZE(object, object_type, free_function, get_program_type_function) \ + ebpf_object_initialize( \ + (ebpf_core_object_t*)(object), \ + (object_type), \ + (free_function), \ + (get_program_type_function), \ + EBPF_FILE_ID, \ + __LINE__) + typedef enum _ebpf_object_type { EBPF_OBJECT_UNKNOWN, @@ -18,8 +112,8 @@ extern "C" } ebpf_object_type_t; typedef struct _ebpf_base_object ebpf_base_object_t; - typedef void (*ebpf_base_release_reference_t)(_Inout_ void* base_object); - typedef void (*ebpf_base_acquire_reference_t)(_Inout_ void* base_object); + typedef void (*ebpf_base_release_reference_t)(_Inout_ void* base_object, ebpf_file_id_t file_id, uint32_t line); + typedef void (*ebpf_base_acquire_reference_t)(_Inout_ void* base_object, ebpf_file_id_t file_id, uint32_t line); typedef struct _ebpf_core_object ebpf_core_object_t; typedef void (*ebpf_free_object_t)(ebpf_core_object_t* object); @@ -80,6 +174,8 @@ extern "C" * @param[in] object_type The type of the object. * @param[in] free_function The function used to free the object. * @param[in] get_program_type_function The function used to get a program type, or NULL. Each program + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * has a program type, and hence so do maps that can contain programs, whether directly (like * BPF_MAP_TYPE_PROG_ARRAY) or indirectly (like BPF_MAP_TYPE_ARRAY_OF_MAPS containing a BPF_MAP_TYPE_PROG_ARRAY). * @retval EBPF_SUCCESS Initialization succeeded. @@ -90,24 +186,30 @@ extern "C" _Inout_ ebpf_core_object_t* object, ebpf_object_type_t object_type, ebpf_free_object_t free_function, - ebpf_object_get_program_type_t get_program_type_function); + ebpf_object_get_program_type_t get_program_type_function, + ebpf_file_id_t file_id, + uint32_t line); /** * @brief Acquire a reference to this object. * * @param[in,out] object Object on which to acquire a reference. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. */ void - ebpf_object_acquire_reference(_Inout_ ebpf_core_object_t* object); + ebpf_object_acquire_reference(_Inout_ ebpf_core_object_t* object, ebpf_file_id_t file_id, uint32_t line); /** * @brief Release a reference on this object. If the reference count reaches * zero, the free_function is invoked on the object. * * @param[in,out] object Object on which to release a reference. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. */ void - ebpf_object_release_reference(_Inout_opt_ ebpf_core_object_t* object); + ebpf_object_release_reference(_Inout_opt_ ebpf_core_object_t* object, ebpf_file_id_t file_id, uint32_t line); /** * @brief Query the stored type of the object. @@ -126,13 +228,17 @@ extern "C" * to find first object. * @param[in] type Type of object to find. * @param[out] next_object Pointer to memory containing the next object or + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * NULL if there are no more objects of that type. */ void ebpf_object_reference_next_object( _In_opt_ const ebpf_core_object_t* previous_object, ebpf_object_type_t type, - _Outptr_result_maybenull_ ebpf_core_object_t** next_object); + _Outptr_result_maybenull_ ebpf_core_object_t** next_object, + ebpf_file_id_t file_id, + uint32_t line); /** * @brief Find an ID in the ID table, verify the type matches, @@ -141,11 +247,18 @@ extern "C" * @param[in] id ID to find in table. * @param[in] object_type Object type to match. * @param[out] object Pointer to memory that contains object success. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * @retval EBPF_SUCCESS The operation was successful. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. */ _Must_inspect_result_ ebpf_result_t - ebpf_object_reference_by_id(ebpf_id_t id, ebpf_object_type_t object_type, _Outptr_ ebpf_core_object_t** object); + ebpf_object_reference_by_id( + ebpf_id_t id, + ebpf_object_type_t object_type, + _Outptr_ ebpf_core_object_t** object, + ebpf_file_id_t file_id, + uint32_t line); /** * @brief Find the object of a given type with the next ID greater than a given ID. @@ -165,12 +278,18 @@ extern "C" * @param[in] handle Handle to find in table. * @param[in] object_type Object type to match. * @param[out] object Pointer to memory that contains object success. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * @retval EBPF_SUCCESS The operation was successful. * @retval EBPF_INVALID_OBJECT The provided handle is not valid. */ ebpf_result_t ebpf_object_reference_by_handle( - ebpf_handle_t handle, ebpf_object_type_t object_type, _Outptr_ struct _ebpf_core_object** object); + ebpf_handle_t handle, + ebpf_object_type_t object_type, + _Outptr_ struct _ebpf_core_object** object, + ebpf_file_id_t file_id, + uint32_t line); /** * @brief Find an ID in the ID table, verify the type matches, @@ -179,11 +298,14 @@ extern "C" * * @param[in] id ID to find in table. * @param[in] object_type Object type to match. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * @retval EBPF_SUCCESS The operation was successful. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. */ _Must_inspect_result_ ebpf_result_t - ebpf_object_acquire_id_reference(ebpf_id_t start_id, ebpf_object_type_t object_type); + ebpf_object_acquire_id_reference( + ebpf_id_t start_id, ebpf_object_type_t object_type, ebpf_file_id_t file_id, uint32_t line); /** * @brief Find an ID in the ID table, verify the type matches, @@ -192,11 +314,14 @@ extern "C" * * @param[in] id ID to find in table. * @param[in] object_type Object type to match. + * @param[in] file_id The file ID of the caller. + * @param[in] line The line number of the caller. * @retval EBPF_SUCCESS The operation was successful. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. */ _Must_inspect_result_ ebpf_result_t - ebpf_object_release_id_reference(ebpf_id_t start_id, ebpf_object_type_t object_type); + ebpf_object_release_id_reference( + ebpf_id_t start_id, ebpf_object_type_t object_type, ebpf_file_id_t file_id, uint32_t line); #ifdef __cplusplus } diff --git a/libs/platform/ebpf_pinning_table.c b/libs/platform/ebpf_pinning_table.c index 000ad0222..d3193192a 100644 --- a/libs/platform/ebpf_pinning_table.c +++ b/libs/platform/ebpf_pinning_table.c @@ -14,6 +14,8 @@ // key. Delete erases the entry from the ebpf_hash_table_t, but doesn't free the memory associated with the // ebpf_pinning_entry_t. +#define EBPF_FILE_ID EBPF_FILE_ID_PINNING_TABLE + #include "ebpf_core_structs.h" #include "ebpf_object.h" #include "ebpf_pinning_table.h" @@ -40,7 +42,7 @@ _ebpf_pinning_entry_free(_Frees_ptr_opt_ ebpf_pinning_entry_t* pinning_entry) if (!pinning_entry) { return; } - ebpf_object_release_reference(pinning_entry->object); + EBPF_OBJECT_RELEASE_REFERENCE(pinning_entry->object); ebpf_free(pinning_entry->path.value); ebpf_free(pinning_entry); } @@ -143,7 +145,7 @@ ebpf_pinning_table_insert( } new_pinning_entry->object = object; - ebpf_object_acquire_reference(object); + EBPF_OBJECT_ACQUIRE_REFERENCE(object); new_key = &new_pinning_entry->path; state = ebpf_lock_lock(&pinning_table->lock); @@ -187,7 +189,7 @@ ebpf_pinning_table_find( if (return_value == EBPF_SUCCESS) { *object = (*existing_pinning_entry)->object; - ebpf_object_acquire_reference(*object); + EBPF_OBJECT_ACQUIRE_REFERENCE(*object); } ebpf_lock_unlock(&pinning_table->lock, state); @@ -304,7 +306,7 @@ ebpf_pinning_table_enumerate_entries( new_entry->object = (*next_pinning_entry)->object; // Take reference on underlying ebpf_object. - ebpf_object_acquire_reference(new_entry->object); + EBPF_OBJECT_ACQUIRE_REFERENCE(new_entry->object); // Duplicate pinning object path. result = ebpf_duplicate_utf8_string(&new_entry->path, &(*next_pinning_entry)->path); @@ -391,7 +393,7 @@ ebpf_pinning_entries_release(uint16_t entry_count, _In_opt_count_(entry_count) e ebpf_pinning_entry_t* entry = &pinning_entries[index]; ebpf_free(entry->path.value); entry->path.value = NULL; - ebpf_object_release_reference(entry->object); + EBPF_OBJECT_RELEASE_REFERENCE(entry->object); } ebpf_free(pinning_entries); EBPF_RETURN_VOID(); diff --git a/libs/platform/kernel/ebpf_handle_kernel.c b/libs/platform/kernel/ebpf_handle_kernel.c index ee1534715..97efa028b 100644 --- a/libs/platform/kernel/ebpf_handle_kernel.c +++ b/libs/platform/kernel/ebpf_handle_kernel.c @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_HANDLE + #include "ebpf_handle.h" #include "framework.h" @@ -59,7 +61,7 @@ ebpf_handle_create(_Out_ ebpf_handle_t* handle, _Inout_ ebpf_base_object_t* obje goto Done; } - object->acquire_reference(object); + EBPF_OBJECT_ACQUIRE_REFERENCE_INDIRECT(object); file_object->FsContext2 = object; *handle = (ebpf_handle_t)file_handle; @@ -94,7 +96,9 @@ _IRQL_requires_max_(PASSIVE_LEVEL) ebpf_result_t ebpf_reference_base_object_by_h ebpf_handle_t handle, _In_opt_ ebpf_compare_object_t compare_function, _In_opt_ const void* context, - _Outptr_ struct _ebpf_base_object** object) + _Outptr_ struct _ebpf_base_object** object, + uint32_t file_id, + uint32_t line) { ebpf_result_t return_value; NTSTATUS status; @@ -126,7 +130,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL) ebpf_result_t ebpf_reference_base_object_by_h } } - local_object->acquire_reference(local_object); + local_object->acquire_reference(local_object, file_id, line); *object = local_object; return_value = EBPF_SUCCESS; diff --git a/libs/platform/unit/platform_unit_test.cpp b/libs/platform/unit/platform_unit_test.cpp index d3e65d942..1cc4ac0ad 100644 --- a/libs/platform/unit/platform_unit_test.cpp +++ b/libs/platform/unit/platform_unit_test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_PLATFORM_UNIT_TESTS + #include "api_common.hpp" #include "catch_wrapper.hpp" #include "ebpf_async.h" @@ -302,10 +304,10 @@ TEST_CASE("pinning_test", "[platform]") ebpf_utf8_string_t bar = EBPF_UTF8_STRING_FROM_CONST_STRING("bar"); REQUIRE( - ebpf_object_initialize( + EBPF_OBJECT_INITIALIZE( &an_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS); REQUIRE( - ebpf_object_initialize( + EBPF_OBJECT_INITIALIZE( &another_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS); ebpf_pinning_table_ptr pinning_table; @@ -322,7 +324,7 @@ TEST_CASE("pinning_test", "[platform]") REQUIRE(ebpf_pinning_table_find(pinning_table.get(), &foo, (ebpf_core_object_t**)&some_object) == EBPF_SUCCESS); REQUIRE(an_object.object.base.reference_count == 3); REQUIRE(some_object == &an_object); - ebpf_object_release_reference(&some_object->object); + EBPF_OBJECT_RELEASE_REFERENCE(&some_object->object); REQUIRE(ebpf_pinning_table_delete(pinning_table.get(), &foo) == EBPF_SUCCESS); REQUIRE(another_object.object.base.reference_count == 2); @@ -330,8 +332,8 @@ TEST_CASE("pinning_test", "[platform]") REQUIRE(an_object.object.base.reference_count == 1); REQUIRE(another_object.object.base.reference_count == 1); - ebpf_object_release_reference(&an_object.object); - ebpf_object_release_reference(&another_object.object); + EBPF_OBJECT_RELEASE_REFERENCE(&an_object.object); + EBPF_OBJECT_RELEASE_REFERENCE(&another_object.object); } TEST_CASE("epoch_test_single_epoch", "[platform]") diff --git a/libs/platform/user/ebpf_handle_user.c b/libs/platform/user/ebpf_handle_user.c index a638af793..0642ef75a 100644 --- a/libs/platform/user/ebpf_handle_user.c +++ b/libs/platform/user/ebpf_handle_user.c @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_HANDLE #include "ebpf_handle.h" typedef ebpf_base_object_t* ebpf_handle_entry_t; @@ -60,7 +61,7 @@ ebpf_handle_create(_Out_ ebpf_handle_t* handle, _Inout_ ebpf_base_object_t* obje *handle = new_handle; _ebpf_handle_table[new_handle] = object; - object->acquire_reference(object); + EBPF_OBJECT_ACQUIRE_REFERENCE_INDIRECT(object); return_value = EBPF_SUCCESS; @@ -79,7 +80,7 @@ ebpf_handle_close(ebpf_handle_t handle) state = ebpf_lock_lock(&_ebpf_handle_table_lock); if (((size_t)handle < EBPF_COUNT_OF(_ebpf_handle_table)) && _ebpf_handle_table[handle] != NULL) { - (_ebpf_handle_table[handle])->release_reference(_ebpf_handle_table[handle]); + EBPF_OBJECT_RELEASE_REFERENCE_INDIRECT(_ebpf_handle_table[handle]); _ebpf_handle_table[handle] = NULL; return_value = EBPF_SUCCESS; } else { @@ -93,7 +94,9 @@ _IRQL_requires_max_(PASSIVE_LEVEL) ebpf_result_t ebpf_reference_base_object_by_h ebpf_handle_t handle, _In_opt_ ebpf_compare_object_t compare_function, _In_opt_ const void* context, - _Outptr_ struct _ebpf_base_object** object) + _Outptr_ struct _ebpf_base_object** object, + uint32_t file_id, + uint32_t line) { ebpf_result_t return_value; ebpf_lock_state_t state; @@ -106,7 +109,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL) ebpf_result_t ebpf_reference_base_object_by_h state = ebpf_lock_lock(&_ebpf_handle_table_lock); if (_ebpf_handle_table[handle] != NULL && (compare_function == NULL || compare_function(_ebpf_handle_table[handle], context))) { - _ebpf_handle_table[handle]->acquire_reference(_ebpf_handle_table[handle]); + _ebpf_handle_table[handle]->acquire_reference(_ebpf_handle_table[handle], file_id, line); *object = _ebpf_handle_table[handle]; return_value = EBPF_SUCCESS; } else { diff --git a/tests/libfuzzer/core_helper_fuzzer/libfuzz_harness.cpp b/tests/libfuzzer/core_helper_fuzzer/libfuzz_harness.cpp index ae8f8b3c4..741f24f3a 100644 --- a/tests/libfuzzer/core_helper_fuzzer/libfuzz_harness.cpp +++ b/tests/libfuzzer/core_helper_fuzzer/libfuzz_harness.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_CORE_HELPER_FUZZER + #include "ebpf_core.h" #include "ebpf_handle.h" #include "ebpf_object.h" @@ -189,7 +191,7 @@ class fuzz_wrapper handles.push_back(handle); ebpf_map_t* map = NULL; - if (ebpf_object_reference_by_handle(handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map) == + if (EBPF_OBJECT_REFERENCE_BY_HANDLE(handle, EBPF_OBJECT_MAP, (ebpf_core_object_t**)&map) == EBPF_SUCCESS) { maps[def.type] = map; if (def.type == BPF_MAP_TYPE_PROG_ARRAY) { @@ -202,7 +204,7 @@ class fuzz_wrapper ~fuzz_wrapper() { for (auto& [_, map] : maps) { - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); } for (auto& handle : handles) { // Ignore invalid handle close. @@ -483,14 +485,14 @@ FUZZ_EXPORT int __cdecl LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) ebpf_handle_t program_handle = fuzz_state.get_program_handle(); ebpf_program_t* program = NULL; ebpf_result_t result = - ebpf_object_reference_by_handle(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); + EBPF_OBJECT_REFERENCE_BY_HANDLE(program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); if (result != EBPF_SUCCESS) { return 0; } fuzz_program(fuzz_state, program_handle, program, data, size); - ebpf_object_release_reference((ebpf_core_object_t*)program); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program); return 0; // Non-zero return values are reserved for future use. } diff --git a/tests/performance/ExecutionContext.cpp b/tests/performance/ExecutionContext.cpp index c28d323e9..9c57bd46c 100644 --- a/tests/performance/ExecutionContext.cpp +++ b/tests/performance/ExecutionContext.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#define EBPF_FILE_ID EBPF_FILE_ID_PERFORMANCE_TESTS + #define TEST_AREA "ExecutionContext" #include "performance.h" @@ -30,7 +32,7 @@ typedef class _ebpf_program_test_state } ~_ebpf_program_test_state() { - ebpf_object_release_reference(reinterpret_cast(program)); + EBPF_OBJECT_RELEASE_REFERENCE(reinterpret_cast(program)); delete program_info_provider; ebpf_core_terminate(); } @@ -109,7 +111,7 @@ typedef class _ebpf_map_test_state } ~_ebpf_map_test_state() { - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); ebpf_core_terminate(); } @@ -255,7 +257,7 @@ typedef class _ebpf_map_lpm_trie_test_state ~_ebpf_map_lpm_trie_test_state() { - ebpf_object_release_reference((ebpf_core_object_t*)map); + EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map); ebpf_core_terminate(); }