First round of memory leak fixes in ebpfapi (#1774)

* First round of memory leak fixes in ebpfapi

Signed-off-by: Alan Jowett <alanjo@microsoft.com>
This commit is contained in:
Alan Jowett 2022-12-29 12:53:16 -07:00 коммит произвёл GitHub
Родитель 9940e0cf32
Коммит 866bc2ac79
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 75 добавлений и 34 удалений

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

@ -161,6 +161,7 @@ _load_program_data_information(
} }
auto program_type_name_string = ebpf_down_cast_from_wstring(std::wstring(program_type_name)); auto program_type_name_string = ebpf_down_cast_from_wstring(std::wstring(program_type_name));
program_information = (ebpf_program_info_t*)ebpf_allocate(sizeof(ebpf_program_info_t)); program_information = (ebpf_program_info_t*)ebpf_allocate(sizeof(ebpf_program_info_t));
if (program_information == nullptr) { if (program_information == nullptr) {
result = EBPF_NO_MEMORY; result = EBPF_NO_MEMORY;
@ -263,13 +264,14 @@ Exit:
ebpf_free(helper_name); ebpf_free(helper_name);
if (result != EBPF_SUCCESS) { if (result != EBPF_SUCCESS) {
ebpf_free(descriptor); ebpf_free(descriptor);
ebpf_free(program_type_name);
ebpf_free(program_type);
ebpf_program_info_free(program_information); ebpf_program_info_free(program_information);
} }
if (program_info_key) { if (program_info_key) {
close_registry_key(program_info_key); close_registry_key(program_info_key);
} }
ebpf_free(program_type_name);
ebpf_free(program_type);
if (helper_key) { if (helper_key) {
close_registry_key(helper_key); close_registry_key(helper_key);
} }
@ -675,5 +677,6 @@ Exit:
ebpf_free(helper_prototype); ebpf_free(helper_prototype);
} }
} }
ebpf_free(helper_name);
return result; return result;
} }

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

@ -125,9 +125,9 @@ _get_program_descriptor_from_info(_In_ const ebpf_program_info_t* info, _Outptr_
{ {
ebpf_result_t result = EBPF_SUCCESS; ebpf_result_t result = EBPF_SUCCESS;
EbpfProgramType* type = nullptr; EbpfProgramType* type = nullptr;
char* name = nullptr;
try { try {
char* name = nullptr;
type = new (std::nothrow) EbpfProgramType(); type = new (std::nothrow) EbpfProgramType();
if (type == nullptr) { if (type == nullptr) {
result = EBPF_NO_MEMORY; result = EBPF_NO_MEMORY;
@ -164,6 +164,8 @@ _get_program_descriptor_from_info(_In_ const ebpf_program_info_t* info, _Outptr_
} }
Exit: Exit:
ebpf_free(name);
if (result != EBPF_SUCCESS) { if (result != EBPF_SUCCESS) {
_ebpf_program_descriptor_free(type); _ebpf_program_descriptor_free(type);
} }
@ -606,8 +608,8 @@ _load_all_section_data_information()
try { try {
for (uint32_t index = 0; index < section_info_count; index++) { for (uint32_t index = 0; index < section_info_count; index++) {
ebpf_section_definition_t* info = section_info[index]; ebpf_section_definition_t* info = section_info[index];
_windows_section_definitions.emplace_back(ebpf_section_info_ptr_t(info)); _windows_section_definitions.emplace_back(ebpf_section_info_ptr_t(info));
section_info[index] = nullptr;
} }
} catch (const std::bad_alloc&) { } catch (const std::bad_alloc&) {
result = EBPF_NO_MEMORY; result = EBPF_NO_MEMORY;
@ -619,6 +621,13 @@ Exit:
if (result != EBPF_SUCCESS) { if (result != EBPF_SUCCESS) {
_windows_section_definitions.clear(); _windows_section_definitions.clear();
} }
if (section_info) {
for (uint32_t index = 0; index < section_info_count; index++) {
_ebpf_section_info_free(section_info[index]);
section_info[index] = nullptr;
}
ebpf_free(section_info);
}
return result; return result;
} }
@ -644,6 +653,7 @@ _load_all_program_data_information()
ebpf_program_info_t* info = program_info[index]; ebpf_program_info_t* info = program_info[index];
ebpf_program_type_t program_type = info->program_type_descriptor.program_type; ebpf_program_type_t program_type = info->program_type_descriptor.program_type;
_windows_program_information[program_type] = ebpf_program_info_ptr_t(info); _windows_program_information[program_type] = ebpf_program_info_ptr_t(info);
program_info[index] = nullptr;
EbpfProgramType* program_data = nullptr; EbpfProgramType* program_data = nullptr;
result = _get_program_descriptor_from_info(info, &program_data); result = _get_program_descriptor_from_info(info, &program_data);
@ -663,6 +673,13 @@ Exit:
_windows_program_information.clear(); _windows_program_information.clear();
_windows_program_types.clear(); _windows_program_types.clear();
} }
if (program_info) {
for (uint32_t index = 0; index < program_info_count; index++) {
ebpf_program_info_free(program_info[index]);
program_info[index] = nullptr;
}
ebpf_free(program_info);
}
return result; return result;
} }

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

@ -303,6 +303,7 @@ handle_ebpf_show_verification(
if (status == ERROR_SUCCESS) { if (status == ERROR_SUCCESS) {
std::cout << report; std::cout << report;
std::cout << "\nProgram terminates within " << stats.max_instruction_count << " instructions\n"; std::cout << "\nProgram terminates within " << stats.max_instruction_count << " instructions\n";
ebpf_free_string(report);
return NO_ERROR; return NO_ERROR;
} else { } else {
if (error_message) { if (error_message) {

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

@ -654,6 +654,7 @@ TEST_CASE("program", "[execution_context]")
REQUIRE(addresses[0] != 0); REQUIRE(addresses[0] != 0);
REQUIRE(addresses[1] == 0); REQUIRE(addresses[1] == 0);
REQUIRE(addresses[2] != 0); REQUIRE(addresses[2] != 0);
ebpf_free_trampoline_table(table);
} }
TEST_CASE("name size", "[execution_context]") TEST_CASE("name size", "[execution_context]")

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

@ -40,13 +40,19 @@ class _test_helper
epoch_initiated = true; epoch_initiated = true;
REQUIRE(ebpf_async_initiate() == EBPF_SUCCESS); REQUIRE(ebpf_async_initiate() == EBPF_SUCCESS);
async_initiated = true; async_initiated = true;
REQUIRE(ebpf_state_initiate() == EBPF_SUCCESS);
state_initiated = true;
} }
~_test_helper() ~_test_helper()
{ {
if (state_initiated)
ebpf_state_terminate();
if (async_initiated) if (async_initiated)
ebpf_async_terminate(); ebpf_async_terminate();
if (epoch_initiated) if (epoch_initiated) {
ebpf_epoch_flush();
ebpf_epoch_terminate(); ebpf_epoch_terminate();
}
if (platform_initiated) if (platform_initiated)
ebpf_platform_terminate(); ebpf_platform_terminate();
ebpf_object_tracking_terminate(); ebpf_object_tracking_terminate();
@ -56,6 +62,7 @@ class _test_helper
bool platform_initiated = false; bool platform_initiated = false;
bool epoch_initiated = false; bool epoch_initiated = false;
bool async_initiated = false; bool async_initiated = false;
bool state_initiated = false;
}; };
TEST_CASE("hash_table_test", "[platform]") TEST_CASE("hash_table_test", "[platform]")
@ -669,7 +676,7 @@ TEST_CASE("serialize_map_test", "[platform]")
// Free de-serialized map info array. // Free de-serialized map info array.
ebpf_map_info_array_free(map_count, map_info_array); ebpf_map_info_array_free(map_count, map_info_array);
free(buffer); ebpf_free(buffer);
} }
TEST_CASE("serialize_program_info_test", "[platform]") TEST_CASE("serialize_program_info_test", "[platform]")
@ -750,11 +757,12 @@ TEST_CASE("serialize_program_info_test", "[platform]")
// Free de-serialized program info. // Free de-serialized program info.
ebpf_program_info_free(out_program_info); ebpf_program_info_free(out_program_info);
free(buffer); ebpf_free(buffer);
} }
TEST_CASE("state_test", "[state]") TEST_CASE("state_test", "[state]")
{ {
_test_helper test_helper;
size_t allocated_index_1 = 0; size_t allocated_index_1 = 0;
size_t allocated_index_2 = 0; size_t allocated_index_2 = 0;
struct struct
@ -762,16 +770,12 @@ TEST_CASE("state_test", "[state]")
uint32_t some_value; uint32_t some_value;
} foo; } foo;
uintptr_t retrieved_value = 0; uintptr_t retrieved_value = 0;
REQUIRE(ebpf_platform_initiate() == EBPF_SUCCESS);
REQUIRE(ebpf_state_initiate() == EBPF_SUCCESS);
REQUIRE(ebpf_state_allocate_index(&allocated_index_1) == EBPF_SUCCESS); REQUIRE(ebpf_state_allocate_index(&allocated_index_1) == EBPF_SUCCESS);
REQUIRE(ebpf_state_allocate_index(&allocated_index_2) == EBPF_SUCCESS); REQUIRE(ebpf_state_allocate_index(&allocated_index_2) == EBPF_SUCCESS);
REQUIRE(allocated_index_2 != allocated_index_1); REQUIRE(allocated_index_2 != allocated_index_1);
REQUIRE(ebpf_state_store(allocated_index_1, reinterpret_cast<uintptr_t>(&foo)) == EBPF_SUCCESS); REQUIRE(ebpf_state_store(allocated_index_1, reinterpret_cast<uintptr_t>(&foo)) == EBPF_SUCCESS);
REQUIRE(ebpf_state_load(allocated_index_1, &retrieved_value) == EBPF_SUCCESS); REQUIRE(ebpf_state_load(allocated_index_1, &retrieved_value) == EBPF_SUCCESS);
REQUIRE(retrieved_value == reinterpret_cast<uintptr_t>(&foo)); REQUIRE(retrieved_value == reinterpret_cast<uintptr_t>(&foo));
ebpf_state_terminate();
ebpf_platform_terminate();
} }
template <size_t bit_count, bool interlocked> template <size_t bit_count, bool interlocked>

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

@ -422,7 +422,7 @@ ebpf_map_memory(size_t length)
if (!descriptor->base) { if (!descriptor->base) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc); EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc);
free(descriptor); ebpf_free(descriptor);
descriptor = nullptr; descriptor = nullptr;
} }
return descriptor; return descriptor;
@ -435,7 +435,7 @@ ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor)
if (!VirtualFree(memory_descriptor->base, 0, MEM_RELEASE)) { if (!VirtualFree(memory_descriptor->base, 0, MEM_RELEASE)) {
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree); EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualFree);
} }
free(memory_descriptor); ebpf_free(memory_descriptor);
} }
} }

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

@ -184,7 +184,7 @@ ExAllocatePoolUninitialized(_In_ POOL_TYPE pool_type, _In_ size_t number_of_byte
void void
ExFreePool(void* p) ExFreePool(void* p)
{ {
free(p); ebpf_free(p);
} }
void void
@ -249,7 +249,7 @@ IoAllocateWorkItem(_In_ DEVICE_OBJECT* device_object)
work_item->device = device_object; work_item->device = device_object;
work_item->work_item = CreateThreadpoolWork(io_work_item_wrapper, work_item, nullptr); work_item->work_item = CreateThreadpoolWork(io_work_item_wrapper, work_item, nullptr);
if (work_item->work_item == nullptr) { if (work_item->work_item == nullptr) {
free(work_item); ebpf_free(work_item);
work_item = nullptr; work_item = nullptr;
} }
return work_item; return work_item;
@ -273,14 +273,14 @@ IoFreeWorkItem(_In_ __drv_freesMem(Mem) PIO_WORKITEM io_workitem)
{ {
if (io_workitem) { if (io_workitem) {
CloseThreadpoolWork(io_workitem->work_item); CloseThreadpoolWork(io_workitem->work_item);
free(io_workitem); ebpf_free(io_workitem);
} }
} }
void void
IoFreeMdl(MDL* mdl) IoFreeMdl(MDL* mdl)
{ {
free(mdl); ebpf_free(mdl);
} }
void void

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

@ -94,6 +94,9 @@
<ClCompile Include="..\ebpf_crypto_hash.c"> <ClCompile Include="..\ebpf_crypto_hash.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ebpf_leak_detector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Midl Include="..\ebpf_program_types.idl"> <Midl Include="..\ebpf_program_types.idl">

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

@ -388,7 +388,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
fd_t dropped_packet_map_fd = bpf_object__find_map_fd_by_name(object, "dropped_packet_map"); fd_t dropped_packet_map_fd = bpf_object__find_map_fd_by_name(object, "dropped_packet_map");
@ -436,6 +436,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
// Reattach to all interfaces so we can test the ingress_ifindex field passed to the program. // Reattach to all interfaces so we can test the ingress_ifindex field passed to the program.
hook.detach_link(link); hook.detach_link(link);
hook.close_link(link);
if_index = 0; if_index = 0;
REQUIRE(hook.attach_link(program_fd, &if_index, sizeof(if_index), &link) == EBPF_SUCCESS); REQUIRE(hook.attach_link(program_fd, &if_index, sizeof(if_index), &link) == EBPF_SUCCESS);
@ -479,7 +480,7 @@ divide_by_zero_test_um(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -521,7 +522,7 @@ bad_map_name_um(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == -EINVAL); REQUIRE(result == -EINVAL);
@ -598,7 +599,7 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map"); fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map");
@ -678,7 +679,7 @@ bindmonitor_tailcall_test(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map"); fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map");
@ -799,7 +800,7 @@ bindmonitor_ring_buffer_test(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -878,7 +879,7 @@ map_test(ebpf_execution_type_t execution_type)
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1020,7 +1021,7 @@ _cgroup_load_test(
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1147,7 +1148,7 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1207,7 +1208,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1221,7 +1222,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1293,7 +1294,7 @@ TEST_CASE("implicit_detach", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1338,7 +1339,7 @@ TEST_CASE("implicit_detach_2", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1387,7 +1388,7 @@ TEST_CASE("explicit_detach", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -1434,7 +1435,7 @@ TEST_CASE("implicit_explicit_detach", "[end_to_end]")
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(result == 0); REQUIRE(result == 0);
@ -2288,7 +2289,7 @@ TEST_CASE("load_native_program_negative3", "[end-to-end]")
"droppacket_um.dll", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &object, &program_fd, &error_message); "droppacket_um.dll", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &object, &program_fd, &error_message);
if (error_message) { if (error_message) {
printf("ebpf_program_load failed with %s\n", error_message); printf("ebpf_program_load failed with %s\n", error_message);
free((void*)error_message); ebpf_free((void*)error_message);
} }
REQUIRE(error == 0); REQUIRE(error == 0);
@ -2648,6 +2649,8 @@ TEST_CASE("get_bpf_attach_type", "[end_to_end]")
TEST_CASE("test_ebpf_object_set_execution_type", "[end_to_end]") TEST_CASE("test_ebpf_object_set_execution_type", "[end_to_end]")
{ {
_test_helper_end_to_end test_helper;
// First open a .dll file // First open a .dll file
bpf_object* native_object = bpf_object__open("droppacket_um.dll"); bpf_object* native_object = bpf_object__open("droppacket_um.dll");
REQUIRE(native_object != nullptr); REQUIRE(native_object != nullptr);

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

@ -145,7 +145,12 @@ typedef class _single_instance_hook : public _hook_helper
detach( detach(
fd_t program_fd, _In_reads_bytes_(attach_parameter_size) void* attach_parameter, size_t attach_parameter_size) fd_t program_fd, _In_reads_bytes_(attach_parameter_size) void* attach_parameter, size_t attach_parameter_size)
{ {
return ebpf_program_detach(program_fd, &attach_type, attach_parameter, attach_parameter_size); ebpf_result_t result = ebpf_program_detach(program_fd, &attach_type, attach_parameter, attach_parameter_size);
if (result == EBPF_SUCCESS) {
ebpf_link_close(link_object);
link_object = nullptr;
}
return result;
} }
void void

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

@ -549,6 +549,9 @@ _rundown_osfhandles()
} }
} }
void
clear_program_info_cache();
_test_helper_end_to_end::~_test_helper_end_to_end() _test_helper_end_to_end::~_test_helper_end_to_end()
{ {
try { try {
@ -569,6 +572,7 @@ _test_helper_end_to_end::~_test_helper_end_to_end()
// Detach all the native module clients. // Detach all the native module clients.
_unload_all_native_modules(); _unload_all_native_modules();
clear_program_info_cache();
if (api_initialized) if (api_initialized)
ebpf_api_terminate(); ebpf_api_terminate();
if (ec_initialized) if (ec_initialized)