From 87f8f559cc0a076856b33d9477d319cf1fdebe4e Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 17 Aug 2014 04:03:29 +0000 Subject: [PATCH] [TCPIP] - Reference the address file while delivering data to avoid a use after free when an address file is closed during datagram delivery svn path=/trunk/; revision=63899 --- reactos/drivers/network/tcpip/tcpip/fileobjs.c | 13 ++++++++++--- reactos/lib/drivers/ip/transport/rawip/rawip.c | 1 + reactos/lib/drivers/ip/transport/udp/udp.c | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/reactos/drivers/network/tcpip/tcpip/fileobjs.c b/reactos/drivers/network/tcpip/tcpip/fileobjs.c index bd696b7cf2b..313e9d1ee66 100644 --- a/reactos/drivers/network/tcpip/tcpip/fileobjs.c +++ b/reactos/drivers/network/tcpip/tcpip/fileobjs.c @@ -222,7 +222,7 @@ PADDRESS_FILE AddrFindShared( * ARGUMENTS: * SearchContext = Pointer to search context * RETURNS: - * Pointer to address file, NULL if none was found + * Pointer to referenced address file, NULL if none was found */ PADDRESS_FILE AddrSearchNext( PAF_SEARCH SearchContext) @@ -232,6 +232,7 @@ PADDRESS_FILE AddrSearchNext( KIRQL OldIrql; PADDRESS_FILE Current = NULL; BOOLEAN Found = FALSE; + PADDRESS_FILE StartingAddrFile; TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql); @@ -241,8 +242,8 @@ PADDRESS_FILE AddrSearchNext( return NULL; } - /* Remove the extra reference we added to keep this address file in memory */ - DereferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry)); + /* Save this pointer so we can dereference it later */ + StartingAddrFile = CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry); CurrentEntry = SearchContext->Next; @@ -279,10 +280,16 @@ PADDRESS_FILE AddrSearchNext( /* Reference the next address file to prevent the link from disappearing behind our back */ ReferenceObject(CONTAINING_RECORD(SearchContext->Next, ADDRESS_FILE, ListEntry)); } + + /* Reference the returned address file before dereferencing the starting + * address file because it may be that Current == StartingAddrFile */ + ReferenceObject(Current); } else Current = NULL; + DereferenceObject(StartingAddrFile); + TcpipReleaseSpinLock(&AddressFileListLock, OldIrql); return Current; diff --git a/reactos/lib/drivers/ip/transport/rawip/rawip.c b/reactos/lib/drivers/ip/transport/rawip/rawip.c index 467fe398102..180f545db39 100644 --- a/reactos/lib/drivers/ip/transport/rawip/rawip.c +++ b/reactos/lib/drivers/ip/transport/rawip/rawip.c @@ -321,6 +321,7 @@ VOID RawIpReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) 0, IPPacket, DataSize); + DereferenceObject(AddrFile); } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); } else { /* There are no open address files that will take this datagram */ diff --git a/reactos/lib/drivers/ip/transport/udp/udp.c b/reactos/lib/drivers/ip/transport/udp/udp.c index 1629aad7f96..2f7dae94594 100644 --- a/reactos/lib/drivers/ip/transport/udp/udp.c +++ b/reactos/lib/drivers/ip/transport/udp/udp.c @@ -320,6 +320,7 @@ VOID UDPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket) UDPHeader->DestPort, IPPacket, DataSize); + DereferenceObject(AddrFile); } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); } else { /* There are no open address files that will take this datagram */