- Fix a race condition that occurs when an IRP gets cancelled after it is inserted...
authorCameron Gutman <aicommander@gmail.com>
Sun, 22 Nov 2009 02:32:47 +0000 (02:32 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sun, 22 Nov 2009 02:32:47 +0000 (02:32 +0000)
svn path=/trunk/; revision=44267

reactos/drivers/network/tcpip/include/datagram.h
reactos/drivers/network/tcpip/include/tcp.h
reactos/drivers/network/tcpip/tcpip/dispatch.c
reactos/lib/drivers/ip/transport/datagram/datagram.c
reactos/lib/drivers/ip/transport/tcp/accept.c
reactos/lib/drivers/ip/transport/tcp/tcp.c

index 760ba3a..f05107a 100644 (file)
@@ -21,7 +21,7 @@ NTSTATUS DGReceiveDatagram(
     PVOID Context,
     PIRP Irp);
 
-VOID DGRemoveIRP(
+BOOLEAN DGRemoveIRP(
     PADDRESS_FILE AddrFile,
     PIRP Irp);
 
index b18fecd..a02c03b 100644 (file)
@@ -96,8 +96,8 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
                                    PCONNECTION_ENDPOINT Connection,
                                    PTDI_REQUEST_KERNEL Request );
 NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog );
-VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
-                             PCONNECTION_ENDPOINT Connection );
+BOOLEAN TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
+                                PCONNECTION_ENDPOINT Connection );
 NTSTATUS TCPAccept
 ( PTDI_REQUEST Request,
   PCONNECTION_ENDPOINT Listener,
@@ -179,6 +179,6 @@ NTSTATUS TCPStartup(
 NTSTATUS TCPShutdown(
   VOID);
 
-VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
+BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
 
 #endif /* __TCP_H */
index c78aece..c6f2d2a 100644 (file)
@@ -133,6 +133,7 @@ VOID NTAPI DispCancelRequest(
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     UCHAR MinorFunction;
+    BOOLEAN DequeuedIrp = TRUE;
 
     IoReleaseCancelSpinLock(Irp->CancelIrql);
 
@@ -157,7 +158,7 @@ VOID NTAPI DispCancelRequest(
     switch(MinorFunction) {
     case TDI_SEND:
     case TDI_RECEIVE:
-       TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
+       DequeuedIrp = TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
         break;
 
     case TDI_SEND_DATAGRAM:
@@ -166,7 +167,7 @@ VOID NTAPI DispCancelRequest(
             break;
         }
 
-        DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
+        DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
         break;
 
     case TDI_RECEIVE_DATAGRAM:
@@ -175,19 +176,21 @@ VOID NTAPI DispCancelRequest(
             break;
         }
 
-        DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
+        DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
         break;
 
     case TDI_CONNECT:
-        TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
+        DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
         break;
 
     default:
         TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
+        ASSERT(FALSE);
         break;
     }
 
-    IRPFinish(Irp, STATUS_CANCELLED);
+    if (DequeuedIrp)
+       IRPFinish(Irp, STATUS_CANCELLED);
 
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
@@ -207,7 +210,6 @@ VOID NTAPI DispCancelListenRequest(
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     PCONNECTION_ENDPOINT Connection;
-    /*NTSTATUS Status = STATUS_SUCCESS;*/
 
     IoReleaseCancelSpinLock(Irp->CancelIrql);
 
@@ -228,13 +230,12 @@ VOID NTAPI DispCancelListenRequest(
     /* Try canceling the request */
     Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
 
-    TCPRemoveIRP(Connection, Irp);
-
-    TCPAbortListenForSocket(Connection->AddressFile->Listener,
-                            Connection);
-
-    Irp->IoStatus.Information = 0;
-    IRPFinish(Irp, STATUS_CANCELLED);
+    if (TCPAbortListenForSocket(Connection->AddressFile->Listener,
+                                Connection))
+    {
+        Irp->IoStatus.Information = 0;
+        IRPFinish(Irp, STATUS_CANCELLED);
+    }
 
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
index 14562e4..3c92aa2 100644 (file)
 
 #include "precomp.h"
 
-VOID DGRemoveIRP(
+BOOLEAN DGRemoveIRP(
     PADDRESS_FILE AddrFile,
     PIRP Irp)
 {
     PLIST_ENTRY ListEntry;
     PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
     KIRQL OldIrql;
+    BOOLEAN Found = FALSE;
 
     TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
                             Irp, AddrFile));
@@ -36,6 +37,7 @@ VOID DGRemoveIRP(
         {
             RemoveEntryList(&ReceiveRequest->ListEntry);
             ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
+            Found = TRUE;
             break;
         }
     }
@@ -43,6 +45,8 @@ VOID DGRemoveIRP(
     KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
 
     TI_DbgPrint(MAX_TRACE, ("Done.\n"));
+
+    return Found;
 }
 
 VOID DGDeliverData(
index 0bdefb3..059d109 100644 (file)
@@ -104,11 +104,12 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
     return Status;
 }
 
-VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
+BOOLEAN TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
                   PCONNECTION_ENDPOINT Connection ) {
     PLIST_ENTRY ListEntry;
     PTDI_BUCKET Bucket;
     KIRQL OldIrql;
+    BOOLEAN Found = FALSE;
 
     KeAcquireSpinLock(&Listener->Lock, &OldIrql);
 
@@ -119,6 +120,7 @@ VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
     if( Bucket->AssociatedEndpoint == Connection ) {
         RemoveEntryList( &Bucket->Entry );
         ExFreePoolWithTag( Bucket, TDI_BUCKET_TAG );
+        Found = TRUE;
         break;
     }
 
@@ -126,6 +128,8 @@ VOID TCPAbortListenForSocket( PCONNECTION_ENDPOINT Listener,
     }
 
     KeReleaseSpinLock(&Listener->Lock, OldIrql);
+
+    return Found;
 }
 
 NTSTATUS TCPAccept ( PTDI_REQUEST Request,
index f0e104e..8c05167 100644 (file)
@@ -904,12 +904,13 @@ NTSTATUS TCPGetSockAddress
     return Status;
 }
 
-VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
+BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
     PLIST_ENTRY Entry;
     PLIST_ENTRY ListHead[4];
     KIRQL OldIrql;
     PTDI_BUCKET Bucket;
     UINT i = 0;
+    BOOLEAN Found = FALSE;
 
     ListHead[0] = &Endpoint->SendRequest;
     ListHead[1] = &Endpoint->ReceiveRequest;
@@ -929,12 +930,15 @@ VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
             {
                 RemoveEntryList( &Bucket->Entry );
                 ExFreePoolWithTag( Bucket, TDI_BUCKET_TAG );
+                Found = TRUE;
                 break;
             }
         }
     }
 
     TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql );
+
+    return Found;
 }
 
 /* EOF */