]> xenbits.xensource.com Git - pvdrivers/win/xennet.git/commitdiff
Fix low resources packet leak
authorPaul Durrant <paul.durrant@citrix.com>
Wed, 8 Feb 2017 10:47:06 +0000 (10:47 +0000)
committerPaul Durrant <paul.durrant@citrix.com>
Thu, 9 Feb 2017 16:47:39 +0000 (16:47 +0000)
When the low resources limit is hit then the NDIS_RECEIVE_FLAGS_RESOURCES
is passed to NdisMIndicateReceiveNetBufferLists(), which means that the
calling code can assume the NET_BUFFER_LIST is immediately released.
The code therefore attempts to immediately release the chain of
NET_BUFFER_LIST, but because __IndicateReceiveNetBufferLists() segmented
the chain, only the first one is actually released. This leads to a
resource leak which also prevents XENVIF from shutting down correctly
(waiting for the leaked packets to be returned).

This patch fixes the issue by handling the release of individual
NET_BUFFER_LISTs directly in __IndicateReceiveNetBufferLists(), if the
NDIS_RECEIVE_FLAGS_RESOURCES is set.

Reported-by: Martin Cerveny <martin@c-home.cz>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Tested-by: Martin Cerveny <martin@c-home.cz>
src/xennet/receiver.c

index 1e6775e195321b8447edec03a39cfa8320ba2167..2f7ea25bba4f2c325ff5460cace02e1ed2c0fe20 100644 (file)
@@ -328,15 +328,20 @@ fail1:
 }
 
 static FORCEINLINE VOID __IndicateReceiveNetBufferLists(
-    IN  NDIS_HANDLE         MiniportAdapterHandle,
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferLists,
     IN  NDIS_PORT_NUMBER    PortNumber,
     IN  ULONG               NumberOfNetBufferLists,
     IN  ULONG               ReceiveFlags
     )
 {
+    PXENNET_ADAPTER         Adapter = Receiver->Adapter;
+    NDIS_HANDLE             MiniportAdapterHandle = AdapterGetHandle(Adapter);
+    PXENVIF_VIF_INTERFACE   VifInterface;
     ULONG                   Count;
 
+    VifInterface = AdapterGetVifInterface(Receiver->Adapter);
+
     Count = 0;
     while (NetBufferLists != NULL) {
         PNET_BUFFER_LIST        Next;
@@ -350,6 +355,20 @@ static FORCEINLINE VOID __IndicateReceiveNetBufferLists(
                                            1,
                                            ReceiveFlags);
 
+        if (ReceiveFlags & NDIS_RECEIVE_FLAGS_RESOURCES) {
+            PVOID   Cookie;
+
+            Cookie = __ReceiverReleaseNetBufferList(Receiver,
+                                                    NetBufferLists,
+                                                    FALSE);
+
+            XENVIF_VIF(ReceiverReturnPacket,
+                       VifInterface,
+                       Cookie);
+
+            (VOID) InterlockedIncrement(&Receiver->Returned);
+        }
+
         Count++;
         NetBufferLists = Next;
     }
@@ -396,14 +415,11 @@ __ReceiverPushPackets(
     if (Indicated - Returned > IN_NDIS_MAX)
         Flags |= NDIS_RECEIVE_FLAGS_RESOURCES;
 
-    __IndicateReceiveNetBufferLists(AdapterGetHandle(Receiver->Adapter),
+    __IndicateReceiveNetBufferLists(Receiver,
                                     NetBufferList,
                                     NDIS_DEFAULT_PORT_NUMBER,
                                     Count,
                                     Flags);
-
-    if (Flags & NDIS_RECEIVE_FLAGS_RESOURCES)
-        (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
 }
 
 NDIS_STATUS