mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 20:03:12 +00:00
[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 svn path=/trunk/; revision=52086
This commit is contained in:
parent
347ef6343f
commit
b92d45b853
4 changed files with 54 additions and 39 deletions
|
@ -270,6 +270,8 @@ typedef struct _CONNECTION_ENDPOINT {
|
||||||
|
|
||||||
/* Signals */
|
/* Signals */
|
||||||
UINT SignalState; /* Active signals from oskit */
|
UINT SignalState; /* Active signals from oskit */
|
||||||
|
|
||||||
|
struct _CONNECTION_ENDPOINT *Next; /* Next connection in address file list */
|
||||||
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
|
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ NTSTATUS DispTdiAssociateAddress(
|
||||||
PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
|
PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
|
||||||
PTRANSPORT_CONTEXT TranContext;
|
PTRANSPORT_CONTEXT TranContext;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
PCONNECTION_ENDPOINT Connection;
|
PCONNECTION_ENDPOINT Connection, LastConnection;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PADDRESS_FILE AddrFile = NULL;
|
PADDRESS_FILE AddrFile = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -340,15 +340,22 @@ NTSTATUS DispTdiAssociateAddress(
|
||||||
|
|
||||||
/* Add connection endpoint to the address file */
|
/* Add connection endpoint to the address file */
|
||||||
ReferenceObject(Connection);
|
ReferenceObject(Connection);
|
||||||
|
if (AddrFile->Connection == NULL)
|
||||||
AddrFile->Connection = Connection;
|
AddrFile->Connection = Connection;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastConnection = AddrFile->Connection;
|
||||||
|
while (LastConnection->Next != NULL)
|
||||||
|
LastConnection = LastConnection->Next;
|
||||||
|
LastConnection->Next = Connection;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
|
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
UnlockObjectFromDpcLevel(AddrFile);
|
UnlockObjectFromDpcLevel(AddrFile);
|
||||||
UnlockObject(Connection, OldIrql);
|
UnlockObject(Connection, OldIrql);
|
||||||
|
|
||||||
return Status;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,10 +432,11 @@ NTSTATUS DispTdiDisassociateAddress(
|
||||||
* Status of operation
|
* Status of operation
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PCONNECTION_ENDPOINT Connection;
|
PCONNECTION_ENDPOINT Connection, LastConnection;
|
||||||
PTRANSPORT_CONTEXT TranContext;
|
PTRANSPORT_CONTEXT TranContext;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
|
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
|
||||||
|
|
||||||
|
@ -458,19 +466,42 @@ NTSTATUS DispTdiDisassociateAddress(
|
||||||
|
|
||||||
LockObjectAtDpcLevel(Connection->AddressFile);
|
LockObjectAtDpcLevel(Connection->AddressFile);
|
||||||
|
|
||||||
/* Remove this connection from the address file */
|
/* Unlink this connection from the address file */
|
||||||
DereferenceObject(Connection->AddressFile->Connection);
|
if (Connection->AddressFile->Connection == Connection)
|
||||||
Connection->AddressFile->Connection = NULL;
|
{
|
||||||
|
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);
|
UnlockObjectFromDpcLevel(Connection->AddressFile);
|
||||||
|
|
||||||
|
if (Status == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
/* Remove the address file from this connection */
|
/* Remove the address file from this connection */
|
||||||
DereferenceObject(Connection->AddressFile);
|
DereferenceObject(Connection->AddressFile);
|
||||||
Connection->AddressFile = NULL;
|
Connection->AddressFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
UnlockObject(Connection, OldIrql);
|
UnlockObject(Connection, OldIrql);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -602,7 +633,6 @@ NTSTATUS DispTdiListen(
|
||||||
Status = STATUS_NO_MEMORY;
|
Status = STATUS_NO_MEMORY;
|
||||||
|
|
||||||
if( NT_SUCCESS(Status) ) {
|
if( NT_SUCCESS(Status) ) {
|
||||||
ReferenceObject(Connection->AddressFile);
|
|
||||||
Connection->AddressFile->Listener->AddressFile =
|
Connection->AddressFile->Listener->AddressFile =
|
||||||
Connection->AddressFile;
|
Connection->AddressFile;
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,9 @@ VOID AddrFileFree(
|
||||||
|
|
||||||
TI_DbgPrint(MID_TRACE, ("Called.\n"));
|
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 */
|
/* Remove address file from the global list */
|
||||||
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
|
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
|
||||||
RemoveEntryList(&AddrFile->ListEntry);
|
RemoveEntryList(&AddrFile->ListEntry);
|
||||||
|
@ -377,17 +380,14 @@ NTSTATUS FileCloseAddress(
|
||||||
if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
|
if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
LockObject(AddrFile, &OldIrql);
|
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 )
|
if( AddrFile->Listener )
|
||||||
{
|
{
|
||||||
AddrFile->Listener->AddressFile = NULL;
|
AddrFile->Listener->AddressFile = NULL;
|
||||||
TCPClose( AddrFile->Listener );
|
TCPClose( AddrFile->Listener );
|
||||||
}
|
}
|
||||||
if( AddrFile->Connection )
|
|
||||||
{
|
|
||||||
AddrFile->Connection->AddressFile = NULL;
|
|
||||||
DereferenceObject( AddrFile->Connection );
|
|
||||||
}
|
|
||||||
UnlockObject(AddrFile, OldIrql);
|
UnlockObject(AddrFile, OldIrql);
|
||||||
|
|
||||||
DereferenceObject(AddrFile);
|
DereferenceObject(AddrFile);
|
||||||
|
|
|
@ -666,13 +666,14 @@ NTSTATUS TCPClose
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PVOID Socket;
|
PVOID Socket;
|
||||||
PADDRESS_FILE AddressFile = NULL;
|
|
||||||
PCONNECTION_ENDPOINT AddressConnection = NULL;
|
|
||||||
|
|
||||||
LockObject(Connection, &OldIrql);
|
LockObject(Connection, &OldIrql);
|
||||||
Socket = Connection->SocketContext;
|
Socket = Connection->SocketContext;
|
||||||
Connection->SocketContext = NULL;
|
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 */
|
/* Don't try to close again if the other side closed us already */
|
||||||
if (Socket)
|
if (Socket)
|
||||||
{
|
{
|
||||||
|
@ -693,27 +694,9 @@ NTSTATUS TCPClose
|
||||||
Status = STATUS_SUCCESS;
|
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);
|
UnlockObject(Connection, OldIrql);
|
||||||
|
|
||||||
DereferenceObject(Connection);
|
DereferenceObject(Connection);
|
||||||
if (AddressConnection)
|
|
||||||
DereferenceObject(AddressConnection);
|
|
||||||
if (AddressFile)
|
|
||||||
DereferenceObject(AddressFile);
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue