Add object history tracking instrumentation (#2449)

* Add object history tracking instrumentation

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Fix file_id type in history

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Code analysis failure

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* PR feedback

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

* Fix incorrect instrumentation

Signed-off-by: Alan Jowett <alanjo@microsoft.com>

---------

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2023-05-10 20:50:50 -06:00 коммит произвёл GitHub
Родитель 6df36ed81e
Коммит f92c9995b0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 410 добавлений и 169 удалений

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_CORE
#include "ebpf_async.h" #include "ebpf_async.h"
#include "ebpf_core.h" #include "ebpf_core.h"
#include "ebpf_epoch.h" #include "ebpf_epoch.h"
@ -278,7 +280,7 @@ ebpf_core_load_code(
EBPF_LOG_ENTRY(); EBPF_LOG_ENTRY();
ebpf_result_t retval; ebpf_result_t retval;
ebpf_program_t* program = NULL; 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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -289,7 +291,7 @@ ebpf_core_load_code(
} }
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)program); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -345,7 +347,7 @@ ebpf_core_resolve_helper(
EBPF_LOG_ENTRY(); EBPF_LOG_ENTRY();
ebpf_program_t* program = NULL; ebpf_program_t* program = NULL;
ebpf_result_t return_value = 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) { if (return_value != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -361,7 +363,7 @@ ebpf_core_resolve_helper(
} }
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)program); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program);
EBPF_RETURN_RESULT(return_value); EBPF_RETURN_RESULT(return_value);
} }
@ -427,7 +429,7 @@ ebpf_core_resolve_maps(
uint32_t map_index = 0; uint32_t map_index = 0;
ebpf_result_t return_value = 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) { if (return_value != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -435,7 +437,7 @@ ebpf_core_resolve_maps(
for (map_index = 0; map_index < count_of_maps; map_index++) { for (map_index = 0; map_index < count_of_maps; map_index++) {
ebpf_map_t* map; ebpf_map_t* map;
return_value = 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) { if (return_value != EBPF_SUCCESS) {
goto Done; goto Done;
@ -449,10 +451,10 @@ ebpf_core_resolve_maps(
Done: Done:
// Release our reference only after the map has been associated with the program. // 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++) { 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); EBPF_RETURN_RESULT(return_value);
} }
@ -518,7 +520,7 @@ ebpf_core_create_map(
retval = EBPF_SUCCESS; retval = EBPF_SUCCESS;
Done: Done:
ebpf_object_release_reference(map_object); EBPF_OBJECT_RELEASE_REFERENCE(map_object);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -727,7 +729,7 @@ _ebpf_core_protocol_map_find_element(
size_t value_length; size_t value_length;
size_t key_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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -759,7 +761,7 @@ _ebpf_core_protocol_map_find_element(
reply->header.length = reply_length; reply->header.length = reply_length;
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(retval); 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 value_length;
size_t key_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) { if (retval != EBPF_SUCCESS) {
goto Done; 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); map, key_length, request->data, value_length, request->data + key_length, request->option, 0);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -809,7 +811,7 @@ _ebpf_core_protocol_map_update_element_with_handle(
ebpf_map_t* map = NULL; ebpf_map_t* map = NULL;
size_t key_length; 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) { if (retval != EBPF_SUCCESS) {
goto Done; 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); retval = ebpf_map_update_entry_with_handle(map, key_length, request->key, request->value_handle, request->option);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(retval); 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; ebpf_map_t* map = NULL;
size_t key_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) { if (retval != EBPF_SUCCESS) {
goto Done; 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); retval = ebpf_map_delete_entry(map, key_length, request->key, 0);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -867,7 +869,7 @@ _ebpf_core_protocol_map_get_next_key(
size_t previous_key_length; size_t previous_key_length;
size_t next_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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -904,7 +906,7 @@ _ebpf_core_protocol_map_get_next_key(
reply->header.length = reply_length; reply->header.length = reply_length;
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(retval); 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_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); ebpf_free((void*)options);
} }
@ -971,7 +973,7 @@ _ebpf_core_protocol_program_test_run(
} }
retval = 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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -1002,7 +1004,7 @@ _ebpf_core_protocol_program_test_run(
Done: Done:
if (retval != EBPF_PENDING) { if (retval != EBPF_PENDING) {
ebpf_free(options); 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); EBPF_RETURN_RESULT(retval);
} }
@ -1021,7 +1023,7 @@ _ebpf_core_protocol_query_program_info(
ebpf_utf8_string_t section_name = {0}; ebpf_utf8_string_t section_name = {0};
ebpf_code_type_t code_type; 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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -1068,7 +1070,7 @@ Done:
ebpf_utf8_string_free(&file_name); ebpf_utf8_string_free(&file_name);
ebpf_utf8_string_free(&section_name); ebpf_utf8_string_free(&section_name);
ebpf_object_release_reference((ebpf_core_object_t*)program); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program);
EBPF_RETURN_RESULT(retval); 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); retval = ebpf_pinning_table_delete(_ebpf_core_map_pinning_table, path);
goto Done; goto Done;
} else { } 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) { if (retval != EBPF_SUCCESS) {
goto Done; 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); retval = ebpf_pinning_table_insert(_ebpf_core_map_pinning_table, path, (ebpf_core_object_t*)object);
} }
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)object); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object);
EBPF_RETURN_RESULT(retval); 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); retval = ebpf_handle_create(handle, (ebpf_base_object_t*)object);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)object); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -1162,7 +1164,7 @@ _ebpf_core_protocol_get_pinned_object(
retval = ebpf_core_get_pinned_object(&path, &reply->handle); retval = ebpf_core_get_pinned_object(&path, &reply->handle);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)object); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)object);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -1177,7 +1179,7 @@ _ebpf_core_protocol_link_program(
ebpf_code_type_t code_type; ebpf_code_type_t code_type;
retval = 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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -1214,8 +1216,8 @@ Done:
if (retval != EBPF_SUCCESS && link) { if (retval != EBPF_SUCCESS && link) {
ebpf_link_detach_program(link); ebpf_link_detach_program(link);
} }
ebpf_object_release_reference((ebpf_core_object_t*)program); 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*)link);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -1246,9 +1248,9 @@ _ebpf_core_find_matching_link(
// Enumerate all link objects starting with previous_object. // Enumerate all link objects starting with previous_object.
while (TRUE) { while (TRUE) {
struct bpf_link_info info = {0}; 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) { if (previous_object != NULL) {
ebpf_object_release_reference(previous_object); EBPF_OBJECT_RELEASE_REFERENCE(previous_object);
} }
if (local_link == NULL) { if (local_link == NULL) {
// No more links. // No more links.
@ -1275,15 +1277,15 @@ _ebpf_core_find_matching_link(
// Compare program id. // Compare program id.
if (program_handle != ebpf_handle_invalid) { if (program_handle != ebpf_handle_invalid) {
ebpf_core_object_t* program = NULL; 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) { if (result != EBPF_SUCCESS) {
break; break;
} }
if (info.prog_id != program->id) { if (info.prog_id != program->id) {
ebpf_object_release_reference(program); EBPF_OBJECT_RELEASE_REFERENCE(program);
continue; continue;
} }
ebpf_object_release_reference(program); EBPF_OBJECT_RELEASE_REFERENCE(program);
} }
match_found = TRUE; match_found = TRUE;
@ -1306,7 +1308,7 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ
ebpf_link_t* link = NULL; ebpf_link_t* link = NULL;
if (request->link_handle != ebpf_handle_invalid) { 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) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -1345,7 +1347,7 @@ _ebpf_core_protocol_unlink_program(_In_ const ebpf_operation_unlink_program_requ
} }
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)link); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link);
EBPF_RETURN_RESULT(retval); EBPF_RETURN_RESULT(retval);
} }
@ -1394,7 +1396,7 @@ _ebpf_core_protocol_get_program_info(
goto Done; goto Done;
} }
} else { } else {
retval = ebpf_object_reference_by_handle( retval = EBPF_OBJECT_REFERENCE_BY_HANDLE(
request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program); request->program_handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program);
if (retval != EBPF_SUCCESS) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
@ -1422,7 +1424,7 @@ _ebpf_core_protocol_get_program_info(
Done: Done:
ebpf_program_free_program_info(program_info); 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); 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_LOG_ENTRY();
ebpf_core_object_t* object; 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) { if (result != EBPF_SUCCESS) {
return result; return result;
} }
result = ebpf_handle_create(handle, (ebpf_base_object_t*)object); result = ebpf_handle_create(handle, (ebpf_base_object_t*)object);
ebpf_object_release_reference(object); EBPF_OBJECT_RELEASE_REFERENCE(object);
EBPF_RETURN_RESULT(result); 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; ebpf_map_t* map = NULL;
result = 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) { if (result != EBPF_SUCCESS) {
goto Done; 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) { if (result != EBPF_SUCCESS) {
goto Done; goto Done;
} }
@ -1690,10 +1692,10 @@ _ebpf_core_protocol_bind_map(_In_ const ebpf_operation_bind_map_request_t* reque
Done: Done:
if (program) { if (program) {
ebpf_object_release_reference((ebpf_core_object_t*)program); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program);
} }
if (map) { if (map) {
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
} }
EBPF_RETURN_RESULT(result); 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); uint16_t info_size = reply_length - FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info);
ebpf_core_object_t* object; 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) { if (result != EBPF_SUCCESS) {
return result; return result;
} }
@ -1729,7 +1731,7 @@ _ebpf_core_protocol_get_object_info(
if (result == EBPF_SUCCESS) { if (result == EBPF_SUCCESS) {
reply->header.length = FIELD_OFFSET(ebpf_operation_get_object_info_reply_t, info) + info_size; 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); EBPF_RETURN_RESULT(result);
} }
@ -1742,7 +1744,7 @@ _ebpf_core_protocol_ring_buffer_map_query_buffer(
ebpf_map_t* map = NULL; ebpf_map_t* map = NULL;
ebpf_result_t result = 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) { if (result != EBPF_SUCCESS) {
goto Exit; 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); result = ebpf_ring_buffer_map_query_buffer(map, (uint8_t**)(uintptr_t*)&reply->buffer_address);
Exit: Exit:
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
EBPF_RETURN_RESULT(result); EBPF_RETURN_RESULT(result);
} }
@ -1772,7 +1774,7 @@ _ebpf_core_protocol_ring_buffer_map_async_query(
bool reference_taken = FALSE; bool reference_taken = FALSE;
ebpf_result_t result = 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) { if (result != EBPF_SUCCESS) {
goto Exit; goto Exit;
} }
@ -1795,7 +1797,7 @@ _ebpf_core_protocol_ring_buffer_map_async_query(
Exit: Exit:
if (reference_taken) { if (reference_taken) {
ebpf_object_release_reference((ebpf_core_object_t*)map); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)map);
} }
return result; return result;
} }
@ -2494,7 +2496,7 @@ ebpf_core_close_context(_In_opt_ void* context)
ebpf_epoch_state_t* epoch_state = ebpf_epoch_enter(); ebpf_epoch_state_t* epoch_state = ebpf_epoch_enter();
ebpf_core_object_t* object = (ebpf_core_object_t*)context; 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); ebpf_epoch_exit(epoch_state);
} }

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_LINK
#include "ebpf_core.h" #include "ebpf_core.h"
#include "ebpf_epoch.h" #include "ebpf_epoch.h"
#include "ebpf_handle.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. // 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. // 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) { if (result != EBPF_SUCCESS) {
retval = EBPF_NO_MEMORY; retval = EBPF_NO_MEMORY;
goto Exit; goto Exit;
@ -310,7 +312,7 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link)
ebpf_program_t* program = NULL; ebpf_program_t* program = NULL;
bool link_is_detaching = false; 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); 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); ebpf_lock_unlock(&link->attach_lock, state);
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)link); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)link);
EBPF_RETURN_VOID(); EBPF_RETURN_VOID();
} }

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_MAPS
#include "ebpf_async.h" #include "ebpf_async.h"
#include "ebpf_bitmap.h" #include "ebpf_bitmap.h"
#include "ebpf_epoch.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. // 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) { if (result != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_NTSTATUS( EBPF_LOG_MESSAGE_NTSTATUS(
EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_MAP, "Get object ref by handle failed.", result); 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: Exit:
if (inner_map_template_object) { if (inner_map_template_object) {
ebpf_object_release_reference(inner_map_template_object); EBPF_OBJECT_RELEASE_REFERENCE(inner_map_template_object);
} }
return result; 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++) { 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]; ebpf_id_t id = *(ebpf_id_t*)&map->data[i * map->ebpf_map_definition.value_size];
if (id) { 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; ebpf_core_object_t* value_object = NULL;
if (value_handle != (uintptr_t)ebpf_handle_invalid) { 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) { if (result != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UINT64_UINT64( EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, 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 // 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. // 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); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID);
if (result == EBPF_STALE_ID) { if (result == EBPF_STALE_ID) {
result = EBPF_SUCCESS; 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 // 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. // 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 // 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 // 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 // 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. // 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) { if (locked) {
@ -764,7 +766,7 @@ _delete_array_map_entry_with_reference(
if (id) { if (id) {
// The object may have been already deleted, so an error return value of 'stale id' is ok. // 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); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID);
if (result == EBPF_STALE_ID) { if (result == EBPF_STALE_ID) {
result = EBPF_SUCCESS; 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 // Note that this call might fail and that's fine. The id might be valid, but the object might have been
// since deleted. // 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) { if (id) {
// The object may have been already deleted, so an error return value of 'stale id' is ok. // 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); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID);
if (result == EBPF_STALE_ID) { if (result == EBPF_STALE_ID) {
result = EBPF_SUCCESS; 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; uint8_t* value = NULL;
if (_find_hash_map_entry(map, key, false, &value) == EBPF_SUCCESS) { if (_find_hash_map_entry(map, key, false, &value) == EBPF_SUCCESS) {
ebpf_id_t id = *(ebpf_id_t*)value; 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); 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_map_t* object_map = EBPF_FROM_FIELD(ebpf_core_object_map_t, core_map, map);
ebpf_core_object_t* value_object = NULL; 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) { if (result != EBPF_SUCCESS) {
EBPF_LOG_MESSAGE_UINT64_UINT64( EBPF_LOG_MESSAGE_UINT64_UINT64(
EBPF_TRACELOG_LEVEL_ERROR, 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 // 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. // 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); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID);
if (result == EBPF_STALE_ID) { if (result == EBPF_STALE_ID) {
result = EBPF_SUCCESS; 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 // 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. // 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: Done:
if (value_object != NULL) { 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); ebpf_lock_unlock(&object_map->lock, lock_state);
return result; return result;
@ -1480,7 +1482,7 @@ _delete_map_hash_map_entry(_Inout_ ebpf_core_map_t* map, _In_ const uint8_t* key
if (id) { if (id) {
// The object may have been already deleted, so an error return value of 'stale id' is ok. // 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); ebpf_assert(result == EBPF_SUCCESS || result == EBPF_STALE_ID);
if (result == EBPF_STALE_ID) { if (result == EBPF_STALE_ID) {
result = EBPF_SUCCESS; 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]; 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; 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) { if (result != EBPF_SUCCESS) {
goto Exit; goto Exit;
} }
@ -2360,7 +2362,7 @@ ebpf_map_find_entry(
// Release the extra reference obtained. // Release the extra reference obtained.
// REVIEW: is this safe? // REVIEW: is this safe?
if (object) { if (object) {
ebpf_object_release_reference(object); EBPF_OBJECT_RELEASE_REFERENCE(object);
return_value = (uint8_t*)object; return_value = (uint8_t*)object;
} }
} else { } else {

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_NATIVE
#include "ebpf_core.h" #include "ebpf_core.h"
#include "ebpf_handle.h" #include "ebpf_handle.h"
#include "ebpf_native.h" #include "ebpf_native.h"
@ -202,10 +204,10 @@ _ebpf_native_clean_up_programs(
for (uint32_t i = 0; i < count_of_programs; i++) { for (uint32_t i = 0; i < count_of_programs; i++) {
if (programs[i].handle != ebpf_handle_invalid) { if (programs[i].handle != ebpf_handle_invalid) {
ebpf_program_t* program_object = NULL; 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)); 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_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) { if (close_handles) {
ebpf_assert_success(ebpf_handle_close(programs[i].handle)); ebpf_assert_success(ebpf_handle_close(programs[i].handle));
programs[i].handle = ebpf_handle_invalid; programs[i].handle = ebpf_handle_invalid;
@ -377,6 +379,23 @@ ebpf_native_terminate()
EBPF_RETURN_VOID(); 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 static NTSTATUS
_ebpf_native_provider_attach_client_callback( _ebpf_native_provider_attach_client_callback(
HANDLE nmr_binding_handle, HANDLE nmr_binding_handle,
@ -438,8 +457,8 @@ _ebpf_native_provider_attach_client_callback(
ebpf_lock_create(&client_context->lock); ebpf_lock_create(&client_context->lock);
client_context->base.marker = _ebpf_native_marker; client_context->base.marker = _ebpf_native_marker;
client_context->base.acquire_reference = ebpf_native_acquire_reference; client_context->base.acquire_reference = _ebpf_native_acquire_reference_internal;
client_context->base.release_reference = ebpf_native_release_reference; client_context->base.release_reference = _ebpf_native_release_reference_internal;
// Acquire "attach" reference. Released when detach is called for this module. // Acquire "attach" reference. Released when detach is called for this module.
client_context->base.reference_count = 1; client_context->base.reference_count = 1;
client_context->client_module_id = *client_module_id; 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_core_object_t* object;
ebpf_handle_t inner_map_handle = ebpf_handle_invalid; ebpf_handle_t inner_map_handle = ebpf_handle_invalid;
uint16_t info_size = (uint16_t)sizeof(info); 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) { if (result != EBPF_SUCCESS) {
goto Exit; goto Exit;
} }
@ -743,7 +762,7 @@ _ebpf_native_validate_map(_In_ const ebpf_native_map_t* map, ebpf_handle_t origi
} }
Exit: Exit:
ebpf_object_release_reference(object); EBPF_OBJECT_RELEASE_REFERENCE(object);
EBPF_RETURN_RESULT(result); EBPF_RETURN_RESULT(result);
} }
@ -1163,7 +1182,7 @@ _ebpf_native_load_programs(_Inout_ ebpf_native_module_t* module)
context->native_program = native_program; context->native_program = native_program;
ebpf_program_t* program_object = NULL; 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); native_program->handle, EBPF_OBJECT_PROGRAM, (ebpf_core_object_t**)&program_object);
if (result != EBPF_SUCCESS) { if (result != EBPF_SUCCESS) {
ebpf_free(context); 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); 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) { if (result != EBPF_SUCCESS) {
ebpf_free(context); ebpf_free(context);

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_PROGRAM
#include "bpf_helpers.h" #include "bpf_helpers.h"
#include "ebpf_async.h" #include "ebpf_async.h"
#include "ebpf_core.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)); ebpf_assert(ebpf_list_is_empty(&program->links));
for (index = 0; index < program->count_of_maps; index++) { 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; 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. // 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. // 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); &local_program->object, EBPF_OBJECT_PROGRAM, _ebpf_program_free, _ebpf_program_get_program_type);
if (retval != EBPF_SUCCESS) { if (retval != EBPF_SUCCESS) {
goto Done; goto Done;
@ -589,7 +591,7 @@ ebpf_program_associate_additional_map(ebpf_program_t* program, ebpf_map_t* map)
goto Done; 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[map_count - 1] = map;
program->maps = program_maps; program->maps = program_maps;
program->count_of_maps = map_count; 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_maps = NULL;
program->count_of_maps = maps_count; program->count_of_maps = maps_count;
for (index = 0; index < maps_count; index++) { 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); ebpf_lock_unlock(&program->lock, state);
@ -1147,7 +1149,7 @@ ebpf_program_invoke(
} }
if (state.count != 0) { 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; current_program = NULL;
} }
@ -1447,7 +1449,7 @@ ebpf_program_attach_link(_Inout_ ebpf_program_t* program, _Inout_ ebpf_link_t* l
{ {
EBPF_LOG_ENTRY(); EBPF_LOG_ENTRY();
// Acquire "attach" reference on the link object. // 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. // Insert the link in the attach list.
ebpf_lock_state_t state; 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); ebpf_lock_unlock(&program->lock, state);
// Release the "attach" reference. // 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(); EBPF_RETURN_VOID();
} }
@ -1549,7 +1551,7 @@ ebpf_program_create_and_initialize(
} }
Done: Done:
ebpf_object_release_reference((ebpf_core_object_t*)program); EBPF_OBJECT_RELEASE_REFERENCE((ebpf_core_object_t*)program);
return retval; return retval;
} }

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_EXECUTION_CONTEXT_UNIT_TESTS
#include "catch_wrapper.hpp" #include "catch_wrapper.hpp"
#include "ebpf_async.h" #include "ebpf_async.h"
#include "ebpf_core.h" #include "ebpf_core.h"
@ -101,7 +103,7 @@ template <typename T> class ebpf_object_deleter
void void
operator()(T* object) operator()(T* object)
{ {
ebpf_object_release_reference(reinterpret_cast<ebpf_core_object_t*>(object)); EBPF_OBJECT_RELEASE_REFERENCE(reinterpret_cast<ebpf_core_object_t*>(object));
} }
}; };

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

@ -57,6 +57,8 @@ extern "C"
* *
* @param[in] handle Handle to find in table. * @param[in] handle Handle to find in table.
* @param[out] object Pointer to memory that contains object success. * @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_SUCCESS The operation was successful.
* @retval EBPF_INVALID_OBJECT The provided handle is not valid. * @retval EBPF_INVALID_OBJECT The provided handle is not valid.
*/ */
@ -64,7 +66,9 @@ extern "C"
ebpf_handle_t handle, ebpf_handle_t handle,
_In_opt_ ebpf_compare_object_t compare_function, _In_opt_ ebpf_compare_object_t compare_function,
_In_opt_ const void* context, _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 #ifdef __cplusplus
} }

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

@ -74,6 +74,70 @@ typedef struct _ebpf_id_entry
// case this becomes a hash table. // case this becomes a hash table.
static _Guarded_by_(_ebpf_object_tracking_list_lock) ebpf_id_entry_t _ebpf_id_table[1024]; 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. // Get the ID last stored at a given index.
static inline ebpf_id_t static inline ebpf_id_t
_get_id_from_index(uint32_t index) _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 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; int new_index;
ebpf_result_t return_value; 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].counter++;
_ebpf_id_table[new_index].reference_count = 1; _ebpf_id_table[new_index].reference_count = 1;
_ebpf_id_table[new_index].object = object; _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); object->id = _get_id_from_index(new_index);
return_value = EBPF_SUCCESS; return_value = EBPF_SUCCESS;
@ -133,7 +198,7 @@ Done:
} }
_Requires_lock_held_(&_ebpf_object_tracking_list_lock) static void _ebpf_object_tracking_list_remove( _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; uint32_t index;
ebpf_result_t return_value = _get_index_from_id(object->id, &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. // Under lock, so un-protected access is ok.
_ebpf_id_table[index].reference_count--; _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_assert(_ebpf_id_table[index].reference_count >= 0);
_ebpf_id_table[index].object = NULL; _ebpf_id_table[index].object = NULL;
} }
@ -153,6 +219,8 @@ ebpf_object_tracking_initiate()
{ {
ebpf_lock_create(&_ebpf_object_tracking_list_lock); ebpf_lock_create(&_ebpf_object_tracking_list_lock);
memset(_ebpf_id_table, 0, sizeof(_ebpf_id_table)); 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 void
@ -169,7 +237,9 @@ ebpf_object_initialize(
_Inout_ ebpf_core_object_t* object, _Inout_ ebpf_core_object_t* object,
ebpf_object_type_t object_type, ebpf_object_type_t object_type,
ebpf_free_object_t free_function, 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_LOG_MESSAGE_POINTER_ENUM(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object initialized", object, object_type); 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->free_function = free_function;
object->get_program_type = get_program_type_function; object->get_program_type = get_program_type_function;
ebpf_list_initialize(&object->object_list_entry); 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 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) { if (object->base.marker != _ebpf_object_marker) {
__fastfail(FAST_FAIL_INVALID_ARG); __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. * @retval false Reference was not acquired.
*/ */
static bool 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) { if (object->marker != _ebpf_object_marker) {
__fastfail(FAST_FAIL_INVALID_ARG); __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) == if (ebpf_interlocked_compare_exchange_int64(&object->reference_count, new_ref_count + 1, new_ref_count) ==
new_ref_count) { new_ref_count) {
_update_reference_history(object, EBPF_OBJECT_ACQUIRE, file_id, line);
return true; return true;
} }
} }
} }
void 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; int64_t new_ref_count;
_update_reference_history(object, EBPF_OBJECT_RELEASE, file_id, line);
if (!object) { if (!object) {
return; 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_lock_state_t state = ebpf_lock_lock(&_ebpf_object_tracking_list_lock);
EBPF_LOG_MESSAGE_POINTER_ENUM( EBPF_LOG_MESSAGE_POINTER_ENUM(
EBPF_TRACELOG_LEVEL_VERBOSE, EBPF_TRACELOG_KEYWORD_BASE, "eBPF object terminated", object, object->type); 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); ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state);
} }
// Free the object outside the lock. // Free the object outside the lock.
if (new_ref_count == 0) { if (new_ref_count == 0) {
_update_reference_history(object, EBPF_OBJECT_DESTROY, file_id, line);
object->base.marker = ~object->base.marker; object->base.marker = ~object->base.marker;
object->free_function(object); object->free_function(object);
} }
@ -340,7 +415,9 @@ void
ebpf_object_reference_next_object( ebpf_object_reference_next_object(
_In_opt_ const ebpf_core_object_t* previous_object, _In_opt_ const ebpf_core_object_t* previous_object,
ebpf_object_type_t type, 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_result_t return_value = EBPF_SUCCESS;
ebpf_lock_state_t state; ebpf_lock_state_t state;
@ -362,7 +439,7 @@ ebpf_object_reference_next_object(
if (_ebpf_id_table[index].object == NULL) { if (_ebpf_id_table[index].object == NULL) {
continue; 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; continue;
} }
*next_object = _ebpf_id_table[index].object; *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); 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 _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); 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 { } else {
ebpf_core_object_t* found = _ebpf_id_table[index].object; ebpf_core_object_t* found = _ebpf_id_table[index].object;
if ((found != NULL) && (found->type == object_type)) { 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; *object = found;
} else { } else {
return_value = EBPF_KEY_NOT_FOUND; 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); 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; 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_result_t
ebpf_object_reference_by_handle( 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( 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* _Must_inspect_result_ char*
@ -440,7 +528,7 @@ ebpf_duplicate_string(_In_z_ const char* source)
} }
_Must_inspect_result_ ebpf_result_t _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); 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_id_entry_t* entry = &_ebpf_id_table[index];
ebpf_assert(entry->reference_count); if (entry->reference_count <= 0) {
if (entry->reference_count == 0) { __fastfail(FAST_FAIL_INVALID_REFERENCE_COUNT);
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;
} }
// ref count is non-zero // 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. // We're under lock so un-protected access is ok.
entry->reference_count++; entry->reference_count++;
result = EBPF_SUCCESS; result = EBPF_SUCCESS;
_update_reference_history(entry, EBPF_OBJECT_ACQUIRE, file_id, line);
Done: Done:
ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state);
@ -494,7 +571,7 @@ Done:
} }
_Must_inspect_result_ ebpf_result_t _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); 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_id_entry_t* entry = &_ebpf_id_table[index];
ebpf_assert(entry->reference_count); if (entry->reference_count <= 0) {
if (entry->reference_count == 0) { __fastfail(FAST_FAIL_INVALID_REFERENCE_COUNT);
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;
} }
// ref count is non-zero // 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--; entry->reference_count--;
ebpf_assert(entry->reference_count >= 0); ebpf_assert(entry->reference_count >= 0);
result = EBPF_SUCCESS; result = EBPF_SUCCESS;
_update_reference_history(entry, EBPF_OBJECT_RELEASE, file_id, line);
Done: Done:
ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state); ebpf_lock_unlock(&_ebpf_object_tracking_list_lock, state);
return result; return result;
} }

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

@ -9,6 +9,100 @@ extern "C"
{ {
#endif #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 typedef enum _ebpf_object_type
{ {
EBPF_OBJECT_UNKNOWN, EBPF_OBJECT_UNKNOWN,
@ -18,8 +112,8 @@ extern "C"
} ebpf_object_type_t; } ebpf_object_type_t;
typedef struct _ebpf_base_object ebpf_base_object_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_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); 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 struct _ebpf_core_object ebpf_core_object_t;
typedef void (*ebpf_free_object_t)(ebpf_core_object_t* object); 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] object_type The type of the object.
* @param[in] free_function The function used to free 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] 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 * 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). * 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. * @retval EBPF_SUCCESS Initialization succeeded.
@ -90,24 +186,30 @@ extern "C"
_Inout_ ebpf_core_object_t* object, _Inout_ ebpf_core_object_t* object,
ebpf_object_type_t object_type, ebpf_object_type_t object_type,
ebpf_free_object_t free_function, 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. * @brief Acquire a reference to this object.
* *
* @param[in,out] object Object on which to acquire a reference. * @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 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 * @brief Release a reference on this object. If the reference count reaches
* zero, the free_function is invoked on the object. * zero, the free_function is invoked on the object.
* *
* @param[in,out] object Object on which to release a reference. * @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 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. * @brief Query the stored type of the object.
@ -126,13 +228,17 @@ extern "C"
* to find first object. * to find first object.
* @param[in] type Type of object to find. * @param[in] type Type of object to find.
* @param[out] next_object Pointer to memory containing the next object or * @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. * NULL if there are no more objects of that type.
*/ */
void void
ebpf_object_reference_next_object( ebpf_object_reference_next_object(
_In_opt_ const ebpf_core_object_t* previous_object, _In_opt_ const ebpf_core_object_t* previous_object,
ebpf_object_type_t type, 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, * @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] id ID to find in table.
* @param[in] object_type Object type to match. * @param[in] object_type Object type to match.
* @param[out] object Pointer to memory that contains object success. * @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_SUCCESS The operation was successful.
* @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid.
*/ */
_Must_inspect_result_ ebpf_result_t _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. * @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] handle Handle to find in table.
* @param[in] object_type Object type to match. * @param[in] object_type Object type to match.
* @param[out] object Pointer to memory that contains object success. * @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_SUCCESS The operation was successful.
* @retval EBPF_INVALID_OBJECT The provided handle is not valid. * @retval EBPF_INVALID_OBJECT The provided handle is not valid.
*/ */
ebpf_result_t ebpf_result_t
ebpf_object_reference_by_handle( 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, * @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] id ID to find in table.
* @param[in] object_type Object type to match. * @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_SUCCESS The operation was successful.
* @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid.
*/ */
_Must_inspect_result_ ebpf_result_t _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, * @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] id ID to find in table.
* @param[in] object_type Object type to match. * @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_SUCCESS The operation was successful.
* @retval EBPF_KEY_NOT_FOUND The provided ID is not valid. * @retval EBPF_KEY_NOT_FOUND The provided ID is not valid.
*/ */
_Must_inspect_result_ ebpf_result_t _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 #ifdef __cplusplus
} }

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

@ -14,6 +14,8 @@
// key. Delete erases the entry from the ebpf_hash_table_t, but doesn't free the memory associated with the // key. Delete erases the entry from the ebpf_hash_table_t, but doesn't free the memory associated with the
// ebpf_pinning_entry_t. // ebpf_pinning_entry_t.
#define EBPF_FILE_ID EBPF_FILE_ID_PINNING_TABLE
#include "ebpf_core_structs.h" #include "ebpf_core_structs.h"
#include "ebpf_object.h" #include "ebpf_object.h"
#include "ebpf_pinning_table.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) { if (!pinning_entry) {
return; 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->path.value);
ebpf_free(pinning_entry); ebpf_free(pinning_entry);
} }
@ -143,7 +145,7 @@ ebpf_pinning_table_insert(
} }
new_pinning_entry->object = object; new_pinning_entry->object = object;
ebpf_object_acquire_reference(object); EBPF_OBJECT_ACQUIRE_REFERENCE(object);
new_key = &new_pinning_entry->path; new_key = &new_pinning_entry->path;
state = ebpf_lock_lock(&pinning_table->lock); state = ebpf_lock_lock(&pinning_table->lock);
@ -187,7 +189,7 @@ ebpf_pinning_table_find(
if (return_value == EBPF_SUCCESS) { if (return_value == EBPF_SUCCESS) {
*object = (*existing_pinning_entry)->object; *object = (*existing_pinning_entry)->object;
ebpf_object_acquire_reference(*object); EBPF_OBJECT_ACQUIRE_REFERENCE(*object);
} }
ebpf_lock_unlock(&pinning_table->lock, state); ebpf_lock_unlock(&pinning_table->lock, state);
@ -304,7 +306,7 @@ ebpf_pinning_table_enumerate_entries(
new_entry->object = (*next_pinning_entry)->object; new_entry->object = (*next_pinning_entry)->object;
// Take reference on underlying ebpf_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. // Duplicate pinning object path.
result = ebpf_duplicate_utf8_string(&new_entry->path, &(*next_pinning_entry)->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_pinning_entry_t* entry = &pinning_entries[index];
ebpf_free(entry->path.value); ebpf_free(entry->path.value);
entry->path.value = NULL; entry->path.value = NULL;
ebpf_object_release_reference(entry->object); EBPF_OBJECT_RELEASE_REFERENCE(entry->object);
} }
ebpf_free(pinning_entries); ebpf_free(pinning_entries);
EBPF_RETURN_VOID(); EBPF_RETURN_VOID();

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_HANDLE
#include "ebpf_handle.h" #include "ebpf_handle.h"
#include "framework.h" #include "framework.h"
@ -59,7 +61,7 @@ ebpf_handle_create(_Out_ ebpf_handle_t* handle, _Inout_ ebpf_base_object_t* obje
goto Done; goto Done;
} }
object->acquire_reference(object); EBPF_OBJECT_ACQUIRE_REFERENCE_INDIRECT(object);
file_object->FsContext2 = object; file_object->FsContext2 = object;
*handle = (ebpf_handle_t)file_handle; *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, ebpf_handle_t handle,
_In_opt_ ebpf_compare_object_t compare_function, _In_opt_ ebpf_compare_object_t compare_function,
_In_opt_ const void* context, _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_result_t return_value;
NTSTATUS status; 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; *object = local_object;
return_value = EBPF_SUCCESS; return_value = EBPF_SUCCESS;

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_PLATFORM_UNIT_TESTS
#include "api_common.hpp" #include "api_common.hpp"
#include "catch_wrapper.hpp" #include "catch_wrapper.hpp"
#include "ebpf_async.h" #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"); ebpf_utf8_string_t bar = EBPF_UTF8_STRING_FROM_CONST_STRING("bar");
REQUIRE( REQUIRE(
ebpf_object_initialize( EBPF_OBJECT_INITIALIZE(
&an_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS); &an_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS);
REQUIRE( REQUIRE(
ebpf_object_initialize( EBPF_OBJECT_INITIALIZE(
&another_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS); &another_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS);
ebpf_pinning_table_ptr pinning_table; 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(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(an_object.object.base.reference_count == 3);
REQUIRE(some_object == &an_object); 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(ebpf_pinning_table_delete(pinning_table.get(), &foo) == EBPF_SUCCESS);
REQUIRE(another_object.object.base.reference_count == 2); 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(an_object.object.base.reference_count == 1);
REQUIRE(another_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(&an_object.object);
ebpf_object_release_reference(&another_object.object); EBPF_OBJECT_RELEASE_REFERENCE(&another_object.object);
} }
TEST_CASE("epoch_test_single_epoch", "[platform]") TEST_CASE("epoch_test_single_epoch", "[platform]")

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

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_HANDLE
#include "ebpf_handle.h" #include "ebpf_handle.h"
typedef ebpf_base_object_t* ebpf_handle_entry_t; 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; *handle = new_handle;
_ebpf_handle_table[new_handle] = object; _ebpf_handle_table[new_handle] = object;
object->acquire_reference(object); EBPF_OBJECT_ACQUIRE_REFERENCE_INDIRECT(object);
return_value = EBPF_SUCCESS; return_value = EBPF_SUCCESS;
@ -79,7 +80,7 @@ ebpf_handle_close(ebpf_handle_t handle)
state = ebpf_lock_lock(&_ebpf_handle_table_lock); state = ebpf_lock_lock(&_ebpf_handle_table_lock);
if (((size_t)handle < EBPF_COUNT_OF(_ebpf_handle_table)) && _ebpf_handle_table[handle] != NULL) { 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; _ebpf_handle_table[handle] = NULL;
return_value = EBPF_SUCCESS; return_value = EBPF_SUCCESS;
} else { } else {
@ -93,7 +94,9 @@ _IRQL_requires_max_(PASSIVE_LEVEL) ebpf_result_t ebpf_reference_base_object_by_h
ebpf_handle_t handle, ebpf_handle_t handle,
_In_opt_ ebpf_compare_object_t compare_function, _In_opt_ ebpf_compare_object_t compare_function,
_In_opt_ const void* context, _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_result_t return_value;
ebpf_lock_state_t state; 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); state = ebpf_lock_lock(&_ebpf_handle_table_lock);
if (_ebpf_handle_table[handle] != NULL && if (_ebpf_handle_table[handle] != NULL &&
(compare_function == NULL || compare_function(_ebpf_handle_table[handle], context))) { (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]; *object = _ebpf_handle_table[handle];
return_value = EBPF_SUCCESS; return_value = EBPF_SUCCESS;
} else { } else {

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_CORE_HELPER_FUZZER
#include "ebpf_core.h" #include "ebpf_core.h"
#include "ebpf_handle.h" #include "ebpf_handle.h"
#include "ebpf_object.h" #include "ebpf_object.h"
@ -189,7 +191,7 @@ class fuzz_wrapper
handles.push_back(handle); handles.push_back(handle);
ebpf_map_t* map = NULL; 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) { EBPF_SUCCESS) {
maps[def.type] = map; maps[def.type] = map;
if (def.type == BPF_MAP_TYPE_PROG_ARRAY) { if (def.type == BPF_MAP_TYPE_PROG_ARRAY) {
@ -202,7 +204,7 @@ class fuzz_wrapper
~fuzz_wrapper() ~fuzz_wrapper()
{ {
for (auto& [_, map] : maps) { 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) { for (auto& handle : handles) {
// Ignore invalid handle close. // 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_handle_t program_handle = fuzz_state.get_program_handle();
ebpf_program_t* program = NULL; ebpf_program_t* program = NULL;
ebpf_result_t result = 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) { if (result != EBPF_SUCCESS) {
return 0; return 0;
} }
fuzz_program(fuzz_state, program_handle, program, data, size); 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. return 0; // Non-zero return values are reserved for future use.
} }

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

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#define EBPF_FILE_ID EBPF_FILE_ID_PERFORMANCE_TESTS
#define TEST_AREA "ExecutionContext" #define TEST_AREA "ExecutionContext"
#include "performance.h" #include "performance.h"
@ -30,7 +32,7 @@ typedef class _ebpf_program_test_state
} }
~_ebpf_program_test_state() ~_ebpf_program_test_state()
{ {
ebpf_object_release_reference(reinterpret_cast<ebpf_core_object_t*>(program)); EBPF_OBJECT_RELEASE_REFERENCE(reinterpret_cast<ebpf_core_object_t*>(program));
delete program_info_provider; delete program_info_provider;
ebpf_core_terminate(); ebpf_core_terminate();
} }
@ -109,7 +111,7 @@ typedef class _ebpf_map_test_state
} }
~_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(); ebpf_core_terminate();
} }
@ -255,7 +257,7 @@ typedef class _ebpf_map_lpm_trie_test_state
~_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(); ebpf_core_terminate();
} }