Do not call NdisMPauseComplete before TunPause returns

Otherwise we trigger a bugcheck on Server 2019.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2019-03-29 21:42:46 +01:00
parent 7b3ea2a8a9
commit bba0f6aecf

View File

@ -179,14 +179,15 @@ static NTSTATUS TunCheckForPause(_Inout_ TUN_CTX *ctx, _In_ LONG64 increment)
} }
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
static NDIS_STATUS TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ LONG64 decrement) static NDIS_STATUS TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ LONG64 decrement, _In_ BOOLEAN async_completion)
{ {
ASSERT(decrement <= InterlockedGet64(&ctx->ActiveTransactionCount)); ASSERT(decrement <= InterlockedGet64(&ctx->ActiveTransactionCount));
if (!InterlockedSubtract64(&ctx->ActiveTransactionCount, decrement) && if (!InterlockedSubtract64(&ctx->ActiveTransactionCount, decrement) &&
InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSED, TUN_STATE_PAUSING) == TUN_STATE_PAUSING) { InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSED, TUN_STATE_PAUSING) == TUN_STATE_PAUSING) {
InterlockedExchange64(&ctx->Device.RefCount, 0); InterlockedExchange64(&ctx->Device.RefCount, 0);
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
NdisMPauseComplete(ctx->MiniportAdapterHandle); if (async_completion)
NdisMPauseComplete(ctx->MiniportAdapterHandle);
return NDIS_STATUS_SUCCESS; return NDIS_STATUS_SUCCESS;
} }
@ -259,7 +260,7 @@ static VOID TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp)
{ {
TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq);
TunCompleteRequest(Irp, 0, STATUS_CANCELLED); TunCompleteRequest(Irp, 0, STATUS_CANCELLED);
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
} }
_IRQL_requires_same_ _IRQL_requires_same_
@ -334,7 +335,7 @@ retry:
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
irp->IoStatus.Status = status; irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NETWORK_INCREMENT); IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
goto retry; goto retry;
} }
@ -399,7 +400,7 @@ static BOOLEAN TunNBLRefDec(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl,
NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags); NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags);
InterlockedSubtract(&ctx->PacketQueue.NumNbl, 1); InterlockedSubtract(&ctx->PacketQueue.NumNbl, 1);
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -556,7 +557,7 @@ static void TunQueueProcess(_Inout_ TUN_CTX *ctx)
} else { } else {
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(irp, IO_NETWORK_INCREMENT); IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
irp = NULL; irp = NULL;
} }
@ -585,7 +586,7 @@ static NTSTATUS TunDispatchCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp)
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -611,7 +612,7 @@ static NTSTATUS TunDispatchClose(DEVICE_OBJECT *DeviceObject, IRP *Irp)
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -642,11 +643,11 @@ static NTSTATUS TunDispatchRead(DEVICE_OBJECT *DeviceObject, IRP *Irp)
TunQueueProcess(ctx); TunQueueProcess(ctx);
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
return STATUS_PENDING; return STATUS_PENDING;
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -777,7 +778,7 @@ static NTSTATUS TunDispatchWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp)
information = b - buffer; information = b - buffer;
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, information, status); TunCompleteRequest(Irp, information, status);
return status; return status;
@ -807,7 +808,7 @@ static NTSTATUS TunDispatchCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp)
} }
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, count); TunCompletePause(ctx, count, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -855,7 +856,7 @@ static NDIS_STATUS TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_P
TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED); TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED);
} }
return TunCompletePause(ctx, count); return TunCompletePause(ctx, count, FALSE);
} }
static MINIPORT_RESTART TunRestart; static MINIPORT_RESTART TunRestart;
@ -1373,7 +1374,7 @@ static void TunSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext, NET_BUFFER
TunQueueProcess(ctx); TunQueueProcess(ctx);
cleanup_TunCompletePause: cleanup_TunCompletePause:
TunCompletePause(ctx, 1); TunCompletePause(ctx, 1, TRUE);
} }
DRIVER_INITIALIZE DriverEntry; DRIVER_INITIALIZE DriverEntry;