Simplify IRP processing after mapping
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
d82a68f830
commit
ae6e72a39e
65
wintun.c
65
wintun.c
@ -263,35 +263,6 @@ TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp)
|
|||||||
TunCompleteRequest(ctx, Irp, STATUS_CANCELLED, IO_NO_INCREMENT);
|
TunCompleteRequest(ctx, Irp, STATUS_CANCELLED, IO_NO_INCREMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
||||||
_Must_inspect_result_
|
|
||||||
static NTSTATUS
|
|
||||||
TunGetIrpBuffer(_In_ IRP *Irp, _Out_ UCHAR **buffer, _Out_ ULONG *Size)
|
|
||||||
{
|
|
||||||
TUN_MAPPED_UBUFFER *ubuffer;
|
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext;
|
|
||||||
|
|
||||||
switch (stack->MajorFunction)
|
|
||||||
{
|
|
||||||
case IRP_MJ_READ:
|
|
||||||
*Size = stack->Parameters.Read.Length;
|
|
||||||
ubuffer = &file_ctx->ReadBuffer;
|
|
||||||
break;
|
|
||||||
case IRP_MJ_WRITE:
|
|
||||||
*Size = stack->Parameters.Write.Length;
|
|
||||||
ubuffer = &file_ctx->WriteBuffer;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
if (*Size > ubuffer->Size)
|
|
||||||
return STATUS_INVALID_USER_BUFFER;
|
|
||||||
ASSERT(ubuffer->KernelAddress != NULL);
|
|
||||||
*buffer = ubuffer->KernelAddress;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
@ -300,9 +271,9 @@ TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress,
|
|||||||
VOID *current_uaddr = InterlockedGetPointer(&MappedBuffer->UserAddress);
|
VOID *current_uaddr = InterlockedGetPointer(&MappedBuffer->UserAddress);
|
||||||
if (current_uaddr)
|
if (current_uaddr)
|
||||||
{
|
{
|
||||||
if (UserAddress == current_uaddr) // TODO: Check ThreadID
|
if (UserAddress != current_uaddr || Size > MappedBuffer->Size) // TODO: Check ThreadID
|
||||||
return STATUS_SUCCESS;
|
return STATUS_ALREADY_INITIALIZED;
|
||||||
return STATUS_ALREADY_INITIALIZED;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
@ -312,7 +283,7 @@ TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress,
|
|||||||
current_uaddr = InterlockedGetPointer(&MappedBuffer->UserAddress);
|
current_uaddr = InterlockedGetPointer(&MappedBuffer->UserAddress);
|
||||||
if (current_uaddr)
|
if (current_uaddr)
|
||||||
{
|
{
|
||||||
if (UserAddress != current_uaddr) // TODO: Check ThreadID
|
if (UserAddress != current_uaddr || Size > MappedBuffer->Size) // TODO: Check ThreadID
|
||||||
status = STATUS_ALREADY_INITIALIZED;
|
status = STATUS_ALREADY_INITIALIZED;
|
||||||
goto err_releasemutex;
|
goto err_releasemutex;
|
||||||
}
|
}
|
||||||
@ -398,22 +369,13 @@ _Must_inspect_result_
|
|||||||
static _Return_type_success_(
|
static _Return_type_success_(
|
||||||
return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *Ctx, _Out_ UCHAR **Buffer, _Out_ ULONG *Size)
|
return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *Ctx, _Out_ UCHAR **Buffer, _Out_ ULONG *Size)
|
||||||
{
|
{
|
||||||
IRP *irp;
|
IRP *irp = IoCsqRemoveNextIrp(&Ctx->Device.ReadQueue.Csq, NULL);
|
||||||
|
|
||||||
retry:
|
|
||||||
irp = IoCsqRemoveNextIrp(&Ctx->Device.ReadQueue.Csq, NULL);
|
|
||||||
if (!irp)
|
if (!irp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
|
||||||
NTSTATUS status = TunGetIrpBuffer(irp, Buffer, Size);
|
*Size = stack->Parameters.Read.Length;
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
TunCompleteRequest(Ctx, irp, status, IO_NO_INCREMENT);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(irp->IoStatus.Information <= (ULONG_PTR)*Size);
|
ASSERT(irp->IoStatus.Information <= (ULONG_PTR)*Size);
|
||||||
|
*Buffer = ((TUN_FILE_CTX *)stack->FileObject->FsContext)->ReadBuffer.KernelAddress;
|
||||||
return irp;
|
return irp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,12 +769,11 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT))
|
if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT))
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
|
|
||||||
UCHAR *buffer;
|
|
||||||
ULONG size;
|
|
||||||
if (!NT_SUCCESS(status = TunGetIrpBuffer(Irp, &buffer, &size)))
|
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
MDL *mdl = ((TUN_FILE_CTX *)stack->FileObject->FsContext)->WriteBuffer.Mdl;
|
TUN_MAPPED_UBUFFER *ubuffer = &((TUN_FILE_CTX *)stack->FileObject->FsContext)->WriteBuffer;
|
||||||
|
UCHAR *buffer = ubuffer->KernelAddress;
|
||||||
|
ULONG size = stack->Parameters.Write.Length;
|
||||||
|
|
||||||
const UCHAR *b = buffer, *b_end = buffer + size;
|
const UCHAR *b = buffer, *b_end = buffer + size;
|
||||||
typedef enum _ethtypeidx_t
|
typedef enum _ethtypeidx_t
|
||||||
{
|
{
|
||||||
@ -868,7 +829,7 @@ TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NET_BUFFER_LIST *nbl =
|
NET_BUFFER_LIST *nbl =
|
||||||
NdisAllocateNetBufferAndNetBufferList(Ctx->NBLPool, 0, 0, mdl, (ULONG)(p->Data - buffer), p->Size);
|
NdisAllocateNetBufferAndNetBufferList(Ctx->NBLPool, 0, 0, ubuffer->Mdl, (ULONG)(p->Data - buffer), p->Size);
|
||||||
if (!nbl)
|
if (!nbl)
|
||||||
{
|
{
|
||||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
Loading…
Reference in New Issue
Block a user