From 8df10d319e7ee1bf6bcad393d83d19500a6818a6 Mon Sep 17 00:00:00 2001 From: "Alan Jowett (from Dev Box)" Date: Fri, 1 Mar 2024 16:06:10 -0800 Subject: [PATCH] Eliminate calls with FILE_FLAG_OVERLAPPED set, but no overlapped Signed-off-by: Alan Jowett (from Dev Box) --- libs/api/ebpf_api.cpp | 3 ++- libs/api_common/device_helper.cpp | 36 +++++++++++++++++++++++++++---- libs/api_common/device_helper.hpp | 5 ++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/libs/api/ebpf_api.cpp b/libs/api/ebpf_api.cpp index 6857487f5d..239258adb1 100644 --- a/libs/api/ebpf_api.cpp +++ b/libs/api/ebpf_api.cpp @@ -4472,7 +4472,8 @@ ebpf_program_test_run(fd_t program_fd, _Inout_ ebpf_test_run_options_t* options) if (result == EBPF_PENDING) { unsigned long bytes_returned; completion_event.wait(); - if (GetOverlappedResult(reinterpret_cast(get_device_handle()), &overlapped, &bytes_returned, FALSE)) { + if (GetOverlappedResult( + reinterpret_cast(get_async_device_handle()), &overlapped, &bytes_returned, FALSE)) { result = EBPF_SUCCESS; } else { result = win32_error_code_to_ebpf_result(GetLastError()); diff --git a/libs/api_common/device_helper.cpp b/libs/api_common/device_helper.cpp index 71c8646067..c5496295ab 100644 --- a/libs/api_common/device_helper.cpp +++ b/libs/api_common/device_helper.cpp @@ -26,7 +26,10 @@ typedef struct _async_ioctl_completion_context async_ioctl_completion_callback_t callback; } async_ioctl_completion_context_t; +// Handle used for synchronous calls to the driver. static ebpf_handle_t _device_handle = ebpf_handle_invalid; +// Handle used for asynchronous calls to the driver. +static ebpf_handle_t _async_device_handle = ebpf_handle_invalid; static std::mutex _mutex; _Must_inspect_result_ ebpf_result_t @@ -38,13 +41,28 @@ initialize_device_handle() return EBPF_ALREADY_INITIALIZED; } - _device_handle = Platform::CreateFile( - EBPF_DEVICE_WIN32_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); + if (_async_device_handle != ebpf_handle_invalid) { + return EBPF_ALREADY_INITIALIZED; + } + + // Open the device handle without the FILE_FLAG_OVERLAPPED flag for synchronous calls. + _device_handle = + Platform::CreateFile(EBPF_DEVICE_WIN32_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, 0); if (_device_handle == ebpf_handle_invalid) { return win32_error_code_to_ebpf_result(GetLastError()); } + // Open the device handle with the FILE_FLAG_OVERLAPPED flag for asynchronous calls. + _async_device_handle = Platform::CreateFile( + EBPF_DEVICE_WIN32_NAME, GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); + + if (_async_device_handle == ebpf_handle_invalid) { + Platform::CloseHandle(_device_handle); + _device_handle = ebpf_handle_invalid; + return win32_error_code_to_ebpf_result(GetLastError()); + } + return EBPF_SUCCESS; } @@ -70,6 +88,16 @@ get_device_handle() return _device_handle; } +ebpf_handle_t +get_async_device_handle() +{ + if (_async_device_handle == ebpf_handle_invalid) { + // Ignore failures. + (void)initialize_device_handle(); + } + return _async_device_handle; +} + void clean_up_async_ioctl_completion(_Inout_opt_ _Post_invalid_ async_ioctl_completion_t* async_ioctl_completion) { @@ -151,7 +179,7 @@ get_async_ioctl_result(_In_ const async_ioctl_completion_t* ioctl_completion) { unsigned long dummy; if (!GetOverlappedResult( - reinterpret_cast(get_device_handle()), + reinterpret_cast(get_async_device_handle()), get_async_ioctl_operation_overlapped(ioctl_completion), &dummy, FALSE)) @@ -219,5 +247,5 @@ initialize_async_ioctl_operation( bool cancel_async_ioctl(_Inout_opt_ OVERLAPPED* overlapped = nullptr) { - return Platform::CancelIoEx(get_device_handle(), overlapped); + return Platform::CancelIoEx(get_async_device_handle(), overlapped); } diff --git a/libs/api_common/device_helper.hpp b/libs/api_common/device_helper.hpp index c556f176ac..d0fce36672 100644 --- a/libs/api_common/device_helper.hpp +++ b/libs/api_common/device_helper.hpp @@ -37,6 +37,9 @@ clean_up_device_handle(); ebpf_handle_t get_device_handle(); +ebpf_handle_t +get_async_device_handle(); + typedef ebpf_result_t (*async_ioctl_completion_callback_t)(_Inout_opt_ void* completion_context); typedef struct _async_ioctl_completion_context async_ioctl_completion_t; @@ -101,7 +104,7 @@ invoke_ioctl(request_t& request, reply_t& reply = _empty_reply, _Inout_opt_ OVER } auto success = Platform::DeviceIoControl( - get_device_handle(), + overlapped ? get_async_device_handle() : get_device_handle(), IOCTL_EBPF_CTL_METHOD_BUFFERED, request_ptr, request_size,