aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--undocumented.h39
-rw-r--r--wintun.c89
-rw-r--r--wintun.proj6
-rw-r--r--wintun.vcxproj3
-rw-r--r--wintun.vcxproj.filters5
5 files changed, 131 insertions, 11 deletions
diff --git a/undocumented.h b/undocumented.h
new file mode 100644
index 0000000..c904c7a
--- /dev/null
+++ b/undocumented.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+#pragma once
+
+#include <wdm.h>
+
+typedef enum
+{
+ SystemExtendedHandleInformation = 0x40
+} SYSTEM_INFORMATION_CLASS;
+
+typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
+{
+ PVOID Object;
+ HANDLE UniqueProcessId;
+ HANDLE HandleValue;
+ ACCESS_MASK GrantedAccess;
+ USHORT CreatorBackTraceIndex;
+ USHORT ObjectTypeIndex;
+ ULONG HandleAttributes;
+ ULONG Reserved;
+} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION_EX
+{
+ ULONG_PTR NumberOfHandles;
+ ULONG_PTR Reserved;
+ SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ANYSIZE_ARRAY];
+} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
+
+extern NTSTATUS
+ZwQuerySystemInformation(
+ SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ PVOID SystemInformation,
+ ULONG SystemInformationLength,
+ ULONG *ReturnLength);
diff --git a/wintun.c b/wintun.c
index ee11243..c870e7b 100644
--- a/wintun.c
+++ b/wintun.c
@@ -8,6 +8,7 @@
#include <wdmsec.h>
#include <ndis.h>
#include <ntstrsafe.h>
+#include "undocumented.h"
#pragma warning(disable : 4100) /* unreferenced formal parameter */
#pragma warning(disable : 4200) /* nonstandard: zero-sized array in struct/union */
@@ -98,10 +99,12 @@ typedef struct _TUN_REGISTER_RINGS
} Send, Receive;
} TUN_REGISTER_RINGS;
-/* Register rings hosted by the client
+/* Register rings hosted by the client.
* The lpInBuffer and nInBufferSize parameters of DeviceIoControl() must point to an TUN_REGISTER_RINGS struct.
* Client must wait for this IOCTL to finish before adding packets to the ring. */
#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820, 0x970, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
+/* Force close all open handles to allow for updating. */
+#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820, 0x971, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
typedef enum _TUN_FLAGS
{
@@ -749,6 +752,65 @@ TunUnregisterBuffers(_Inout_ TUN_CTX *Ctx, _In_ FILE_OBJECT *Owner)
ObDereferenceObject(Ctx->Device.Send.TailMoved);
}
+_IRQL_requires_max_(PASSIVE_LEVEL)
+static void
+TunForceHandlesClosed(_Inout_ DEVICE_OBJECT *DeviceObject)
+{
+ NTSTATUS Status;
+ PEPROCESS Process;
+ KAPC_STATE ApcState;
+ PVOID Object = NULL;
+ ULONG VerifierFlags = 0;
+ OBJECT_HANDLE_INFORMATION HandleInfo;
+ SYSTEM_HANDLE_INFORMATION_EX *HandleTable = NULL;
+
+ MmIsVerifierEnabled(&VerifierFlags);
+
+ for (ULONG Size = 0, RequestedSize;
+ (Status = ZwQuerySystemInformation(SystemExtendedHandleInformation, HandleTable, Size, &RequestedSize)) ==
+ STATUS_INFO_LENGTH_MISMATCH;
+ Size = RequestedSize)
+ {
+ if (HandleTable)
+ ExFreePoolWithTag(HandleTable, TUN_MEMORY_TAG);
+ HandleTable = ExAllocatePoolWithTag(PagedPool, RequestedSize, TUN_MEMORY_TAG);
+ if (!HandleTable)
+ return;
+ }
+ if (!NT_SUCCESS(Status) || !HandleTable)
+ goto cleanup;
+
+ HANDLE CurrentProcessId = PsGetCurrentProcessId();
+ for (ULONG_PTR Index = 0; Index < HandleTable->NumberOfHandles; ++Index)
+ {
+ FILE_OBJECT *FileObject = HandleTable->Handles[Index].Object;
+ if (!FileObject || FileObject->Type != 5 || FileObject->DeviceObject != DeviceObject)
+ continue;
+ HANDLE ProcessId = HandleTable->Handles[Index].UniqueProcessId;
+ if (ProcessId == CurrentProcessId)
+ continue;
+ Status = PsLookupProcessByProcessId(ProcessId, &Process);
+ if (!NT_SUCCESS(Status))
+ continue;
+ KeStackAttachProcess(Process, &ApcState);
+ if (!VerifierFlags)
+ Status = ObReferenceObjectByHandle(
+ HandleTable->Handles[Index].HandleValue, 0, NULL, UserMode, &Object, &HandleInfo);
+ if (NT_SUCCESS(Status))
+ {
+ if (VerifierFlags || Object == FileObject)
+ ObCloseHandle(HandleTable->Handles[Index].HandleValue, UserMode);
+ if (!VerifierFlags)
+ ObfDereferenceObject(Object);
+ }
+ KeUnstackDetachProcess(&ApcState);
+ ObfDereferenceObject(Process);
+ }
+cleanup:
+ if (HandleTable)
+ ExFreePoolWithTag(HandleTable, TUN_MEMORY_TAG);
+}
+
static NTSTATUS TunInitializeDispatchSecurityDescriptor(VOID)
{
NTSTATUS Status;
@@ -795,7 +857,8 @@ static NTSTATUS
TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
IO_STACK_LOCATION *Stack = IoGetCurrentIrpStackLocation(Irp);
- if (Stack->Parameters.DeviceIoControl.IoControlCode != TUN_IOCTL_REGISTER_RINGS)
+ if (Stack->Parameters.DeviceIoControl.IoControlCode != TUN_IOCTL_REGISTER_RINGS &&
+ Stack->Parameters.DeviceIoControl.IoControlCode != TUN_IOCTL_FORCE_CLOSE_HANDLES)
return NdisDispatchDeviceControl(DeviceObject, Irp);
SECURITY_SUBJECT_CONTEXT SubjectContext;
@@ -816,13 +879,23 @@ TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
SeReleaseSubjectContext(&SubjectContext);
if (!HasAccess)
goto cleanup;
- ExAcquireResourceSharedLite(&TunDispatchCtxGuard, TRUE);
+ switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case TUN_IOCTL_REGISTER_RINGS: {
+ ExAcquireResourceSharedLite(&TunDispatchCtxGuard, TRUE);
#pragma warning(suppress : 28175)
- TUN_CTX *Ctx = DeviceObject->Reserved;
- Status = NDIS_STATUS_ADAPTER_NOT_READY;
- if (Ctx)
- Status = TunRegisterBuffers(Ctx, Irp);
- ExReleaseResourceLite(&TunDispatchCtxGuard);
+ TUN_CTX *Ctx = DeviceObject->Reserved;
+ Status = NDIS_STATUS_ADAPTER_NOT_READY;
+ if (Ctx)
+ Status = TunRegisterBuffers(Ctx, Irp);
+ ExReleaseResourceLite(&TunDispatchCtxGuard);
+ break;
+ }
+ case TUN_IOCTL_FORCE_CLOSE_HANDLES:
+ TunForceHandlesClosed(Stack->FileObject->DeviceObject);
+ Status = STATUS_SUCCESS;
+ break;
+ }
cleanup:
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
diff --git a/wintun.proj b/wintun.proj
index bd4a32c..7f787a0 100644
--- a/wintun.proj
+++ b/wintun.proj
@@ -30,17 +30,17 @@
-->
<Target Name="Driver-x86"
Outputs="x86\Release\wintun\wintun.sys;x86\Release\wintun\wintun.inf;x86\Release\wintun\wintun.cat"
- Inputs="wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
+ Inputs="undocumented.h;wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=Win32"/>
</Target>
<Target Name="Driver-amd64"
Outputs="amd64\Release\wintun\wintun.sys;amd64\Release\wintun\wintun.inf;amd64\Release\wintun\wintun.cat"
- Inputs="wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
+ Inputs="undocumented.h;wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=x64"/>
</Target>
<Target Name="Driver-arm64"
Outputs="arm64\Release\wintun\wintun.sys;arm64\Release\wintun\wintun.inf;arm64\Release\wintun\wintun.cat"
- Inputs="wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
+ Inputs="undocumented.h;wintun.c;wintun.inf;wintun.props;wintun.rc;wintun.vcxproj">
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=ARM64"/>
</Target>
diff --git a/wintun.vcxproj b/wintun.vcxproj
index 693e3db..4d72a65 100644
--- a/wintun.vcxproj
+++ b/wintun.vcxproj
@@ -176,6 +176,9 @@
<Inf Include="wintun.inf" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="undocumented.h" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project> \ No newline at end of file
diff --git a/wintun.vcxproj.filters b/wintun.vcxproj.filters
index 7077380..5a7e2d9 100644
--- a/wintun.vcxproj.filters
+++ b/wintun.vcxproj.filters
@@ -29,4 +29,9 @@
<Filter>Source Files</Filter>
</Inf>
</ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="undocumented.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
</Project> \ No newline at end of file