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:
Родитель
9940e0cf32
Коммит
866bc2ac79
|
@ -161,6 +161,7 @@ _load_program_data_information(
|
|||
}
|
||||
|
||||
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));
|
||||
if (program_information == nullptr) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
|
@ -263,13 +264,14 @@ Exit:
|
|||
ebpf_free(helper_name);
|
||||
if (result != EBPF_SUCCESS) {
|
||||
ebpf_free(descriptor);
|
||||
ebpf_free(program_type_name);
|
||||
ebpf_free(program_type);
|
||||
ebpf_program_info_free(program_information);
|
||||
}
|
||||
if (program_info_key) {
|
||||
close_registry_key(program_info_key);
|
||||
}
|
||||
ebpf_free(program_type_name);
|
||||
ebpf_free(program_type);
|
||||
|
||||
if (helper_key) {
|
||||
close_registry_key(helper_key);
|
||||
}
|
||||
|
@ -675,5 +677,6 @@ Exit:
|
|||
ebpf_free(helper_prototype);
|
||||
}
|
||||
}
|
||||
ebpf_free(helper_name);
|
||||
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;
|
||||
EbpfProgramType* type = nullptr;
|
||||
char* name = nullptr;
|
||||
|
||||
try {
|
||||
char* name = nullptr;
|
||||
type = new (std::nothrow) EbpfProgramType();
|
||||
if (type == nullptr) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
|
@ -164,6 +164,8 @@ _get_program_descriptor_from_info(_In_ const ebpf_program_info_t* info, _Outptr_
|
|||
}
|
||||
|
||||
Exit:
|
||||
ebpf_free(name);
|
||||
|
||||
if (result != EBPF_SUCCESS) {
|
||||
_ebpf_program_descriptor_free(type);
|
||||
}
|
||||
|
@ -606,8 +608,8 @@ _load_all_section_data_information()
|
|||
try {
|
||||
for (uint32_t index = 0; index < section_info_count; index++) {
|
||||
ebpf_section_definition_t* info = section_info[index];
|
||||
|
||||
_windows_section_definitions.emplace_back(ebpf_section_info_ptr_t(info));
|
||||
section_info[index] = nullptr;
|
||||
}
|
||||
} catch (const std::bad_alloc&) {
|
||||
result = EBPF_NO_MEMORY;
|
||||
|
@ -619,6 +621,13 @@ Exit:
|
|||
if (result != EBPF_SUCCESS) {
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -644,6 +653,7 @@ _load_all_program_data_information()
|
|||
ebpf_program_info_t* info = program_info[index];
|
||||
ebpf_program_type_t program_type = info->program_type_descriptor.program_type;
|
||||
_windows_program_information[program_type] = ebpf_program_info_ptr_t(info);
|
||||
program_info[index] = nullptr;
|
||||
|
||||
EbpfProgramType* program_data = nullptr;
|
||||
result = _get_program_descriptor_from_info(info, &program_data);
|
||||
|
@ -663,6 +673,13 @@ Exit:
|
|||
_windows_program_information.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;
|
||||
}
|
||||
|
||||
|
|
|
@ -303,6 +303,7 @@ handle_ebpf_show_verification(
|
|||
if (status == ERROR_SUCCESS) {
|
||||
std::cout << report;
|
||||
std::cout << "\nProgram terminates within " << stats.max_instruction_count << " instructions\n";
|
||||
ebpf_free_string(report);
|
||||
return NO_ERROR;
|
||||
} else {
|
||||
if (error_message) {
|
||||
|
|
|
@ -654,6 +654,7 @@ TEST_CASE("program", "[execution_context]")
|
|||
REQUIRE(addresses[0] != 0);
|
||||
REQUIRE(addresses[1] == 0);
|
||||
REQUIRE(addresses[2] != 0);
|
||||
ebpf_free_trampoline_table(table);
|
||||
}
|
||||
|
||||
TEST_CASE("name size", "[execution_context]")
|
||||
|
|
|
@ -40,13 +40,19 @@ class _test_helper
|
|||
epoch_initiated = true;
|
||||
REQUIRE(ebpf_async_initiate() == EBPF_SUCCESS);
|
||||
async_initiated = true;
|
||||
REQUIRE(ebpf_state_initiate() == EBPF_SUCCESS);
|
||||
state_initiated = true;
|
||||
}
|
||||
~_test_helper()
|
||||
{
|
||||
if (state_initiated)
|
||||
ebpf_state_terminate();
|
||||
if (async_initiated)
|
||||
ebpf_async_terminate();
|
||||
if (epoch_initiated)
|
||||
if (epoch_initiated) {
|
||||
ebpf_epoch_flush();
|
||||
ebpf_epoch_terminate();
|
||||
}
|
||||
if (platform_initiated)
|
||||
ebpf_platform_terminate();
|
||||
ebpf_object_tracking_terminate();
|
||||
|
@ -56,6 +62,7 @@ class _test_helper
|
|||
bool platform_initiated = false;
|
||||
bool epoch_initiated = false;
|
||||
bool async_initiated = false;
|
||||
bool state_initiated = false;
|
||||
};
|
||||
|
||||
TEST_CASE("hash_table_test", "[platform]")
|
||||
|
@ -669,7 +676,7 @@ TEST_CASE("serialize_map_test", "[platform]")
|
|||
// Free de-serialized 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]")
|
||||
|
@ -750,11 +757,12 @@ TEST_CASE("serialize_program_info_test", "[platform]")
|
|||
// Free de-serialized program info.
|
||||
ebpf_program_info_free(out_program_info);
|
||||
|
||||
free(buffer);
|
||||
ebpf_free(buffer);
|
||||
}
|
||||
|
||||
TEST_CASE("state_test", "[state]")
|
||||
{
|
||||
_test_helper test_helper;
|
||||
size_t allocated_index_1 = 0;
|
||||
size_t allocated_index_2 = 0;
|
||||
struct
|
||||
|
@ -762,16 +770,12 @@ TEST_CASE("state_test", "[state]")
|
|||
uint32_t some_value;
|
||||
} foo;
|
||||
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_2) == EBPF_SUCCESS);
|
||||
REQUIRE(allocated_index_2 != allocated_index_1);
|
||||
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(retrieved_value == reinterpret_cast<uintptr_t>(&foo));
|
||||
ebpf_state_terminate();
|
||||
ebpf_platform_terminate();
|
||||
}
|
||||
|
||||
template <size_t bit_count, bool interlocked>
|
||||
|
|
|
@ -422,7 +422,7 @@ ebpf_map_memory(size_t length)
|
|||
|
||||
if (!descriptor->base) {
|
||||
EBPF_LOG_WIN32_API_FAILURE(EBPF_TRACELOG_KEYWORD_BASE, VirtualAlloc);
|
||||
free(descriptor);
|
||||
ebpf_free(descriptor);
|
||||
descriptor = nullptr;
|
||||
}
|
||||
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)) {
|
||||
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
|
||||
ExFreePool(void* p)
|
||||
{
|
||||
free(p);
|
||||
ebpf_free(p);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -249,7 +249,7 @@ IoAllocateWorkItem(_In_ DEVICE_OBJECT* device_object)
|
|||
work_item->device = device_object;
|
||||
work_item->work_item = CreateThreadpoolWork(io_work_item_wrapper, work_item, nullptr);
|
||||
if (work_item->work_item == nullptr) {
|
||||
free(work_item);
|
||||
ebpf_free(work_item);
|
||||
work_item = nullptr;
|
||||
}
|
||||
return work_item;
|
||||
|
@ -273,14 +273,14 @@ IoFreeWorkItem(_In_ __drv_freesMem(Mem) PIO_WORKITEM io_workitem)
|
|||
{
|
||||
if (io_workitem) {
|
||||
CloseThreadpoolWork(io_workitem->work_item);
|
||||
free(io_workitem);
|
||||
ebpf_free(io_workitem);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IoFreeMdl(MDL* mdl)
|
||||
{
|
||||
free(mdl);
|
||||
ebpf_free(mdl);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -94,6 +94,9 @@
|
|||
<ClCompile Include="..\ebpf_crypto_hash.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ebpf_leak_detector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="..\ebpf_program_types.idl">
|
||||
|
|
|
@ -388,7 +388,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
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.
|
||||
hook.detach_link(link);
|
||||
hook.close_link(link);
|
||||
if_index = 0;
|
||||
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) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -521,7 +522,7 @@ bad_map_name_um(ebpf_execution_type_t execution_type)
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == -EINVAL);
|
||||
|
||||
|
@ -598,7 +599,7 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
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) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
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) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -878,7 +879,7 @@ map_test(ebpf_execution_type_t execution_type)
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1020,7 +1021,7 @@ _cgroup_load_test(
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
|
||||
REQUIRE(result == 0);
|
||||
|
@ -1147,7 +1148,7 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1207,7 +1208,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1221,7 +1222,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1293,7 +1294,7 @@ TEST_CASE("implicit_detach", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1338,7 +1339,7 @@ TEST_CASE("implicit_detach_2", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1387,7 +1388,7 @@ TEST_CASE("explicit_detach", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
REQUIRE(result == 0);
|
||||
|
||||
|
@ -1434,7 +1435,7 @@ TEST_CASE("implicit_explicit_detach", "[end_to_end]")
|
|||
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
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);
|
||||
if (error_message) {
|
||||
printf("ebpf_program_load failed with %s\n", error_message);
|
||||
free((void*)error_message);
|
||||
ebpf_free((void*)error_message);
|
||||
}
|
||||
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_helper_end_to_end test_helper;
|
||||
|
||||
// First open a .dll file
|
||||
bpf_object* native_object = bpf_object__open("droppacket_um.dll");
|
||||
REQUIRE(native_object != nullptr);
|
||||
|
|
|
@ -145,7 +145,12 @@ typedef class _single_instance_hook : public _hook_helper
|
|||
detach(
|
||||
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
|
||||
|
|
|
@ -549,6 +549,9 @@ _rundown_osfhandles()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
clear_program_info_cache();
|
||||
|
||||
_test_helper_end_to_end::~_test_helper_end_to_end()
|
||||
{
|
||||
try {
|
||||
|
@ -569,6 +572,7 @@ _test_helper_end_to_end::~_test_helper_end_to_end()
|
|||
// Detach all the native module clients.
|
||||
_unload_all_native_modules();
|
||||
|
||||
clear_program_info_cache();
|
||||
if (api_initialized)
|
||||
ebpf_api_terminate();
|
||||
if (ec_initialized)
|
||||
|
|
Загрузка…
Ссылка в новой задаче