Hi, Lubo Some comments as below: 1. Dhcp6Dxe,DnsDxe\ComponentName.c HttpBootDxe\HttpBootDhcp6.c UefiPxeBcDxe\PxeBcDhcp6.c Check for NULL pointer before free it. 2. DnsDxe\DnsImpl.c Ip6Dxe\ComponentName.c Mtftp6Dxe\Mtftp6Support.c There is memory leak if GetModeData return SUCCESS but IsConfigured is False. 3. IpSecDxe\IkeService.c Mtftp6Dxe\Mtftp6Support.c Ip6ModeData is not initialized but used in ON_EXIT. 4. // The caller is responsible for freeing the reference buffer The comments seems redundant. It's just one line FreePool.
Siyuan -----Original Message----- From: Zhang, Lubo Sent: Thursday, January 21, 2016 10:07 AM To: edk2-devel@lists.01.org Cc: Fu, Siyuan <siyuan...@intel.com>; Ye, Ting <ting...@intel.com>; Wu, Jiaxin <jiaxin...@intel.com> Subject: [patch] NetworkPkg:Fix Network memory leak when calling GetModeData interface Multiple network protocols have a GetModeData() interface, which may allocate memory resource in the return mode data structure. It's callers responsibility to free these buffers. Cc: Fu Siyuan <siyuan...@intel.com> Cc: Ye Ting <ting...@intel.com> Cc: Wu Jiaxin <jiaxin...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Zhang Lubo <lubo.zh...@intel.com> --- NetworkPkg/Dhcp6Dxe/ComponentName.c | 7 ++++++- NetworkPkg/DnsDxe/ComponentName.c | 11 +++++++++++ NetworkPkg/DnsDxe/DnsDhcp.c | 13 ++++++++++++- NetworkPkg/DnsDxe/DnsImpl.c | 35 ++++++++++++++++++++++++++++++++++ NetworkPkg/HttpBootDxe/HttpBootDhcp6.c | 6 +++++- NetworkPkg/Ip6Dxe/ComponentName.c | 27 ++++++++++++++++++++++++++ NetworkPkg/IpSecDxe/IkeService.c | 27 ++++++++++++++++++++++++++ NetworkPkg/Mtftp6Dxe/Mtftp6Support.c | 26 +++++++++++++++++++++++++ NetworkPkg/TcpDxe/TcpMisc.c | 30 ++++++++++++++++++++++++++++- NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 7 ++++++- NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c | 34 +++++++++++++++++++++++++++++++-- 11 files changed, 216 insertions(+), 7 deletions(-) diff --git a/NetworkPkg/Dhcp6Dxe/ComponentName.c b/NetworkPkg/Dhcp6Dxe/ComponentName.c index 927a7fe..e46106d 100644 --- a/NetworkPkg/Dhcp6Dxe/ComponentName.c +++ b/NetworkPkg/Dhcp6Dxe/ComponentName.c @@ -284,11 +284,16 @@ UpdateName ( if (Dhcp6ModeData.Ia->State > Dhcp6Rebinding) { return EFI_DEVICE_ERROR; } HandleName = mDhcp6ControllerName[Dhcp6ModeData.Ia->State]; } - + // + // The caller is responsible for freeing the reference buffer // + FreePool (Dhcp6ModeData.ClientId); FreePool (Dhcp6ModeData.Ia); + Status = AddUnicodeString2 ( "eng", gDhcp6ComponentName.SupportedLanguages, &gDhcp6ControllerNameTable, HandleName, diff --git a/NetworkPkg/DnsDxe/ComponentName.c b/NetworkPkg/DnsDxe/ComponentName.c index d95ed92..1efd425 100644 --- a/NetworkPkg/DnsDxe/ComponentName.c +++ b/NetworkPkg/DnsDxe/ComponentName.c @@ -209,10 +209,16 @@ UpdateDns4Name ( ModeData.DnsConfigData.StationIp.Addr[2], ModeData.DnsConfigData.StationIp.Addr[3], ModeData.DnsConfigData.LocalPort ); + // + // The caller is responsible for freeing the reference buffer // + FreePool (ModeData.DnsCacheList); FreePool (ModeData.DnsServerList); + if (gDnsControllerNameTable != NULL) { FreeUnicodeStringTable (gDnsControllerNameTable); gDnsControllerNameTable = NULL; } @@ -278,10 +284,15 @@ UpdateDns6Name ( sizeof (HandleName), L"DNSv6 (StationIp=%s, LocalPort=%d)", Address, ModeData.DnsConfigData.LocalPort ); + // + // The caller is responsible for freeing the reference buffer // + FreePool (ModeData.DnsServerList); FreePool (ModeData.DnsCacheList); if (gDnsControllerNameTable != NULL) { FreeUnicodeStringTable (gDnsControllerNameTable); gDnsControllerNameTable = NULL; } diff --git a/NetworkPkg/DnsDxe/DnsDhcp.c b/NetworkPkg/DnsDxe/DnsDhcp.c index 6b409ba..71fb698 100644 --- a/NetworkPkg/DnsDxe/DnsDhcp.c +++ b/NetworkPkg/DnsDxe/DnsDhcp.c @@ -131,11 +131,22 @@ DnsStartIp4( while (!Timeout) { Ip4->Poll (Ip4); if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && - Ip4Mode.IsConfigured) { + Ip4Mode.IsConfigured) { + if (Ip4Mode.GroupTable != NULL) { + FreePool (Ip4Mode.GroupTable); + } + + if (Ip4Mode.RouteTable != NULL) { + FreePool (Ip4Mode.RouteTable); + } + + if (Ip4Mode.IcmpTypeList != NULL) { + FreePool (Ip4Mode.IcmpTypeList); + } break; } } if (Timeout) { diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c index 71dacce..e5cbfc6 100644 --- a/NetworkPkg/DnsDxe/DnsImpl.c +++ b/NetworkPkg/DnsDxe/DnsImpl.c @@ -568,10 +568,21 @@ Dns4GetMapping ( while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) { Udp->Poll (Udp); if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) && Ip4Mode.IsConfigured) { + if (Ip4Mode.GroupTable != NULL) { + FreePool (Ip4Mode.GroupTable); + } + + if (Ip4Mode.RouteTable != NULL) { + FreePool (Ip4Mode.RouteTable); + } + + if (Ip4Mode.IcmpTypeList != NULL) { + FreePool (Ip4Mode.IcmpTypeList); + } Udp->Configure (Udp, NULL); return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS); } } @@ -619,10 +630,34 @@ Dns6GetMapping ( Udp->Poll (Udp); if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL)) && Ip6Mode.IsConfigured) { + if (Ip6Mode.AddressList != NULL) { + FreePool (Ip6Mode.AddressList); + } + + if (Ip6Mode.GroupTable != NULL) { + FreePool (Ip6Mode.GroupTable); + } + + if (Ip6Mode.RouteTable != NULL) { + FreePool (Ip6Mode.RouteTable); + } + + if (Ip6Mode.NeighborCache != NULL) { + FreePool (Ip6Mode.NeighborCache); + } + + if (Ip6Mode.PrefixTable != NULL) { + FreePool (Ip6Mode.PrefixTable); + } + + if (Ip6Mode.IcmpTypeList != NULL) { + FreePool (Ip6Mode.IcmpTypeList); + } + Udp->Configure (Udp, NULL); return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS); } } diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c index e5cf894..3067f2d 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c @@ -972,12 +972,16 @@ ON_EXIT: if (EFI_ERROR (Status)) { Dhcp6->Stop (Dhcp6); Dhcp6->Configure (Dhcp6, NULL); } else { ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA)); - ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA)); Dhcp6->Configure (Dhcp6, &Config); + // + // The caller is responsible for freeing the reference buffer + // + FreePool (Mode.ClientId); + FreePool (Mode.Ia); } return Status; } diff --git a/NetworkPkg/Ip6Dxe/ComponentName.c b/NetworkPkg/Ip6Dxe/ComponentName.c index 75a1562..103d081 100644 --- a/NetworkPkg/Ip6Dxe/ComponentName.c +++ b/NetworkPkg/Ip6Dxe/ComponentName.c @@ -262,10 +262,37 @@ UpdateName ( // Format the child name into the string buffer. // Offset = 0; Status = Ip6->GetModeData (Ip6, &Ip6ModeData, NULL, NULL); if (!EFI_ERROR (Status) && Ip6ModeData.IsStarted) { + // + // The caller need to free the reference buffer + // + if (Ip6ModeData.AddressList != NULL) { + FreePool (Ip6ModeData.AddressList); + } + + if (Ip6ModeData.GroupTable != NULL) { + FreePool (Ip6ModeData.GroupTable); + } + + if (Ip6ModeData.RouteTable != NULL) { + FreePool (Ip6ModeData.RouteTable); + } + + if (Ip6ModeData.NeighborCache != NULL) { + FreePool (Ip6ModeData.NeighborCache); + } + + if (Ip6ModeData.PrefixTable != NULL) { + FreePool (Ip6ModeData.PrefixTable); + } + + if (Ip6ModeData.IcmpTypeList != NULL) { + FreePool (Ip6ModeData.IcmpTypeList); + } + Status = NetLibIp6ToStr (&Ip6ModeData.ConfigData.StationAddress, Address, sizeof(Address)); if (EFI_ERROR (Status)) { return Status; } Offset += UnicodeSPrint ( diff --git a/NetworkPkg/IpSecDxe/IkeService.c b/NetworkPkg/IpSecDxe/IkeService.c index d857196..2803a89 100644 --- a/NetworkPkg/IpSecDxe/IkeService.c +++ b/NetworkPkg/IpSecDxe/IkeService.c @@ -345,10 +345,37 @@ IkeOpenOutputUdp ( } UdpService->IsConfigured = TRUE; ON_EXIT: + // + // The caller need to free the reference buffer // if + (Ip6ModeData.AddressList != NULL) { + FreePool (Ip6ModeData.AddressList); } + + if (Ip6ModeData.GroupTable != NULL) { + FreePool (Ip6ModeData.GroupTable); + } + + if (Ip6ModeData.RouteTable != NULL) { + FreePool (Ip6ModeData.RouteTable); + } + + if (Ip6ModeData.NeighborCache != NULL) { + FreePool (Ip6ModeData.NeighborCache); } + + if (Ip6ModeData.PrefixTable != NULL) { + FreePool (Ip6ModeData.PrefixTable); } + + if (Ip6ModeData.IcmpTypeList != NULL) { + FreePool (Ip6ModeData.IcmpTypeList); } + if (IfInfo != NULL) { FreePool (IfInfo); } return Status; diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c index c31fc9d..9487d30 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c @@ -330,10 +330,36 @@ Mtftp6GetMapping ( } } } ON_EXIT: + // + // The caller need to free the reference buffer // if + (Ip6Mode.AddressList != NULL) { + FreePool (Ip6Mode.AddressList); + } + + if (Ip6Mode.GroupTable != NULL) { + FreePool (Ip6Mode.GroupTable); + } + + if (Ip6Mode.RouteTable != NULL) { + FreePool (Ip6Mode.RouteTable); + } + + if (Ip6Mode.NeighborCache != NULL) { + FreePool (Ip6Mode.NeighborCache); + } + + if (Ip6Mode.PrefixTable != NULL) { + FreePool (Ip6Mode.PrefixTable); + } + + if (Ip6Mode.IcmpTypeList != NULL) { + FreePool (Ip6Mode.IcmpTypeList); + } if (Event != NULL) { gBS->CloseEvent (Event); } diff --git a/NetworkPkg/TcpDxe/TcpMisc.c b/NetworkPkg/TcpDxe/TcpMisc.c index 4096252..a8fdc78 100644 --- a/NetworkPkg/TcpDxe/TcpMisc.c +++ b/NetworkPkg/TcpDxe/TcpMisc.c @@ -559,17 +559,45 @@ TcpGetRcvMss ( if (Sock->IpVersion == IP_VERSION_4) { Ip4 = TcpProto->TcpService->IpIo->Ip.Ip4; ASSERT (Ip4 != NULL); Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL); + if (Ip4Mode.GroupTable != NULL) { + FreePool (Ip4Mode.GroupTable); + } + + if (Ip4Mode.RouteTable != NULL) { + FreePool (Ip4Mode.RouteTable); + } + + if (Ip4Mode.IcmpTypeList != NULL) { + FreePool (Ip4Mode.IcmpTypeList); + } return (UINT16) (Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD)); } else { Ip6 = TcpProto->TcpService->IpIo->Ip.Ip6; ASSERT (Ip6 != NULL); Ip6->GetModeData (Ip6, &Ip6Mode, NULL, NULL); - + if (Ip6Mode.AddressList != NULL) { + FreePool (Ip6Mode.AddressList); + } + if (Ip6Mode.GroupTable != NULL) { + FreePool (Ip6Mode.GroupTable); + } + if (Ip6Mode.RouteTable != NULL) { + FreePool (Ip6Mode.RouteTable); + } + if (Ip6Mode.NeighborCache != NULL) { + FreePool (Ip6Mode.NeighborCache); + } + if (Ip6Mode.PrefixTable != NULL) { + FreePool (Ip6Mode.PrefixTable); + } + if (Ip6Mode.IcmpTypeList != NULL) { + FreePool (Ip6Mode.IcmpTypeList); + } return (UINT16) (Ip6Mode.MaxPacketSize - sizeof (TCP_HEAD)); } } /** diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c index 6ad5f5f..fe15950 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c @@ -2080,17 +2080,22 @@ PxeBcDhcp6Sarr ( // the IP policy is Automatic). So we just hold the station IP address here and leave the IP policy as // Automatic, until we get the server IP address. This could let IP6 driver finish the router discovery // to find a valid router address. // CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS)); + // + // The caller is responsible for freeing the reference buffer // + FreePool (Mode.ClientId); FreePool (Mode.Ia); // // Check the selected offer whether BINL retry is needed. // Status = PxeBcHandleDhcp6Offer (Private); if (EFI_ERROR (Status)) { Dhcp6->Stop (Dhcp6); return Status; } - + return EFI_SUCCESS; } diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c index a6f6668..e125768 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c @@ -729,10 +729,22 @@ PxeBcCreateIp4Children ( // Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL); if (EFI_ERROR (Status)) { goto ON_ERROR; } + + if (Ip4ModeData.GroupTable != NULL) { + FreePool (Ip4ModeData.GroupTable); + } + + if (Ip4ModeData.RouteTable != NULL) { + FreePool (Ip4ModeData.RouteTable); + } + + if (Ip4ModeData.IcmpTypeList != NULL) { + FreePool (Ip4ModeData.IcmpTypeList); } Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize; Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC)); if (Private->Ip4Nic == NULL) { @@ -1056,13 +1068,31 @@ PxeBcCreateIp6Children ( // Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL); if (EFI_ERROR (Status)) { goto ON_ERROR; } - + Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize; - + + if (Ip6ModeData.AddressList != NULL) { + FreePool (Ip6ModeData.AddressList); } if (Ip6ModeData.GroupTable + != NULL) { + FreePool (Ip6ModeData.GroupTable); + } + if (Ip6ModeData.RouteTable != NULL) { + FreePool (Ip6ModeData.RouteTable); + } + if (Ip6ModeData.NeighborCache != NULL) { + FreePool (Ip6ModeData.NeighborCache); } if + (Ip6ModeData.PrefixTable != NULL) { + FreePool (Ip6ModeData.PrefixTable); } if + (Ip6ModeData.IcmpTypeList != NULL) { + FreePool (Ip6ModeData.IcmpTypeList); } // // Locate Ip6->Ip6Config and store it for set IPv6 address. // Status = gBS->HandleProtocol ( ControllerHandle, -- 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel