From e016a230afb20abc112a79d29a0deae875d744fd Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 22 Nov 2009 02:32:47 +0000 Subject: [PATCH] - Fix a race condition that occurs when an IRP gets cancelled after it is inserted into the completion queue but before it is completed svn path=/trunk/; revision=44267 --- .../drivers/network/tcpip/include/datagram.h | 2 +- reactos/drivers/network/tcpip/include/tcp.h | 6 ++--- .../drivers/network/tcpip/tcpip/dispatch.c | 27 ++++++++++--------- .../drivers/ip/transport/datagram/datagram.c | 6 ++++- reactos/lib/drivers/ip/transport/tcp/accept.c | 6 ++++- reactos/lib/drivers/ip/transport/tcp/tcp.c | 6 ++++- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/reactos/drivers/network/tcpip/include/datagram.h b/reactos/drivers/network/tcpip/include/datagram.h index 760ba3a85be..f05107a7de1 100644 --- a/reactos/drivers/network/tcpip/include/datagram.h +++ b/reactos/drivers/network/tcpip/include/datagram.h @@ -21,7 +21,7 @@ NTSTATUS DGReceiveDatagram( PVOID Context, PIRP Irp); -VOID DGRemoveIRP( +BOOLEAN DGRemoveIRP( PADDRESS_FILE AddrFile, PIRP Irp); diff --git a/reactos/drivers/network/tcpip/include/tcp.h b/reactos/drivers/network/tcpip/include/tcp.h index b18fecdd295..a02c03b796e 100644 --- a/reactos/drivers/network/tcpip/include/tcp.h +++ b/reactos/drivers/network/tcpip/include/tcp.h @@ -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 */ diff --git a/reactos/drivers/network/tcpip/tcpip/dispatch.c b/reactos/drivers/network/tcpip/tcpip/dispatch.c index c78aeceb89f..c6f2d2a55e9 100644 --- a/reactos/drivers/network/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/network/tcpip/tcpip/dispatch.c @@ -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")); } diff --git a/reactos/lib/drivers/ip/transport/datagram/datagram.c b/reactos/lib/drivers/ip/transport/datagram/datagram.c index 14562e4ddbf..3c92aa26002 100644 --- a/reactos/lib/drivers/ip/transport/datagram/datagram.c +++ b/reactos/lib/drivers/ip/transport/datagram/datagram.c @@ -10,13 +10,14 @@ #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( diff --git a/reactos/lib/drivers/ip/transport/tcp/accept.c b/reactos/lib/drivers/ip/transport/tcp/accept.c index 0bdefb32ec0..059d109af73 100644 --- a/reactos/lib/drivers/ip/transport/tcp/accept.c +++ b/reactos/lib/drivers/ip/transport/tcp/accept.c @@ -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, diff --git a/reactos/lib/drivers/ip/transport/tcp/tcp.c b/reactos/lib/drivers/ip/transport/tcp/tcp.c index f0e104efe6d..8c051677353 100644 --- a/reactos/lib/drivers/ip/transport/tcp/tcp.c +++ b/reactos/lib/drivers/ip/transport/tcp/tcp.c @@ -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 */