|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH] Fix multiple completion vulnerability in transmit code
My previous patch 7c3365d5 "Make transmitter robust against a possible
completion race" did not fix the problem. There is still the possibility
that a NET_BUFFER_LIST containing multiple NET_BUFFERs could lead to
multiple completions if the underlying transmit completes quickly (or indeed
synchrnously). This is because a reference is taken before sending each
NET_BUFFER but, if that transmission completes immediately the reference is
dropped back to zero (leading to the NET_BUFFER_LIST being completed) before
the reference is taken for the next NET_BUFFER.
This patch therefore takes an extra reference before sending any NET_BUFFERs
and then drops it when there are no more NET_BUFFERs to send. This ensures
that the reference count on the NET_BUFFER_LIST can only fall to zero once
the whole thing has been processed.
Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
src/xennet/transmitter.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 91ed5f2..eaf5267 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -90,6 +90,7 @@ TransmitterTeardown(
typedef struct _NET_BUFFER_LIST_RESERVED {
LONG Reference;
+ LONG Status;
} NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST,
MiniportReserved));
@@ -120,6 +121,39 @@ __TransmitterCompleteNetBufferList(
NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
}
+__TransmitterGetNetBufferList(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PNET_BUFFER_LIST NetBufferList
+ )
+{
+ PNET_BUFFER_LIST_RESERVED ListReserved;
+
+ UNREFERENCED_PARAMETER(Transmitter);
+
+ ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+
+ if (InterlockedIncrement(&ListReserved->Reference) == 1)
+ ListReserved->Status = NDIS_STATUS_PENDING;
+}
+
+__TransmitterPutNetBufferList(
+ IN PXENNET_TRANSMITTER Transmitter,
+ IN PNET_BUFFER_LIST NetBufferList
+ )
+{
+ PNET_BUFFER_LIST_RESERVED ListReserved;
+
+ UNREFERENCED_PARAMETER(Transmitter);
+
+ ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+
+ ASSERT(ListReserved->Reference != 0);
+ if (InterlockedDecrement(&ListReserved->Reference) == 0)
+ __TransmitterCompleteNetBufferList(Transmitter,
+ NetBufferList,
+ ListReserved->Status);
+}
+
static VOID
__TransmitterReturnPacket(
IN PXENNET_TRANSMITTER Transmitter,
@@ -134,9 +168,8 @@ __TransmitterReturnPacket(
ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
- ASSERT(ListReserved->Reference != 0);
- if (InterlockedDecrement(&ListReserved->Reference) == 0)
- __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
+ (VOID) InterlockedExchange(&ListReserved->Status, Status);
+ __TransmitterPutNetBufferList(Transmitter, NetBufferList);
}
static VOID
@@ -248,6 +281,8 @@ TransmitterSendNetBufferLists(
ListReserved =
(PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+ __TransmitterGetNetBufferList(Transmitter, NetBufferList);
+
NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
while (NetBuffer != NULL) {
PNET_BUFFER NetBufferListNext =
NET_BUFFER_NEXT_NB(NetBuffer);
@@ -255,7 +290,7 @@ TransmitterSendNetBufferLists(
XENVIF_PACKET_HASH Hash;
NTSTATUS status;
- InterlockedIncrement(&ListReserved->Reference);
+ __TransmitterGetNetBufferList(Transmitter, NetBufferList);
Hash.Algorithm = XENVIF_PACKET_HASH_ALGORITHM_NONE;
@@ -278,6 +313,8 @@ TransmitterSendNetBufferLists(
NetBuffer = NetBufferListNext;
}
+ __TransmitterPutNetBufferList(Transmitter, NetBufferList);
+
NetBufferList = ListNext;
}
--
2.1.1
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |