Add handle closing ioctl
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
0d9b9b925a
commit
5239d53db0
39
undocumented.h
Normal file
39
undocumented.h
Normal file
@ -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);
|
89
wintun.c
89
wintun.c
@ -8,6 +8,7 @@
|
|||||||
#include <wdmsec.h>
|
#include <wdmsec.h>
|
||||||
#include <ndis.h>
|
#include <ndis.h>
|
||||||
#include <ntstrsafe.h>
|
#include <ntstrsafe.h>
|
||||||
|
#include "undocumented.h"
|
||||||
|
|
||||||
#pragma warning(disable : 4100) /* unreferenced formal parameter */
|
#pragma warning(disable : 4100) /* unreferenced formal parameter */
|
||||||
#pragma warning(disable : 4200) /* nonstandard: zero-sized array in struct/union */
|
#pragma warning(disable : 4200) /* nonstandard: zero-sized array in struct/union */
|
||||||
@ -98,10 +99,12 @@ typedef struct _TUN_REGISTER_RINGS
|
|||||||
} Send, Receive;
|
} Send, Receive;
|
||||||
} TUN_REGISTER_RINGS;
|
} 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.
|
* 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. */
|
* 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)
|
#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
|
typedef enum _TUN_FLAGS
|
||||||
{
|
{
|
||||||
@ -749,6 +752,65 @@ TunUnregisterBuffers(_Inout_ TUN_CTX *Ctx, _In_ FILE_OBJECT *Owner)
|
|||||||
ObDereferenceObject(Ctx->Device.Send.TailMoved);
|
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)
|
static NTSTATUS TunInitializeDispatchSecurityDescriptor(VOID)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
@ -795,7 +857,8 @@ static NTSTATUS
|
|||||||
TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
|
TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *Stack = IoGetCurrentIrpStackLocation(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);
|
return NdisDispatchDeviceControl(DeviceObject, Irp);
|
||||||
|
|
||||||
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
||||||
@ -816,13 +879,23 @@ TunDispatchDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp)
|
|||||||
SeReleaseSubjectContext(&SubjectContext);
|
SeReleaseSubjectContext(&SubjectContext);
|
||||||
if (!HasAccess)
|
if (!HasAccess)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
ExAcquireResourceSharedLite(&TunDispatchCtxGuard, TRUE);
|
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case TUN_IOCTL_REGISTER_RINGS: {
|
||||||
|
ExAcquireResourceSharedLite(&TunDispatchCtxGuard, TRUE);
|
||||||
#pragma warning(suppress : 28175)
|
#pragma warning(suppress : 28175)
|
||||||
TUN_CTX *Ctx = DeviceObject->Reserved;
|
TUN_CTX *Ctx = DeviceObject->Reserved;
|
||||||
Status = NDIS_STATUS_ADAPTER_NOT_READY;
|
Status = NDIS_STATUS_ADAPTER_NOT_READY;
|
||||||
if (Ctx)
|
if (Ctx)
|
||||||
Status = TunRegisterBuffers(Ctx, Irp);
|
Status = TunRegisterBuffers(Ctx, Irp);
|
||||||
ExReleaseResourceLite(&TunDispatchCtxGuard);
|
ExReleaseResourceLite(&TunDispatchCtxGuard);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TUN_IOCTL_FORCE_CLOSE_HANDLES:
|
||||||
|
TunForceHandlesClosed(Stack->FileObject->DeviceObject);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
@ -30,17 +30,17 @@
|
|||||||
-->
|
-->
|
||||||
<Target Name="Driver-x86"
|
<Target Name="Driver-x86"
|
||||||
Outputs="x86\Release\wintun\wintun.sys;x86\Release\wintun\wintun.inf;x86\Release\wintun\wintun.cat"
|
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"/>
|
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=Win32"/>
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Driver-amd64"
|
<Target Name="Driver-amd64"
|
||||||
Outputs="amd64\Release\wintun\wintun.sys;amd64\Release\wintun\wintun.inf;amd64\Release\wintun\wintun.cat"
|
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"/>
|
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=x64"/>
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="Driver-arm64"
|
<Target Name="Driver-arm64"
|
||||||
Outputs="arm64\Release\wintun\wintun.sys;arm64\Release\wintun\wintun.inf;arm64\Release\wintun\wintun.cat"
|
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"/>
|
<MSBuild Projects="wintun.vcxproj" Targets="Build" Properties="Configuration=Release;Platform=ARM64"/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
@ -176,6 +176,9 @@
|
|||||||
<Inf Include="wintun.inf" />
|
<Inf Include="wintun.inf" />
|
||||||
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="undocumented.h" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets" />
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
</Project>
|
</Project>
|
@ -29,4 +29,9 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</Inf>
|
</Inf>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="undocumented.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user