From 0a8bf9d1ff0f67bf3906b4cb5ef98a166a1a0bdb Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 30 Oct 2020 14:34:40 +0100 Subject: [PATCH] api: only force close handles if requested Signed-off-by: Jason A. Donenfeld --- api/adapter.c | 13 +++++++------ api/adapter.h | 2 +- api/rundll32.c | 5 +++-- api/wintun.h | 12 ++++++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/api/adapter.c b/api/adapter.c index 741cec9..30c3afe 100644 --- a/api/adapter.c +++ b/api/adapter.c @@ -1657,16 +1657,17 @@ cleanupToken: #ifdef MAYBE_WOW64 static WINTUN_STATUS -DeleteAdapterNatively(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequired) +DeleteAdapterNatively(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Inout_ BOOL *RebootRequired) { LOG(WINTUN_LOG_INFO, L"Spawning native process"); WCHAR GuidStr[MAX_GUID_STRING_LEN]; - WCHAR Arguments[14 + MAX_GUID_STRING_LEN + 1]; + WCHAR Arguments[16 + MAX_GUID_STRING_LEN + 1]; if (_snwprintf_s( Arguments, _countof(Arguments), _TRUNCATE, - L"DeleteAdapter %.*s", + L"DeleteAdapter %d %.*s", + ForceCloseSessions ? 1 : 0, StringFromGUID2(&Adapter->CfgInstanceID, GuidStr, _countof(GuidStr)), GuidStr) == -1) return LOG(WINTUN_LOG_ERR, L"Command line too long"), ERROR_INVALID_PARAMETER; @@ -1693,7 +1694,7 @@ cleanupArgv: #endif WINTUN_STATUS WINAPI -WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequired) +WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Inout_ BOOL *RebootRequired) { if (!ElevateToSystem()) return LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user"), ERROR_ACCESS_DENIED; @@ -1702,7 +1703,7 @@ WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequ #ifdef MAYBE_WOW64 if (NativeMachine != IMAGE_FILE_PROCESS) { - Result = DeleteAdapterNatively(Adapter, RebootRequired); + Result = DeleteAdapterNatively(Adapter, ForceCloseSessions, RebootRequired); RevertToSelf(); return Result; } @@ -1722,7 +1723,7 @@ WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequ goto cleanupToken; } - if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS) + if (ForceCloseSessions && ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS) LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles"); SetQuietInstall(DevInfo, &DevInfoData); diff --git a/api/adapter.h b/api/adapter.h index c0e4c53..d57ca35 100644 --- a/api/adapter.h +++ b/api/adapter.h @@ -115,4 +115,4 @@ WintunCreateAdapter( * @copydoc WINTUN_DELETE_ADAPTER_FUNC */ WINTUN_STATUS WINAPI -WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequired); +WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Inout_ BOOL *RebootRequired); diff --git a/api/rundll32.c b/api/rundll32.c index ac678a5..164b305 100644 --- a/api/rundll32.c +++ b/api/rundll32.c @@ -121,10 +121,11 @@ VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int goto cleanup; WINTUN_ADAPTER Adapter = { 0 }; - if (FAILED(CLSIDFromString(Argv[2], &Adapter.CfgInstanceID))) + BOOL ForceCloseSessions = wcstoul(Argv[2], NULL, 10); + if (FAILED(CLSIDFromString(Argv[3], &Adapter.CfgInstanceID))) goto cleanup; BOOL RebootRequired = FALSE; - WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", WintunDeleteAdapter(&Adapter, &RebootRequired), RebootRequired); + WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", WintunDeleteAdapter(&Adapter, ForceCloseSessions, &RebootRequired), RebootRequired); cleanup: Done(); diff --git a/api/wintun.h b/api/wintun.h index ff79d8a..8137155 100644 --- a/api/wintun.h +++ b/api/wintun.h @@ -52,15 +52,19 @@ typedef WINTUN_STATUS(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)( /** * Deletes a Wintun adapter. * - * @param Adapter Adapter handle obtained with WintunGetAdapter or WintunCreateAdapter. + * @param Adapter Adapter handle obtained with WintunGetAdapter or WintunCreateAdapter. * - * @param RebootRequired Pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot. Must be - * initialised to FALSE manually before this function is called. + * @param ForceCloseSessions Force close adapter handles that may be in use by other processes. Only set this to TRUE + * with extreme care, as this is resource intensive and may put processes into an undefined + * or unpredictable state. Most users should set this to FALSE. + * + * @param RebootRequired Pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot. Must be + * initialised to FALSE manually before this function is called. * * @return ERROR_SUCCESS on success or the adapter was not found; Win32 error code otherwise. */ typedef WINTUN_STATUS( - WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Inout_ BOOL *RebootRequired); + WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ BOOL ForceCloseSessions, _Inout_ BOOL *RebootRequired); /** * Called by WintunEnumAdapters for each adapter in the pool.