[ros-diffs] [cgutman] 54169: [TCPIP] - Do not transmit fragments recursively since it can cause a kernel stack overflow with large packets - Big thanks to hto for his work on this bug which has eluded me since...

cgutman at svn.reactos.org cgutman at svn.reactos.org
Mon Oct 17 00:38:47 UTC 2011


Author: cgutman
Date: Mon Oct 17 00:38:46 2011
New Revision: 54169

URL: http://svn.reactos.org/svn/reactos?rev=54169&view=rev
Log:
[TCPIP]
- Do not transmit fragments recursively since it can cause a kernel stack overflow with large packets
- Big thanks to hto for his work on this bug which has eluded me since last year
See issue #5796 for more details.

Modified:
    trunk/reactos/drivers/network/tcpip/include/transmit.h
    trunk/reactos/lib/drivers/ip/network/transmit.c

Modified: trunk/reactos/drivers/network/tcpip/include/transmit.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/transmit.h?rev=54169&r1=54168&r2=54169&view=diff
==============================================================================
--- trunk/reactos/drivers/network/tcpip/include/transmit.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/tcpip/include/transmit.h [iso-8859-1] Mon Oct 17 00:38:46 2011
@@ -25,8 +25,8 @@
     UINT BytesLeft;                     /* Number of bytes left to send */
     UINT PathMTU;                       /* Path Maximum Transmission Unit */
     PNEIGHBOR_CACHE_ENTRY NCE;          /* Pointer to NCE to use */
-    PIP_TRANSMIT_COMPLETE Complete;     /* Completion Routine */
-    PVOID Context;                      /* Completion Context */
+    KEVENT Event;                       /* Signalled when the transmission is complete */
+    NDIS_STATUS Status;                 /* Status of the transmission */
 } IPFRAGMENT_CONTEXT, *PIPFRAGMENT_CONTEXT;
 
 

Modified: trunk/reactos/lib/drivers/ip/network/transmit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/transmit.c?rev=54169&r1=54168&r2=54169&view=diff
==============================================================================
--- trunk/reactos/lib/drivers/ip/network/transmit.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/ip/network/transmit.c [iso-8859-1] Mon Oct 17 00:38:46 2011
@@ -28,30 +28,14 @@
  */
 {
     PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)Context;
-    NTSTATUS Status;
 
     TI_DbgPrint
 	(MAX_TRACE,
 	 ("Called. Context (0x%X)  NdisPacket (0x%X)  NdisStatus (0x%X)\n",
 	  Context, NdisPacket, NdisStatus));
-
-    if (NT_SUCCESS(NdisStatus) && PrepareNextFragment(IFC)) {
-	    /* A fragment was prepared for transmission, so send it */
-	    Status = IPSendFragment(IFC->NdisPacket, IFC->NCE, IFC);
-        if (!NT_SUCCESS(Status))
-        {
-            FreeNdisPacket(IFC->NdisPacket);
-            IFC->Complete(IFC->Context, IFC->Datagram, Status);
-            ExFreePoolWithTag(IFC, IFC_TAG);
-        }
-    } else {
-	TI_DbgPrint(MAX_TRACE, ("Calling completion handler.\n"));
-
-	/* There are no more fragments to transmit, so call completion handler */
-	FreeNdisPacket(IFC->NdisPacket);
-	IFC->Complete(IFC->Context, IFC->Datagram, NdisStatus);
-	ExFreePoolWithTag(IFC, IFC_TAG);
-    }
+	  
+	IFC->Status = NdisStatus;
+	KeSetEvent(&IFC->Event, 0, FALSE);
 }
 
 NTSTATUS IPSendFragment(
@@ -202,8 +186,7 @@
     IFC->Position     = 0;
     IFC->BytesLeft    = IPPacket->TotalSize - IPPacket->HeaderSize;
     IFC->Data         = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize);
-    IFC->Complete     = Complete;
-    IFC->Context      = Context;
+    KeInitializeEvent(&IFC->Event, NotificationEvent, FALSE);
 
     TI_DbgPrint(MID_TRACE,("Copying header from %x to %x (%d)\n",
 			   IPPacket->Header, IFC->Header,
@@ -211,19 +194,27 @@
 
     RtlCopyMemory( IFC->Header, IPPacket->Header, IPPacket->HeaderSize );
 
-    /* Prepare next fragment for transmission and send it */
-
-    if (!PrepareNextFragment(IFC)) {
-        FreeNdisPacket(IFC->NdisPacket);
-        ExFreePoolWithTag(IFC, IFC_TAG);
-        return NDIS_STATUS_FAILURE;
+    while (PrepareNextFragment(IFC))
+    {
+        NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC);
+        if (NT_SUCCESS(NdisStatus))
+        {
+            KeWaitForSingleObject(&IFC->Event,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL);
+            NdisStatus = IFC->Status;
+        }
+
+        if (!NT_SUCCESS(NdisStatus))
+            break;
     }
 
-    if (!NT_SUCCESS((NdisStatus = IPSendFragment(IFC->NdisPacket, NCE, IFC))))
-    {
-        FreeNdisPacket(IFC->NdisPacket);
-        ExFreePoolWithTag(IFC, IFC_TAG);
-    }
+    FreeNdisPacket(IFC->NdisPacket);
+    ExFreePoolWithTag(IFC, IFC_TAG);
+
+    Complete(Context, IPPacket->NdisPacket, NdisStatus);
 
     return NdisStatus;
 }




More information about the Ros-diffs mailing list