From a332f54a1bfce683382228a3a66556a79abd613b Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 30 Oct 2020 14:21:13 +0100 Subject: [PATCH] api: only sleep after force closing handles if required Also force close handles when deleting the adapter, in case the function is called from another process, for example an uninstaller. Signed-off-by: Jason A. Donenfeld --- api/adapter.c | 18 +++++++++++++----- wintun.c | 10 ++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/api/adapter.c b/api/adapter.c index 459d155..741cec9 100644 --- a/api/adapter.c +++ b/api/adapter.c @@ -214,9 +214,15 @@ ForceCloseWintunAdapterHandle(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevIn LOG(WINTUN_LOG_ERR, L"Failed to get adapter device object"); goto out; } - Result = DeviceIoControl(NdisHandle, TUN_IOCTL_FORCE_CLOSE_HANDLES, NULL, 0, NULL, 0, &RequiredBytes, NULL) - ? ERROR_SUCCESS - : LOG_LAST_ERROR(L"Failed to perform ioctl"); + if (DeviceIoControl(NdisHandle, TUN_IOCTL_FORCE_CLOSE_HANDLES, NULL, 0, NULL, 0, &RequiredBytes, NULL)) + { + Result = ERROR_SUCCESS; + Sleep(200); + } + else if (GetLastError() == ERROR_NOTHING_TO_TERMINATE) + Result = ERROR_SUCCESS; + else + Result = LOG_LAST_ERROR(L"Failed to perform ioctl"); CloseHandle(NdisHandle); out: HeapFree(ModuleHeap, 0, InstanceId); @@ -258,7 +264,6 @@ AdapterDisableAllOurs(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **Disa LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter"); if (ForceCloseWintunAdapterHandle(DevInfo, &DeviceNode->Data) != ERROR_SUCCESS) LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles"); - Sleep(200); LOG(WINTUN_LOG_INFO, L"Disabling existing adapter"); if (!SetupDiSetClassInstallParamsW(DevInfo, &DeviceNode->Data, &Params.ClassInstallHeader, sizeof(Params)) || @@ -327,7 +332,6 @@ AdapterDeleteAllOurs(void) LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter"); if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS) LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles"); - Sleep(200); LOG(WINTUN_LOG_INFO, L"Removing existing adapter"); if (!SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) || @@ -1717,6 +1721,10 @@ WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _Inout_ BOOL *RebootRequ LOG(WINTUN_LOG_ERR, L"Failed to get device info data"); goto cleanupToken; } + + if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS) + LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles"); + SetQuietInstall(DevInfo, &DevInfoData); SP_REMOVEDEVICE_PARAMS RemoveDeviceParams = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER), .InstallFunction = DIF_REMOVE }, diff --git a/wintun.c b/wintun.c index 60eb9dd..55d6963 100644 --- a/wintun.c +++ b/wintun.c @@ -759,7 +759,7 @@ TunUnregisterBuffers(_Inout_ TUN_CTX *Ctx, _In_ FILE_OBJECT *Owner) } _IRQL_requires_max_(PASSIVE_LEVEL) -static VOID +static BOOLEAN TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject) { NTSTATUS Status; @@ -769,6 +769,7 @@ TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject) ULONG VerifierFlags = 0; OBJECT_HANDLE_INFORMATION HandleInfo; SYSTEM_HANDLE_INFORMATION_EX *HandleTable = NULL; + BOOLEAN DidClose = FALSE; MmIsVerifierEnabled(&VerifierFlags); @@ -781,7 +782,7 @@ TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject) ExFreePoolWithTag(HandleTable, TUN_MEMORY_TAG); HandleTable = ExAllocatePoolWithTag(PagedPool, RequestedSize, TUN_MEMORY_TAG); if (!HandleTable) - return; + return FALSE; } if (!NT_SUCCESS(Status) || !HandleTable) goto cleanup; @@ -808,6 +809,7 @@ TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject) ObCloseHandle(HandleTable->Handles[Index].HandleValue, UserMode); if (!VerifierFlags) ObfDereferenceObject(Object); + DidClose = TRUE; } KeUnstackDetachProcess(&ApcState); ObfDereferenceObject(Process); @@ -815,6 +817,7 @@ TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject) cleanup: if (HandleTable) ExFreePoolWithTag(HandleTable, TUN_MEMORY_TAG); + return DidClose; } static NTSTATUS TunInitializeDispatchSecurityDescriptor(VOID) @@ -927,8 +930,7 @@ TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp) break; } case TUN_IOCTL_FORCE_CLOSE_HANDLES: - TunForceHandlesClosed(Stack->FileObject->DeviceObject); - Status = STATUS_SUCCESS; + Status = TunForceHandlesClosed(Stack->FileObject->DeviceObject) ? STATUS_SUCCESS : STATUS_NOTHING_TO_TERMINATE; break; } cleanup: