Author: cgutman Date: Sun Jun 5 02:16:45 2011 New Revision: 52086 URL: http://svn.reactos.org/svn/reactos?rev=52086&view=rev Log: [IP/TCPIP] - Add a Next member to CONNECTION_ENDPOINT to allow multiple connections to be associated with a single address file while not overwriting pointers, dereferencing other people's connection objects, and causing horrific amounts of memory corruption - Add several sanity checks to prevent this from happening again - Don't try dereference address files and connection endpoints in the free functions; there should be none associated since r52083 (sanity checks ensure this) - Don't hold an extra reference to the address file when creating a listener; this reference is implicit - This should greatly increase reliability of activities that open lots of sockets such as web browsing and running servers on ROS - This also fixes most issues of not releasing a server port when the listener is closed
Modified: trunk/reactos/drivers/network/tcpip/include/titypes.h trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c Modified: trunk/reactos/drivers/network/tcpip/include/titypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/include/titypes.h?rev=52086&r1=52085&r2=52086&view=diff ============================================================================== --- trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/include/titypes.h [iso-8859-1] Sun Jun 5 02:16:45 2011 @@ -270,6 +270,8 @@ /* Signals */ UINT SignalState; /* Active signals from oskit */ + + struct _CONNECTION_ENDPOINT *Next; /* Next connection in address file list */ } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT; Modified: trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c?rev=52086&r1=52085&r2=52086&view=diff ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/dispatch.c [iso-8859-1] Sun Jun 5 02:16:45 2011 @@ -259,7 +259,7 @@ PTDI_REQUEST_KERNEL_ASSOCIATE Parameters; PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; - PCONNECTION_ENDPOINT Connection; + PCONNECTION_ENDPOINT Connection, LastConnection; PFILE_OBJECT FileObject; PADDRESS_FILE AddrFile = NULL; NTSTATUS Status; @@ -340,15 +340,22 @@ /* Add connection endpoint to the address file */ ReferenceObject(Connection); - AddrFile->Connection = Connection; - - /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */ + if (AddrFile->Connection == NULL) + AddrFile->Connection = Connection; + else + { + LastConnection = AddrFile->Connection; + while (LastConnection->Next != NULL) + LastConnection = LastConnection->Next; + LastConnection->Next = Connection; + } + ObDereferenceObject(FileObject); UnlockObjectFromDpcLevel(AddrFile); UnlockObject(Connection, OldIrql); - return Status; + return STATUS_SUCCESS; } @@ -425,10 +432,11 @@ * Status of operation */ { - PCONNECTION_ENDPOINT Connection; + PCONNECTION_ENDPOINT Connection, LastConnection; PTRANSPORT_CONTEXT TranContext; PIO_STACK_LOCATION IrpSp; KIRQL OldIrql; + NTSTATUS Status; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); @@ -458,19 +466,42 @@ LockObjectAtDpcLevel(Connection->AddressFile); - /* Remove this connection from the address file */ - DereferenceObject(Connection->AddressFile->Connection); - Connection->AddressFile->Connection = NULL; + /* Unlink this connection from the address file */ + if (Connection->AddressFile->Connection == Connection) + { + Connection->AddressFile->Connection = Connection->Next; + DereferenceObject(Connection); + Status = STATUS_SUCCESS; + } + else + { + LastConnection = Connection->AddressFile->Connection; + while (LastConnection->Next != Connection && LastConnection->Next != NULL) + LastConnection = LastConnection->Next; + if (LastConnection->Next == Connection) + { + LastConnection->Next = Connection->Next; + DereferenceObject(Connection); + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } UnlockObjectFromDpcLevel(Connection->AddressFile); - /* Remove the address file from this connection */ - DereferenceObject(Connection->AddressFile); - Connection->AddressFile = NULL; + if (Status == STATUS_SUCCESS) + { + /* Remove the address file from this connection */ + DereferenceObject(Connection->AddressFile); + Connection->AddressFile = NULL; + } UnlockObject(Connection, OldIrql); - return STATUS_SUCCESS; + return Status; } @@ -602,7 +633,6 @@ Status = STATUS_NO_MEMORY; if( NT_SUCCESS(Status) ) { - ReferenceObject(Connection->AddressFile); Connection->AddressFile->Listener->AddressFile = Connection->AddressFile; Modified: trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c?rev=52086&r1=52085&r2=52086&view=diff ============================================================================== --- trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/tcpip/fileobjs.c [iso-8859-1] Sun Jun 5 02:16:45 2011 @@ -161,6 +161,9 @@ TI_DbgPrint(MID_TRACE, ("Called.\n")); + /* We should not be associated with a connection here */ + ASSERT(!AddrFile->Connection); + /* Remove address file from the global list */ TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql); RemoveEntryList(&AddrFile->ListEntry); @@ -377,17 +380,14 @@ if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER; LockObject(AddrFile, &OldIrql); - /* We have to close this connection because we started it */ + + /* We have to close this listener because we started it */ if( AddrFile->Listener ) { AddrFile->Listener->AddressFile = NULL; TCPClose( AddrFile->Listener ); } - if( AddrFile->Connection ) - { - AddrFile->Connection->AddressFile = NULL; - DereferenceObject( AddrFile->Connection ); - } + UnlockObject(AddrFile, OldIrql); DereferenceObject(AddrFile); Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c?rev=52086&r1=52085&r2=52086&view=diff ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Sun Jun 5 02:16:45 2011 @@ -666,12 +666,13 @@ KIRQL OldIrql; NTSTATUS Status; PVOID Socket; - PADDRESS_FILE AddressFile = NULL; - PCONNECTION_ENDPOINT AddressConnection = NULL; LockObject(Connection, &OldIrql); Socket = Connection->SocketContext; Connection->SocketContext = NULL; + + /* We should not be associated to an address file at this point */ + ASSERT(!Connection->AddressFile); /* Don't try to close again if the other side closed us already */ if (Socket) @@ -693,27 +694,9 @@ Status = STATUS_SUCCESS; } - if (Connection->AddressFile) - { - LockObjectAtDpcLevel(Connection->AddressFile); - if (Connection->AddressFile->Connection == Connection) - { - AddressConnection = Connection->AddressFile->Connection; - Connection->AddressFile->Connection = NULL; - } - UnlockObjectFromDpcLevel(Connection->AddressFile); - - AddressFile = Connection->AddressFile; - Connection->AddressFile = NULL; - } - UnlockObject(Connection, OldIrql); DereferenceObject(Connection); - if (AddressConnection) - DereferenceObject(AddressConnection); - if (AddressFile) - DereferenceObject(AddressFile); return Status; }