Use explicit running boolean and use set instead of exchange
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									999a6744db
								
							
						
					
					
						commit
						18cfd522aa
					
				
							
								
								
									
										55
									
								
								wintun.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								wintun.c
									
									
									
									
									
								
							| @ -106,14 +106,9 @@ typedef struct _TUN_REGISTER_RINGS | ||||
| /* 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 | ||||
| { | ||||
|     TUN_FLAGS_RUNNING = 1 << 0, /* Toggles between paused and running state */ | ||||
| } TUN_FLAGS; | ||||
| 
 | ||||
| typedef struct _TUN_CTX | ||||
| { | ||||
|     volatile LONG Flags; | ||||
|     volatile LONG Running; | ||||
| 
 | ||||
|     /* Used like RCU. When we're making use of rings, we take a shared lock. When we want to register or release the
 | ||||
|      * rings and toggle the state, we take an exclusive lock before toggling the atomic and then releasing. It's similar | ||||
| @ -168,10 +163,22 @@ static DRIVER_DISPATCH *NdisDispatchDeviceControl, *NdisDispatchClose; | ||||
| static ERESOURCE TunDispatchCtxGuard; | ||||
| static SECURITY_DESCRIPTOR *TunDispatchSecurityDescriptor; | ||||
| 
 | ||||
| static __forceinline ULONG | ||||
| InterlockedExchangeU(_Inout_ _Interlocked_operand_ ULONG volatile *Target, _In_ ULONG Value) | ||||
| static __forceinline VOID | ||||
| InterlockedSet(_Inout_ _Interlocked_operand_ LONG volatile *Target, _In_ LONG Value) | ||||
| { | ||||
|     return (ULONG)InterlockedExchange((LONG volatile *)Target, Value); | ||||
|     *Target = Value; | ||||
| } | ||||
| 
 | ||||
| static __forceinline VOID | ||||
| InterlockedSetU(_Inout_ _Interlocked_operand_ ULONG volatile *Target, _In_ ULONG Value) | ||||
| { | ||||
|     *Target = Value; | ||||
| } | ||||
| 
 | ||||
| static __forceinline VOID | ||||
| InterlockedSetPointer(_Inout_ _Interlocked_operand_ VOID * volatile *Target, _In_opt_ VOID *Value) | ||||
| { | ||||
|     *Target = Value; | ||||
| } | ||||
| 
 | ||||
| static __forceinline LONG | ||||
| @ -286,7 +293,7 @@ TunSendNetBufferLists( | ||||
| 
 | ||||
|         KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock); | ||||
|         NDIS_STATUS Status; | ||||
|         if ((Status = NDIS_STATUS_PAUSED, !(InterlockedGet(&Ctx->Flags) & TUN_FLAGS_RUNNING)) || | ||||
|         if ((Status = NDIS_STATUS_PAUSED, !InterlockedGet(&Ctx->Running)) || | ||||
|             (Status = NDIS_STATUS_MEDIA_DISCONNECTED, KeReadStateEvent(&Ctx->Device.Disconnected))) | ||||
|             goto skipNbl; | ||||
| 
 | ||||
| @ -357,7 +364,7 @@ TunSendNetBufferLists( | ||||
|         { | ||||
|             NET_BUFFER_LIST *CompletedNbl = Ctx->Device.Send.ActiveNbls.Head; | ||||
|             Ctx->Device.Send.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL(CompletedNbl); | ||||
|             InterlockedExchangeU(&Ring->Tail, TunNblGetOffset(CompletedNbl)); | ||||
|             InterlockedSetU(&Ring->Tail, TunNblGetOffset(CompletedNbl)); | ||||
|             KeSetEvent(Ctx->Device.Send.TailMoved, IO_NETWORK_INCREMENT, FALSE); | ||||
|             NET_BUFFER_LIST_NEXT_NBL(CompletedNbl) = NULL; | ||||
|             NdisMSendNetBufferListsComplete( | ||||
| @ -440,7 +447,7 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net | ||||
|             } | ||||
|             Ctx->Device.Receive.ActiveNbls.Head = NET_BUFFER_LIST_NEXT_NBL_EX(CompletedNbl); | ||||
|             KeReleaseInStackQueuedSpinLock(&LockHandle); | ||||
|             InterlockedExchangeU(&Ring->Head, TunNblGetOffset(CompletedNbl)); | ||||
|             InterlockedSetU(&Ring->Head, TunNblGetOffset(CompletedNbl)); | ||||
|             NdisFreeNetBufferList(CompletedNbl); | ||||
|         } | ||||
| 
 | ||||
| @ -496,16 +503,16 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) | ||||
|             } | ||||
|             if (RingHead == RingTail) | ||||
|             { | ||||
|                 InterlockedExchange(&Ring->Alertable, TRUE); | ||||
|                 InterlockedSet(&Ring->Alertable, TRUE); | ||||
|                 RingTail = InterlockedGetU(&Ring->Tail); | ||||
|                 if (RingHead == RingTail) | ||||
|                 { | ||||
|                     KeWaitForMultipleObjects( | ||||
|                         RTL_NUMBER_OF(Events), Events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); | ||||
|                     InterlockedExchange(&Ring->Alertable, FALSE); | ||||
|                     InterlockedSet(&Ring->Alertable, FALSE); | ||||
|                     continue; | ||||
|                 } | ||||
|                 InterlockedExchange(&Ring->Alertable, FALSE); | ||||
|                 InterlockedSet(&Ring->Alertable, FALSE); | ||||
|                 KeClearEvent(Ctx->Device.Receive.TailMoved); | ||||
|             } | ||||
|         } | ||||
| @ -563,7 +570,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) | ||||
|         KeReleaseInStackQueuedSpinLock(&LockHandle); | ||||
| 
 | ||||
|         KIRQL Irql = ExAcquireSpinLockShared(&Ctx->TransitionLock); | ||||
|         if (!(InterlockedGet(&Ctx->Flags) & TUN_FLAGS_RUNNING)) | ||||
|         if (!InterlockedGet(&Ctx->Running)) | ||||
|             goto skipNbl; | ||||
| 
 | ||||
|         if (!NT_SUCCESS(IoAcquireRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, Nbl))) | ||||
| @ -590,7 +597,7 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx) | ||||
|     if (NT_SUCCESS(IoAcquireRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL))) | ||||
|         IoReleaseRemoveLockAndWait(&Ctx->Device.Receive.ActiveNbls.RemoveLock, NULL); | ||||
| cleanup: | ||||
|     InterlockedExchangeU(&Ring->Head, MAXULONG); | ||||
|     InterlockedSetU(&Ring->Head, MAXULONG); | ||||
| } | ||||
| 
 | ||||
| #define IS_POW2(x) ((x) && !((x) & ((x)-1))) | ||||
| @ -606,7 +613,7 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp) | ||||
|     if (InterlockedCompareExchangePointer(&Ctx->Device.Owner, Stack->FileObject, NULL) != NULL) | ||||
|         return STATUS_ALREADY_INITIALIZED; | ||||
| 
 | ||||
|     ASSERT(InterlockedGet(&Ctx->Flags) & TUN_FLAGS_RUNNING); | ||||
|     ASSERT(InterlockedGet(&Ctx->Running)); | ||||
| 
 | ||||
|     TUN_REGISTER_RINGS *Rrb = Irp->AssociatedIrp.SystemBuffer; | ||||
|     if (Status = STATUS_INVALID_PARAMETER, Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(*Rrb)) | ||||
| @ -712,7 +719,7 @@ cleanupSendMdl: | ||||
| cleanupSendTailMoved: | ||||
|     ObDereferenceObject(Ctx->Device.Send.TailMoved); | ||||
| cleanupResetOwner: | ||||
|     InterlockedExchangePointer(&Ctx->Device.Owner, NULL); | ||||
|     InterlockedSetPointer(&Ctx->Device.Owner, NULL); | ||||
|     return Status; | ||||
| } | ||||
| 
 | ||||
| @ -739,7 +746,7 @@ TunUnregisterBuffers(_Inout_ TUN_CTX *Ctx, _In_ FILE_OBJECT *Owner) | ||||
|     } | ||||
|     ZwClose(Ctx->Device.Receive.Thread); | ||||
| 
 | ||||
|     InterlockedExchangeU(&Ctx->Device.Send.Ring->Tail, MAXULONG); | ||||
|     InterlockedSetU(&Ctx->Device.Send.Ring->Tail, MAXULONG); | ||||
|     KeSetEvent(Ctx->Device.Send.TailMoved, IO_NO_INCREMENT, FALSE); | ||||
| 
 | ||||
|     MmUnlockPages(Ctx->Device.Receive.Mdl); | ||||
| @ -923,7 +930,7 @@ TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS | ||||
| { | ||||
|     TUN_CTX *Ctx = (TUN_CTX *)MiniportAdapterContext; | ||||
|     IoInitializeRemoveLock(&Ctx->Device.Receive.ActiveNbls.RemoveLock, TUN_MEMORY_TAG, 0, 0); | ||||
|     InterlockedOr(&Ctx->Flags, TUN_FLAGS_RUNNING); | ||||
|     InterlockedSet(&Ctx->Running, TRUE); | ||||
|     return NDIS_STATUS_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| @ -934,7 +941,7 @@ TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS Min | ||||
| { | ||||
|     TUN_CTX *Ctx = (TUN_CTX *)MiniportAdapterContext; | ||||
| 
 | ||||
|     InterlockedAnd(&Ctx->Flags, ~TUN_FLAGS_RUNNING); | ||||
|     InterlockedSet(&Ctx->Running, FALSE); | ||||
|     ExReleaseSpinLockExclusive( | ||||
|         &Ctx->TransitionLock, | ||||
|         ExAcquireSpinLockExclusive(&Ctx->TransitionLock)); /* Ensure above change is visible to all readers. */ | ||||
| @ -1123,9 +1130,9 @@ TunHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction) | ||||
|         ExAcquireSpinLockExclusive(&Ctx->TransitionLock)); /* Ensure above change is visible to all readers. */ | ||||
|     NdisFreeNetBufferListPool(Ctx->NblPool); | ||||
| 
 | ||||
|     InterlockedExchangePointer(&Ctx->MiniportAdapterHandle, NULL); | ||||
|     InterlockedSetPointer(&Ctx->MiniportAdapterHandle, NULL); | ||||
| #pragma warning(suppress : 28175) | ||||
|     InterlockedExchangePointer(&Ctx->FunctionalDeviceObject->Reserved, NULL); | ||||
|     InterlockedSetPointer(&Ctx->FunctionalDeviceObject->Reserved, NULL); | ||||
|     ExAcquireResourceExclusiveLite(&TunDispatchCtxGuard, TRUE); /* Ensure above change is visible to all readers. */ | ||||
|     ExReleaseResourceLite(&TunDispatchCtxGuard); | ||||
|     ExFreePoolWithTag(Ctx, TUN_MEMORY_TAG); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user