aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-12-15 21:10:39 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-12-15 21:13:06 +0100
commitb2374dadb6cbd8c9c745041f5c3665cf4d270dff (patch)
tree8aa48e02c0d7bc9d5335628b64e644f6bf180a97
parentdriver: use partial MDL for slicing ring, rather than NB's DataOffset (diff)
downloadwintun-b2374dadb6cbd8c9c745041f5c3665cf4d270dff.tar.xz
wintun-b2374dadb6cbd8c9c745041f5c3665cf4d270dff.zip
driver: use IoAllocateMdl without being too clever
Windows 7 doesn't like our trick of sticking MDLs into the NBL context area. So we do things more traditionally, by allocating an MDL with IoAllocateMdl and freeing it with IoFreeMdl. This means that we have to keep track of the MDL between allocation and free time, and we don't have any more miniport reserved pointers left in the NBL. So instead we walk the MdlChain field of the first NB, and free the one that has an address living inside of the non-partial MDL. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--driver/wintun.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/driver/wintun.c b/driver/wintun.c
index a762dcb..b833663 100644
--- a/driver/wintun.c
+++ b/driver/wintun.c
@@ -412,6 +412,16 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net
KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE);
KeReleaseInStackQueuedSpinLock(&LockHandle);
WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl));
+ const MDL *TargetMdl = Ctx->Device.Receive.Mdl;
+ for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next)
+ {
+ if (MmGetMdlVirtualAddress(Mdl) < MmGetMdlVirtualAddress(TargetMdl) ||
+ (UCHAR *)MmGetMdlVirtualAddress(Mdl) + MmGetMdlByteCount(Mdl) >
+ (UCHAR *)MmGetMdlVirtualAddress(TargetMdl) + MmGetMdlByteCount(TargetMdl))
+ continue;
+ IoFreeMdl(Mdl);
+ break;
+ }
NdisFreeNetBufferList(CompletedNbl);
}
}
@@ -507,20 +517,17 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
break;
RingHead = TUN_RING_WRAP(RingHead + AlignedPacketSize, RingCapacity);
- MDL *Mdl;
- NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, sizeof(*Mdl), 0, NULL, 0, 0);
- if (!Nbl)
+ MDL *Mdl = IoAllocateMdl(NULL, PacketSize, FALSE, FALSE, NULL);
+ if (!Mdl)
goto skipNbl;
- Mdl = (MDL *)NET_BUFFER_LIST_CONTEXT_DATA_START(Nbl);
IoBuildPartialMdl(
Ctx->Device.Receive.Mdl,
Mdl,
(UCHAR *)MmGetMdlVirtualAddress(Ctx->Device.Receive.Mdl) + (ULONG)(Packet->Data - (UCHAR *)Ring),
PacketSize);
- NET_BUFFER *Nb = NET_BUFFER_LIST_FIRST_NB(Nbl);
- NET_BUFFER_FIRST_MDL(Nb) = NET_BUFFER_CURRENT_MDL(Nb) = Mdl;
- NET_BUFFER_DATA_LENGTH(Nb) = PacketSize;
- NET_BUFFER_DATA_OFFSET(Nb) = NET_BUFFER_CURRENT_MDL_OFFSET(Nb) = 0;
+ NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, 0, 0, Mdl, 0, PacketSize);
+ if (!Nbl)
+ goto cleanupMdl;
Nbl->SourceHandle = Ctx->MiniportAdapterHandle;
NdisSetNblFlag(Nbl, NblFlags);
NET_BUFFER_LIST_INFO(Nbl, NetBufferListFrameType) = (PVOID)NblProto;
@@ -556,6 +563,8 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
cleanupNbl:
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
NdisFreeNetBufferList(Nbl);
+ cleanupMdl:
+ IoFreeMdl(Mdl);
skipNbl:
InterlockedIncrementNoFence64((LONG64 *)&Ctx->Statistics.ifInDiscards);
KeWaitForSingleObject(&Ctx->Device.Receive.ActiveNbls.Empty, Executive, KernelMode, FALSE, NULL);