From c2949809b1deb1cc6fcfb27a9e8280f5b7b531b6 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Tue, 5 Mar 2024 03:01:55 +0300 Subject: [PATCH] import edk2-20220126gitbb1bba3d77-6.el8_9.6 --- ...nit-tests-to-CI-and-create-Host-Test.patch | 170 ++ ...2-NetworkPkg-Apply-uncrustify-chang1.patch | 1937 +++++++++++++++++ ...Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch | 1644 ++++++++++++++ ...Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch | 630 ++++++ ...iPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch | 168 ++ ...xeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch | 512 +++++ SPECS/edk2.spec | 28 +- 7 files changed, 5088 insertions(+), 1 deletion(-) create mode 100644 SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch create mode 100644 SOURCES/edk2-NetworkPkg-Apply-uncrustify-chang1.patch create mode 100644 SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch create mode 100644 SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch create mode 100644 SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch create mode 100644 SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch diff --git a/SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch b/SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch new file mode 100644 index 0000000..e06e6df --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch @@ -0,0 +1,170 @@ +From c1fe45c210fc719f1eedc0b02c357b71d6584971 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 2/3] NetworkPkg: : Add Unit tests to CI and create Host Test + DSC + +RH-Author: Jon Maloy +RH-MergeRequest: 51: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21993 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [2/3] c2b221c465295c93b2a57064bb17aee08400aa52 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21993 +CVE: CVE-2023-45230 +Upstream: Merged + +commit 8014ac2d7bbbc503f5562b51af46bb20ae3d22ff +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:44 2024 +0800 + + NetworkPkg: : Add Unit tests to CI and create Host Test DSC + + Adds Host Based testing to the NetworkPkg + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/NetworkPkg.ci.yaml | 7 +- + NetworkPkg/Test/NetworkPkgHostTest.dsc | 98 ++++++++++++++++++++++++++ + 2 files changed, 104 insertions(+), 1 deletion(-) + create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc + +diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml +index 07dc7abd69..076424eb60 100644 +--- a/NetworkPkg/NetworkPkg.ci.yaml ++++ b/NetworkPkg/NetworkPkg.ci.yaml +@@ -24,6 +24,9 @@ + "CompilerPlugin": { + "DscPath": "NetworkPkg.dsc" + }, ++ "HostUnitTestCompilerPlugin": { ++ "DscPath": "Test/NetworkPkgHostTest.dsc" ++ }, + "CharEncodingCheck": { + "IgnoreFiles": [] + }, +@@ -35,7 +38,9 @@ + "CryptoPkg/CryptoPkg.dec" + ], + # For host based unit tests +- "AcceptableDependencies-HOST_APPLICATION":[], ++ "AcceptableDependencies-HOST_APPLICATION":[ ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ ], + # For UEFI shell based apps + "AcceptableDependencies-UEFI_APPLICATION":[ + "ShellPkg/ShellPkg.dec" +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +new file mode 100644 +index 0000000000..1aeca5c5b3 +--- /dev/null ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -0,0 +1,98 @@ ++## @file ++# NetworkPkgHostTest DSC file used to build host-based unit tests. ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++[Defines] ++ PLATFORM_NAME = NetworkPkgHostTest ++ PLATFORM_GUID = 3b68324e-fc07-4d49-9520-9347ede65879 ++ PLATFORM_VERSION = 0.1 ++ DSC_SPECIFICATION = 0x00010005 ++ OUTPUT_DIRECTORY = Build/NetworkPkg/HostTest ++ SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64 ++ BUILD_TARGETS = NOOPT ++ SKUID_IDENTIFIER = DEFAULT ++ ++!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc ++[Packages] ++ MdePkg/MdePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ ++[Components] ++ # ++ # Build HOST_APPLICATION that tests NetworkPkg ++ # ++ ++# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. ++[LibraryClasses] ++ NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf ++ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf ++ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf ++ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf ++ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf ++ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf ++ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf ++ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf ++ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf ++ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf ++ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf ++ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf ++ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf ++ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf ++ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf ++ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf ++ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf ++ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf ++ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf ++ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf ++ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf ++ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf ++ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf ++ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf ++!ifdef CONTINUOUS_INTEGRATION ++ BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf ++ TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf ++!else ++ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf ++ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf ++ TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf ++!endif ++ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf ++ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf ++ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf ++ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf ++ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf ++ ++!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022 ++[LibraryClasses.X64] ++ # Provide StackCookie support lib so that we can link to /GS exports for VS builds ++ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf ++!endif ++ ++[LibraryClasses.common.UEFI_DRIVER] ++ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf ++ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf ++ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf ++[LibraryClasses.common.UEFI_APPLICATION] ++ DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf ++ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf ++[LibraryClasses.ARM, LibraryClasses.AARCH64] ++ # ++ # It is not possible to prevent ARM compiler calls to generic intrinsic functions. ++ # This library provides the instrinsic functions generated by a given compiler. ++ # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. ++ # ++!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019 ++ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf ++!endif ++ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf ++[LibraryClasses.ARM] ++ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf ++[LibraryClasses.RISCV64] ++ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf ++ ++[PcdsFixedAtBuild] ++ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2 ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4 +-- +2.41.0 + diff --git a/SOURCES/edk2-NetworkPkg-Apply-uncrustify-chang1.patch b/SOURCES/edk2-NetworkPkg-Apply-uncrustify-chang1.patch new file mode 100644 index 0000000..fc1e9ef --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-Apply-uncrustify-chang1.patch @@ -0,0 +1,1937 @@ +From 0e3b45af841f875aa1a0131ca9f4573ebd8e61fa Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 15:22:22 -0500 +Subject: [PATCH 1/3] NetworkPkg: Apply uncrustify changes + +RH-Author: Jon Maloy +RH-MergeRequest: 60: NetworkPkg: Apply uncrustify changes +RH-Jira: RHEL-22002 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [1/3] 221e6ef42cbd107383bb2b80e8f7763b6e81f5f9 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-22002 +CVE: CVE-2022-45234 +Upstream: Merged +Conflicts: This patch is too intrusive to apply at once in its entirety, + but we can apply a subset touching only the file being + targeted in the next commit in this series. + This way, that commit applies cleanly. + +commit d1050b9dff1cace252aff86630bfdb59dff5f507 +Author: Michael Kubacki +Date: Sun Dec 5 14:54:07 2021 -0800 + + NetworkPkg: Apply uncrustify changes + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 + + Apply uncrustify changes to .c/.h files in the NetworkPkg package + + Cc: Andrew Fish + Cc: Leif Lindholm + Cc: Michael D Kinney + Signed-off-by: Michael Kubacki + Reviewed-by: Maciej Rabeda + +Signed-off-by: Jon Maloy +--- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 973 ++++++++++++++------------- + 1 file changed, 498 insertions(+), 475 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 8d71143b79..425e0cf806 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -15,7 +15,9 @@ + // + // ALL_DHCP_Relay_Agents_and_Servers address: FF02::1:2 + // +-EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2}}; ++EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = { ++ { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 } ++}; + + /** + Parse out a DHCPv6 option by OptTag, and find the position in buffer. +@@ -30,35 +32,32 @@ EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0, + **/ + EFI_DHCP6_PACKET_OPTION * + PxeBcParseDhcp6Options ( +- IN UINT8 *Buffer, +- IN UINT32 Length, +- IN UINT16 OptTag ++ IN UINT8 *Buffer, ++ IN UINT32 Length, ++ IN UINT16 OptTag + ) + { +- EFI_DHCP6_PACKET_OPTION *Option; +- UINT32 Offset; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ UINT32 Offset; + +- Option = (EFI_DHCP6_PACKET_OPTION *) Buffer; +- Offset = 0; ++ Option = (EFI_DHCP6_PACKET_OPTION *)Buffer; ++ Offset = 0; + + // + // OpLen and OpCode here are both stored in network order. + // + while (Offset < Length) { +- + if (NTOHS (Option->OpCode) == OptTag) { +- + return Option; + } + +- Offset += (NTOHS(Option->OpLen) + 4); +- Option = (EFI_DHCP6_PACKET_OPTION *) (Buffer + Offset); ++ Offset += (NTOHS (Option->OpLen) + 4); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset); + } + + return NULL; + } + +- + /** + Build the options buffer for the DHCPv6 request packet. + +@@ -71,70 +70,70 @@ PxeBcParseDhcp6Options ( + **/ + UINT32 + PxeBcBuildDhcp6Options ( +- IN PXEBC_PRIVATE_DATA *Private, +- OUT EFI_DHCP6_PACKET_OPTION **OptList, +- IN UINT8 *Buffer ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT EFI_DHCP6_PACKET_OPTION **OptList, ++ IN UINT8 *Buffer + ) + { +- PXEBC_DHCP6_OPTION_ENTRY OptEnt; +- UINT32 Index; +- UINT16 Value; ++ PXEBC_DHCP6_OPTION_ENTRY OptEnt; ++ UINT32 Index; ++ UINT16 Value; + +- Index = 0; +- OptList[0] = (EFI_DHCP6_PACKET_OPTION *) Buffer; ++ Index = 0; ++ OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer; + + // + // Append client option request option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO); +- OptList[Index]->OpLen = HTONS (8); +- OptEnt.Oro = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data; +- OptEnt.Oro->OpCode[0] = HTONS(DHCP6_OPT_BOOT_FILE_URL); +- OptEnt.Oro->OpCode[1] = HTONS(DHCP6_OPT_BOOT_FILE_PARAM); +- OptEnt.Oro->OpCode[2] = HTONS(DHCP6_OPT_DNS_SERVERS); +- OptEnt.Oro->OpCode[3] = HTONS(DHCP6_OPT_VENDOR_CLASS); ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO); ++ OptList[Index]->OpLen = HTONS (8); ++ OptEnt.Oro = (PXEBC_DHCP6_OPTION_ORO *)OptList[Index]->Data; ++ OptEnt.Oro->OpCode[0] = HTONS (DHCP6_OPT_BOOT_FILE_URL); ++ OptEnt.Oro->OpCode[1] = HTONS (DHCP6_OPT_BOOT_FILE_PARAM); ++ OptEnt.Oro->OpCode[2] = HTONS (DHCP6_OPT_DNS_SERVERS); ++ OptEnt.Oro->OpCode[3] = HTONS (DHCP6_OPT_VENDOR_CLASS); + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append client network device interface option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI); +- OptList[Index]->OpLen = HTONS ((UINT16)3); +- OptEnt.Undi = (PXEBC_DHCP6_OPTION_UNDI *) OptList[Index]->Data; ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI); ++ OptList[Index]->OpLen = HTONS ((UINT16)3); ++ OptEnt.Undi = (PXEBC_DHCP6_OPTION_UNDI *)OptList[Index]->Data; + + if (Private->Nii != NULL) { +- OptEnt.Undi->Type = Private->Nii->Type; +- OptEnt.Undi->MajorVer = Private->Nii->MajorVer; +- OptEnt.Undi->MinorVer = Private->Nii->MinorVer; ++ OptEnt.Undi->Type = Private->Nii->Type; ++ OptEnt.Undi->MajorVer = Private->Nii->MajorVer; ++ OptEnt.Undi->MinorVer = Private->Nii->MinorVer; + } else { +- OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; +- OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; +- OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; ++ OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; ++ OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; ++ OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; + } + + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append client system architecture option + // +- OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH); +- OptList[Index]->OpLen = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_ARCH)); +- OptEnt.Arch = (PXEBC_DHCP6_OPTION_ARCH *) OptList[Index]->Data; +- Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); ++ OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH); ++ OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_ARCH)); ++ OptEnt.Arch = (PXEBC_DHCP6_OPTION_ARCH *)OptList[Index]->Data; ++ Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); + CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16)); + Index++; +- OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); ++ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + + // + // Append vendor class option to store the PXE class identifier. + // + OptList[Index]->OpCode = HTONS (DHCP6_OPT_VENDOR_CLASS); +- OptList[Index]->OpLen = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS)); +- OptEnt.VendorClass = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data; ++ OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS)); ++ OptEnt.VendorClass = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data; + OptEnt.VendorClass->Vendor = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM); +- OptEnt.VendorClass->ClassLen = HTONS ((UINT16) sizeof (PXEBC_CLASS_ID)); ++ OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (PXEBC_CLASS_ID)); + CopyMem ( + &OptEnt.VendorClass->ClassId, + DEFAULT_CLASS_ID_DATA, +@@ -169,7 +168,6 @@ PxeBcBuildDhcp6Options ( + return Index; + } + +- + /** + Cache the DHCPv6 packet. + +@@ -182,8 +180,8 @@ PxeBcBuildDhcp6Options ( + **/ + EFI_STATUS + PxeBcCacheDhcp6Packet ( +- IN EFI_DHCP6_PACKET *Dst, +- IN EFI_DHCP6_PACKET *Src ++ IN EFI_DHCP6_PACKET *Dst, ++ IN EFI_DHCP6_PACKET *Src + ) + { + if (Dst->Size < Src->Length) { +@@ -211,22 +209,22 @@ PxeBcCacheDhcp6Packet ( + **/ + EFI_STATUS + PxeBcDns6 ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN CHAR16 *HostName, +- OUT EFI_IPv6_ADDRESS *IpAddress ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN CHAR16 *HostName, ++ OUT EFI_IPv6_ADDRESS *IpAddress + ) + { +- EFI_STATUS Status; +- EFI_DNS6_PROTOCOL *Dns6; +- EFI_DNS6_CONFIG_DATA Dns6ConfigData; +- EFI_DNS6_COMPLETION_TOKEN Token; +- EFI_HANDLE Dns6Handle; +- EFI_IPv6_ADDRESS *DnsServerList; +- BOOLEAN IsDone; +- +- Dns6 = NULL; +- Dns6Handle = NULL; +- DnsServerList = Private->DnsServer; ++ EFI_STATUS Status; ++ EFI_DNS6_PROTOCOL *Dns6; ++ EFI_DNS6_CONFIG_DATA Dns6ConfigData; ++ EFI_DNS6_COMPLETION_TOKEN Token; ++ EFI_HANDLE Dns6Handle; ++ EFI_IPv6_ADDRESS *DnsServerList; ++ BOOLEAN IsDone; ++ ++ Dns6 = NULL; ++ Dns6Handle = NULL; ++ DnsServerList = Private->DnsServer; + ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN)); + + // +@@ -245,7 +243,7 @@ PxeBcDns6 ( + Status = gBS->OpenProtocol ( + Dns6Handle, + &gEfiDns6ProtocolGuid, +- (VOID **) &Dns6, ++ (VOID **)&Dns6, + Private->Image, + Private->Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER +@@ -308,10 +306,12 @@ PxeBcDns6 ( + Status = EFI_DEVICE_ERROR; + goto Exit; + } +- if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { ++ ++ if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } ++ + // + // We just return the first IPv6 address from DNS protocol. + // +@@ -325,10 +325,12 @@ Exit: + if (Token.Event != NULL) { + gBS->CloseEvent (Token.Event); + } ++ + if (Token.RspData.H2AData != NULL) { + if (Token.RspData.H2AData->IpList != NULL) { + FreePool (Token.RspData.H2AData->IpList); + } ++ + FreePool (Token.RspData.H2AData); + } + +@@ -375,26 +377,26 @@ Exit: + **/ + EFI_STATUS + PxeBcExtractBootFileUrl ( +- IN PXEBC_PRIVATE_DATA *Private, +- OUT UINT8 **FileName, +- IN OUT EFI_IPv6_ADDRESS *SrvAddr, +- IN CHAR8 *BootFile, +- IN UINT16 Length ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT UINT8 **FileName, ++ IN OUT EFI_IPv6_ADDRESS *SrvAddr, ++ IN CHAR8 *BootFile, ++ IN UINT16 Length + ) + { +- UINT16 PrefixLen; +- CHAR8 *BootFileNamePtr; +- CHAR8 *BootFileName; +- UINT16 BootFileNameLen; +- CHAR8 *TmpStr; +- CHAR8 TmpChar; +- CHAR8 *ServerAddressOption; +- CHAR8 *ServerAddress; +- CHAR8 *ModeStr; +- CHAR16 *HostName; +- BOOLEAN IpExpressedUrl; +- UINTN Len; +- EFI_STATUS Status; ++ UINT16 PrefixLen; ++ CHAR8 *BootFileNamePtr; ++ CHAR8 *BootFileName; ++ UINT16 BootFileNameLen; ++ CHAR8 *TmpStr; ++ CHAR8 TmpChar; ++ CHAR8 *ServerAddressOption; ++ CHAR8 *ServerAddress; ++ CHAR8 *ModeStr; ++ CHAR16 *HostName; ++ BOOLEAN IpExpressedUrl; ++ UINTN Len; ++ EFI_STATUS Status; + + IpExpressedUrl = TRUE; + // +@@ -417,17 +419,18 @@ PxeBcExtractBootFileUrl ( + // As an example where the BOOTFILE_NAME is the EFI loader and + // SERVER_ADDRESS is the ASCII encoding of an IPV6 address. + // +- PrefixLen = (UINT16) AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX); ++ PrefixLen = (UINT16)AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX); + +- if (Length <= PrefixLen || +- CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0) { ++ if ((Length <= PrefixLen) || ++ (CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0)) ++ { + return EFI_NOT_FOUND; + } + + BootFile = BootFile + PrefixLen; +- Length = (UINT16) (Length - PrefixLen); ++ Length = (UINT16)(Length - PrefixLen); + +- TmpStr = (CHAR8 *) AllocateZeroPool (Length + 1); ++ TmpStr = (CHAR8 *)AllocateZeroPool (Length + 1); + if (TmpStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -440,7 +443,7 @@ PxeBcExtractBootFileUrl ( + // + ServerAddressOption = TmpStr; + if (*ServerAddressOption == PXEBC_ADDR_START_DELIMITER) { +- ServerAddressOption ++; ++ ServerAddressOption++; + ServerAddress = ServerAddressOption; + while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) { + ServerAddress++; +@@ -461,10 +464,9 @@ PxeBcExtractBootFileUrl ( + FreePool (TmpStr); + return Status; + } +- + } else { + IpExpressedUrl = FALSE; +- ServerAddress = ServerAddressOption; ++ ServerAddress = ServerAddressOption; + while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) { + ServerAddress++; + } +@@ -473,14 +475,16 @@ PxeBcExtractBootFileUrl ( + FreePool (TmpStr); + return EFI_INVALID_PARAMETER; + } ++ + *ServerAddress = '\0'; + +- Len = AsciiStrSize (ServerAddressOption); ++ Len = AsciiStrSize (ServerAddressOption); + HostName = AllocateZeroPool (Len * sizeof (CHAR16)); + if (HostName == NULL) { + FreePool (TmpStr); + return EFI_OUT_OF_RESOURCES; + } ++ + AsciiStrToUnicodeStrS ( + ServerAddressOption, + HostName, +@@ -490,7 +494,7 @@ PxeBcExtractBootFileUrl ( + // + // Perform DNS resolution. + // +- Status = PxeBcDns6 (Private,HostName, SrvAddr); ++ Status = PxeBcDns6 (Private, HostName, SrvAddr); + if (EFI_ERROR (Status)) { + FreePool (TmpStr); + return Status; +@@ -500,23 +504,24 @@ PxeBcExtractBootFileUrl ( + // + // Get the part of BOOTFILE_NAME string. + // +- BootFileNamePtr = (CHAR8*)((UINTN)ServerAddress + 1); ++ BootFileNamePtr = (CHAR8 *)((UINTN)ServerAddress + 1); + if (IpExpressedUrl) { + if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) { + FreePool (TmpStr); + return EFI_INVALID_PARAMETER; + } ++ + ++BootFileNamePtr; + } + +- BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1); +- if (BootFileNameLen != 0 || FileName != NULL) { ++ BootFileNameLen = (UINT16)(Length - (UINT16)((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1); ++ if ((BootFileNameLen != 0) || (FileName != NULL)) { + // + // Remove trailing mode=octet if present and ignore. All other modes are + // invalid for netboot6, so reject them. + // + ModeStr = AsciiStrStr (BootFileNamePtr, ";mode=octet"); +- if (ModeStr != NULL && *(ModeStr + AsciiStrLen (";mode=octet")) == '\0') { ++ if ((ModeStr != NULL) && (*(ModeStr + AsciiStrLen (";mode=octet")) == '\0')) { + *ModeStr = '\0'; + } else if (AsciiStrStr (BootFileNamePtr, ";mode=") != NULL) { + FreePool (TmpStr); +@@ -526,30 +531,32 @@ PxeBcExtractBootFileUrl ( + // + // Extract boot file name from URL. + // +- BootFileName = (CHAR8 *) AllocateZeroPool (BootFileNameLen); ++ BootFileName = (CHAR8 *)AllocateZeroPool (BootFileNameLen); + if (BootFileName == NULL) { + FreePool (TmpStr); + return EFI_OUT_OF_RESOURCES; + } +- *FileName = (UINT8*) BootFileName; ++ ++ *FileName = (UINT8 *)BootFileName; + + // + // Decode percent-encoding in boot file name. + // + while (*BootFileNamePtr != '\0') { + if (*BootFileNamePtr == '%') { +- TmpChar = *(BootFileNamePtr+ 3); ++ TmpChar = *(BootFileNamePtr+ 3); + *(BootFileNamePtr+ 3) = '\0'; +- *BootFileName = (UINT8) AsciiStrHexToUintn ((CHAR8*)(BootFileNamePtr + 1)); ++ *BootFileName = (UINT8)AsciiStrHexToUintn ((CHAR8 *)(BootFileNamePtr + 1)); + BootFileName++; + *(BootFileNamePtr+ 3) = TmpChar; +- BootFileNamePtr += 3; ++ BootFileNamePtr += 3; + } else { + *BootFileName = *BootFileNamePtr; + BootFileName++; + BootFileNamePtr++; + } + } ++ + *BootFileName = '\0'; + } + +@@ -558,7 +565,6 @@ PxeBcExtractBootFileUrl ( + return EFI_SUCCESS; + } + +- + /** + Parse the Boot File Parameter option. + +@@ -571,14 +577,14 @@ PxeBcExtractBootFileUrl ( + **/ + EFI_STATUS + PxeBcExtractBootFileParam ( +- IN CHAR8 *BootFilePara, +- OUT UINT16 *BootFileSize ++ IN CHAR8 *BootFilePara, ++ OUT UINT16 *BootFileSize + ) + { +- UINT16 Length; +- UINT8 Index; +- UINT8 Digit; +- UINT32 Size; ++ UINT16 Length; ++ UINT8 Index; ++ UINT8 Digit; ++ UINT32 Size; + + CopyMem (&Length, BootFilePara, sizeof (UINT16)); + Length = NTOHS (Length); +@@ -586,7 +592,7 @@ PxeBcExtractBootFileParam ( + // + // The BootFile Size should be 1~5 byte ASCII strings + // +- if (Length < 1 || Length > 5) { ++ if ((Length < 1) || (Length > 5)) { + return EFI_NOT_FOUND; + } + +@@ -608,11 +614,10 @@ PxeBcExtractBootFileParam ( + return EFI_NOT_FOUND; + } + +- *BootFileSize = (UINT16) Size; ++ *BootFileSize = (UINT16)Size; + return EFI_SUCCESS; + } + +- + /** + Parse the cached DHCPv6 packet, including all the options. + +@@ -627,15 +632,15 @@ PxeBcParseDhcp6Packet ( + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + ) + { +- EFI_DHCP6_PACKET *Offer; +- EFI_DHCP6_PACKET_OPTION **Options; +- EFI_DHCP6_PACKET_OPTION *Option; +- PXEBC_OFFER_TYPE OfferType; +- BOOLEAN IsProxyOffer; +- BOOLEAN IsPxeOffer; +- UINT32 Offset; +- UINT32 Length; +- UINT32 EnterpriseNum; ++ EFI_DHCP6_PACKET *Offer; ++ EFI_DHCP6_PACKET_OPTION **Options; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ PXEBC_OFFER_TYPE OfferType; ++ BOOLEAN IsProxyOffer; ++ BOOLEAN IsPxeOffer; ++ UINT32 Offset; ++ UINT32 Length; ++ UINT32 EnterpriseNum; + + IsProxyOffer = TRUE; + IsPxeOffer = FALSE; +@@ -644,15 +649,14 @@ PxeBcParseDhcp6Packet ( + + ZeroMem (Cache6->OptList, sizeof (Cache6->OptList)); + +- Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option); +- Offset = 0; +- Length = GET_DHCP6_OPTION_SIZE (Offer); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option); ++ Offset = 0; ++ Length = GET_DHCP6_OPTION_SIZE (Offer); + + // + // OpLen and OpCode here are both stored in network order, since they are from original packet. + // + while (Offset < Length) { +- + if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) { + Options[PXEBC_DHCP6_IDX_IA_NA] = Option; + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) { +@@ -669,7 +673,7 @@ PxeBcParseDhcp6Packet ( + } + + Offset += (NTOHS (Option->OpLen) + 4); +- Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option + Offset); ++ Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset); + } + + // +@@ -683,7 +687,7 @@ PxeBcParseDhcp6Packet ( + NTOHS (Option->OpLen), + DHCP6_OPT_STATUS_CODE + ); +- if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) { ++ if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) { + IsProxyOffer = FALSE; + } + } +@@ -692,12 +696,13 @@ PxeBcParseDhcp6Packet ( + // The offer with "PXEClient" is a pxe offer. + // + Option = Options[PXEBC_DHCP6_IDX_VENDOR_CLASS]; +- EnterpriseNum = HTONL(PXEBC_DHCP6_ENTERPRISE_NUM); ++ EnterpriseNum = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM); + +- if (Option != NULL && +- NTOHS(Option->OpLen) >= 13 && +- CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0 && +- CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0) { ++ if ((Option != NULL) && ++ (NTOHS (Option->OpLen) >= 13) && ++ (CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0) && ++ (CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0)) ++ { + IsPxeOffer = TRUE; + } + +@@ -721,7 +726,6 @@ PxeBcParseDhcp6Packet ( + return EFI_SUCCESS; + } + +- + /** + Cache the DHCPv6 ack packet, and parse it on demand. + +@@ -735,9 +739,9 @@ PxeBcParseDhcp6Packet ( + **/ + EFI_STATUS + PxeBcCopyDhcp6Ack ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PACKET *Ack, +- IN BOOLEAN Verified ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PACKET *Ack, ++ IN BOOLEAN Verified + ) + { + EFI_PXE_BASE_CODE_MODE *Mode; +@@ -762,7 +766,6 @@ PxeBcCopyDhcp6Ack ( + return EFI_SUCCESS; + } + +- + /** + Cache the DHCPv6 proxy offer packet according to the received order. + +@@ -775,12 +778,12 @@ PxeBcCopyDhcp6Ack ( + **/ + EFI_STATUS + PxeBcCopyDhcp6Proxy ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT32 OfferIndex ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 OfferIndex + ) + { +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_DHCP6_PACKET *Offer; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_DHCP6_PACKET *Offer; + EFI_STATUS Status; + + ASSERT (OfferIndex < Private->OfferNum); +@@ -793,9 +796,10 @@ PxeBcCopyDhcp6Proxy ( + // Cache the proxy offer packet and parse it. + // + Status = PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer); +- if (EFI_ERROR(Status)) { ++ if (EFI_ERROR (Status)) { + return Status; + } ++ + PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6); + + // +@@ -820,33 +824,33 @@ PxeBcCopyDhcp6Proxy ( + **/ + UINT8 * + PxeBcDhcp6SeekOption ( +- IN UINT8 *Buf, +- IN UINT32 SeekLen, +- IN UINT16 OptType ++ IN UINT8 *Buf, ++ IN UINT32 SeekLen, ++ IN UINT16 OptType + ) + { +- UINT8 *Cursor; +- UINT8 *Option; +- UINT16 DataLen; +- UINT16 OpCode; ++ UINT8 *Cursor; ++ UINT8 *Option; ++ UINT16 DataLen; ++ UINT16 OpCode; + + Option = NULL; + Cursor = Buf; + + while (Cursor < Buf + SeekLen) { +- OpCode = ReadUnaligned16 ((UINT16 *) Cursor); ++ OpCode = ReadUnaligned16 ((UINT16 *)Cursor); + if (OpCode == HTONS (OptType)) { + Option = Cursor; + break; + } +- DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2))); ++ ++ DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2))); + Cursor += (DataLen + 4); + } + + return Option; + } + +- + /** + Build and send out the request packet for the bootfile, and parse the reply. + +@@ -861,34 +865,34 @@ PxeBcDhcp6SeekOption ( + **/ + EFI_STATUS + PxeBcRequestBootService ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT32 Index ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 Index + ) + { +- EFI_PXE_BASE_CODE_UDP_PORT SrcPort; +- EFI_PXE_BASE_CODE_UDP_PORT DestPort; +- EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; +- EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; +- UINTN DiscoverLen; +- EFI_DHCP6_PACKET *Request; +- UINTN RequestLen; +- EFI_DHCP6_PACKET *Reply; +- UINT8 *RequestOpt; +- UINT8 *DiscoverOpt; +- UINTN ReadSize; +- UINT16 OpFlags; +- UINT16 OpCode; +- UINT16 OpLen; +- EFI_STATUS Status; +- EFI_DHCP6_PACKET *IndexOffer; +- UINT8 *Option; +- +- PxeBc = &Private->PxeBc; +- Request = Private->Dhcp6Request; +- IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer; +- SrcPort = PXEBC_BS_DISCOVER_PORT; +- DestPort = PXEBC_BS_DISCOVER_PORT; +- OpFlags = 0; ++ EFI_PXE_BASE_CODE_UDP_PORT SrcPort; ++ EFI_PXE_BASE_CODE_UDP_PORT DestPort; ++ EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; ++ EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; ++ UINTN DiscoverLen; ++ EFI_DHCP6_PACKET *Request; ++ UINTN RequestLen; ++ EFI_DHCP6_PACKET *Reply; ++ UINT8 *RequestOpt; ++ UINT8 *DiscoverOpt; ++ UINTN ReadSize; ++ UINT16 OpFlags; ++ UINT16 OpCode; ++ UINT16 OpLen; ++ EFI_STATUS Status; ++ EFI_DHCP6_PACKET *IndexOffer; ++ UINT8 *Option; ++ ++ PxeBc = &Private->PxeBc; ++ Request = Private->Dhcp6Request; ++ IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer; ++ SrcPort = PXEBC_BS_DISCOVER_PORT; ++ DestPort = PXEBC_BS_DISCOVER_PORT; ++ OpFlags = 0; + + if (Request == NULL) { + return EFI_DEVICE_ERROR; +@@ -925,19 +929,20 @@ PxeBcRequestBootService ( + // + // Add Server ID Option. + // +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen); + CopyMem (DiscoverOpt, Option, OpLen + 4); + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } + + while (RequestLen < Request->Length) { +- OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode); +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen); +- if (OpCode != EFI_DHCP6_IA_TYPE_NA && +- OpCode != EFI_DHCP6_IA_TYPE_TA && +- OpCode != DHCP6_OPT_SERVER_ID +- ) { ++ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen); ++ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) && ++ (OpCode != EFI_DHCP6_IA_TYPE_TA) && ++ (OpCode != DHCP6_OPT_SERVER_ID) ++ ) ++ { + // + // Copy all the options except IA option and Server ID + // +@@ -945,6 +950,7 @@ PxeBcRequestBootService ( + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } ++ + RequestOpt += (OpLen + 4); + RequestLen += (OpLen + 4); + } +@@ -959,7 +965,7 @@ PxeBcRequestBootService ( + ); + if (Option != NULL) { + CalcElapsedTime (Private); +- WriteUnaligned16 ((UINT16*)(Option + 4), HTONS((UINT16) Private->ElapsedTime)); ++ WriteUnaligned16 ((UINT16 *)(Option + 4), HTONS ((UINT16)Private->ElapsedTime)); + } + + Status = PxeBc->UdpWrite ( +@@ -973,7 +979,7 @@ PxeBcRequestBootService ( + NULL, + NULL, + &DiscoverLen, +- (VOID *) Discover ++ (VOID *)Discover + ); + + if (EFI_ERROR (Status)) { +@@ -984,8 +990,8 @@ PxeBcRequestBootService ( + // Cache the right PXE reply packet here, set valid flag later. + // Especially for PXE discover packet, store it into mode data here. + // +- Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; +- ReadSize = (UINTN) Reply->Size; ++ Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; ++ ReadSize = (UINTN)Reply->Size; + + // + // Start Udp6Read instance +@@ -1005,7 +1011,7 @@ PxeBcRequestBootService ( + NULL, + NULL, + &ReadSize, +- (VOID *) &Reply->Dhcp6 ++ (VOID *)&Reply->Dhcp6 + ); + // + // Stop Udp6Read instance +@@ -1019,7 +1025,7 @@ PxeBcRequestBootService ( + // + // Update length + // +- Reply->Length = (UINT32) ReadSize; ++ Reply->Length = (UINT32)ReadSize; + + return EFI_SUCCESS; + +@@ -1031,7 +1037,6 @@ ON_ERROR: + return Status; + } + +- + /** + Retry to request bootfile name by the BINL offer. + +@@ -1054,8 +1059,10 @@ PxeBcRetryDhcp6Binl ( + EFI_STATUS Status; + + ASSERT (Index < PXEBC_OFFER_MAX_NUM); +- ASSERT (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl || +- Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl); ++ ASSERT ( ++ Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl || ++ Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl ++ ); + + Mode = Private->PxeBc.Mode; + Private->IsDoDiscover = FALSE; +@@ -1078,7 +1085,7 @@ PxeBcRetryDhcp6Binl ( + Private, + &Private->BootFileName, + &Private->ServerIp.v6, +- (CHAR8 *) (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data), ++ (CHAR8 *)(Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data), + NTOHS (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->OpLen) + ); + if (EFI_ERROR (Status)) { +@@ -1101,9 +1108,10 @@ PxeBcRetryDhcp6Binl ( + return Status; + } + +- if (Cache6->OfferType != PxeOfferTypeProxyPxe10 && +- Cache6->OfferType != PxeOfferTypeProxyWfm11a && +- Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) { ++ if ((Cache6->OfferType != PxeOfferTypeProxyPxe10) && ++ (Cache6->OfferType != PxeOfferTypeProxyWfm11a) && ++ (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL)) ++ { + // + // This BINL ack doesn't have discovery option set or multicast option set + // or bootfile name specified. +@@ -1121,7 +1129,6 @@ PxeBcRetryDhcp6Binl ( + return EFI_SUCCESS; + } + +- + /** + Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount. + +@@ -1133,8 +1140,8 @@ PxeBcRetryDhcp6Binl ( + **/ + EFI_STATUS + PxeBcCacheDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PACKET *RcvdOffer ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PACKET *RcvdOffer + ) + { + PXEBC_DHCP6_PACKET_CACHE *Cache6; +@@ -1179,8 +1186,9 @@ PxeBcCacheDhcp6Offer ( + // + Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum; + Private->OfferCount[OfferType]++; +- } else if ((OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeProxyWfm11a) && +- Private->OfferCount[OfferType] < 1) { ++ } else if (((OfferType == PxeOfferTypeProxyPxe10) || (OfferType == PxeOfferTypeProxyWfm11a)) && ++ (Private->OfferCount[OfferType] < 1)) ++ { + // + // Only cache the first PXE10/WFM11a offer, and discard the others. + // +@@ -1202,7 +1210,6 @@ PxeBcCacheDhcp6Offer ( + return EFI_SUCCESS; + } + +- + /** + Select an DHCPv6 offer, and record SelectIndex and SelectProxyType. + +@@ -1211,12 +1218,12 @@ PxeBcCacheDhcp6Offer ( + **/ + VOID + PxeBcSelectDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- UINT32 Index; +- UINT32 OfferIndex; +- PXEBC_OFFER_TYPE OfferType; ++ UINT32 Index; ++ UINT32 OfferIndex; ++ PXEBC_OFFER_TYPE OfferType; + + Private->SelectIndex = 0; + +@@ -1229,43 +1236,40 @@ PxeBcSelectDhcp6Offer ( + // 1. DhcpPxe10 offer + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpPxe10][0] + 1; +- + } else if (Private->OfferCount[PxeOfferTypeDhcpWfm11a] > 0) { + // + // 2. DhcpWfm11a offer + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpWfm11a][0] + 1; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyPxe10] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyPxe10] > 0)) ++ { + // + // 3. DhcpOnly offer and ProxyPxe10 offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyPxe10; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0)) ++ { + // + // 4. DhcpOnly offer and ProxyWfm11a offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyWfm11a; +- + } else if (Private->OfferCount[PxeOfferTypeDhcpBinl] > 0) { + // + // 5. DhcpBinl offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpBinl][0] + 1; +- +- } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && +- Private->OfferCount[PxeOfferTypeProxyBinl] > 0) { ++ } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && ++ (Private->OfferCount[PxeOfferTypeProxyBinl] > 0)) ++ { + // + // 6. DhcpOnly offer and ProxyBinl offer. + // + Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; + Private->SelectProxyType = PxeOfferTypeProxyBinl; +- + } else { + // + // 7. DhcpOnly offer with bootfilename. +@@ -1283,7 +1287,6 @@ PxeBcSelectDhcp6Offer ( + // Select offer by received order. + // + for (Index = 0; Index < Private->OfferNum; Index++) { +- + OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType; + + if (IS_PROXY_OFFER (OfferType)) { +@@ -1294,8 +1297,9 @@ PxeBcSelectDhcp6Offer ( + } + + if (!Private->IsProxyRecved && +- OfferType == PxeOfferTypeDhcpOnly && +- Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) { ++ (OfferType == PxeOfferTypeDhcpOnly) && ++ (Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL)) ++ { + // + // Skip if DhcpOnly offer without any other proxy offers or bootfilename. + // +@@ -1308,7 +1312,6 @@ PxeBcSelectDhcp6Offer ( + } + } + +- + /** + Handle the DHCPv6 offer packet. + +@@ -1322,21 +1325,21 @@ PxeBcSelectDhcp6Offer ( + **/ + EFI_STATUS + PxeBcHandleDhcp6Offer ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- PXEBC_DHCP6_PACKET_CACHE *Cache6; +- EFI_STATUS Status; +- PXEBC_OFFER_TYPE OfferType; +- UINT32 ProxyIndex; +- UINT32 SelectIndex; +- UINT32 Index; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6; ++ EFI_STATUS Status; ++ PXEBC_OFFER_TYPE OfferType; ++ UINT32 ProxyIndex; ++ UINT32 SelectIndex; ++ UINT32 Index; + + ASSERT (Private->SelectIndex > 0); +- SelectIndex = (UINT32) (Private->SelectIndex - 1); ++ SelectIndex = (UINT32)(Private->SelectIndex - 1); + ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); +- Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6; +- Status = EFI_SUCCESS; ++ Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6; ++ Status = EFI_SUCCESS; + + // + // First try to cache DNS server address if DHCP6 offer provides. +@@ -1346,6 +1349,7 @@ PxeBcHandleDhcp6Offer ( + if (Private->DnsServer == NULL) { + return EFI_OUT_OF_RESOURCES; + } ++ + CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); + } + +@@ -1357,7 +1361,6 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_NO_RESPONSE; + } + } else if (Cache6->OfferType == PxeOfferTypeDhcpOnly) { +- + if (Private->IsProxyRecved) { + // + // DhcpOnly offer is selected, so need try to request bootfilename. +@@ -1375,12 +1378,12 @@ PxeBcHandleDhcp6Offer ( + // Try all the cached ProxyBinl offer one by one to request bootfilename. + // + for (Index = 0; Index < Private->OfferCount[Private->SelectProxyType]; Index++) { +- + ProxyIndex = Private->OfferIndex[Private->SelectProxyType][Index]; + if (!EFI_ERROR (PxeBcRetryDhcp6Binl (Private, ProxyIndex))) { + break; + } + } ++ + if (Index == Private->OfferCount[Private->SelectProxyType]) { + Status = EFI_NO_RESPONSE; + } +@@ -1397,7 +1400,6 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_NO_RESPONSE; + + for (Index = 0; Index < Private->OfferNum; Index++) { +- + OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType; + + if (!IS_PROXY_OFFER (OfferType)) { +@@ -1423,7 +1425,7 @@ PxeBcHandleDhcp6Offer ( + } + } + +- if (!EFI_ERROR (Status) && Private->SelectProxyType != PxeOfferTypeProxyBinl) { ++ if (!EFI_ERROR (Status) && (Private->SelectProxyType != PxeOfferTypeProxyBinl)) { + // + // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it. + // +@@ -1441,14 +1443,13 @@ PxeBcHandleDhcp6Offer ( + // + // All PXE boot information is ready by now. + // +- Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE); ++ Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE); + Private->PxeBc.Mode->DhcpDiscoverValid = TRUE; + } + + return Status; + } + +- + /** + Unregister the address by Ip6Config protocol. + +@@ -1457,7 +1458,7 @@ PxeBcHandleDhcp6Offer ( + **/ + VOID + PxeBcUnregisterIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { + if (Private->Ip6Policy != PXEBC_IP6_POLICY_MAX) { +@@ -1485,18 +1486,18 @@ PxeBcUnregisterIp6Address ( + **/ + EFI_STATUS + PxeBcCheckRouteTable ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINTN TimeOutInSecond, +- OUT EFI_IPv6_ADDRESS *GatewayAddr ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINTN TimeOutInSecond, ++ OUT EFI_IPv6_ADDRESS *GatewayAddr + ) + { +- EFI_STATUS Status; +- EFI_IP6_PROTOCOL *Ip6; +- EFI_IP6_MODE_DATA Ip6ModeData; +- UINTN Index; +- EFI_EVENT TimeOutEvt; +- UINTN RetryCount; +- BOOLEAN GatewayIsFound; ++ EFI_STATUS Status; ++ EFI_IP6_PROTOCOL *Ip6; ++ EFI_IP6_MODE_DATA Ip6ModeData; ++ UINTN Index; ++ EFI_EVENT TimeOutEvt; ++ UINTN RetryCount; ++ BOOLEAN GatewayIsFound; + + ASSERT (GatewayAddr != NULL); + ASSERT (Private != NULL); +@@ -1527,23 +1528,28 @@ PxeBcCheckRouteTable ( + 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 (GatewayIsFound || RetryCount == TimeOutInSecond) { ++ if (GatewayIsFound || (RetryCount == TimeOutInSecond)) { + break; + } + +@@ -1569,6 +1575,7 @@ PxeBcCheckRouteTable ( + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } ++ + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + Ip6->Poll (Ip6); + } +@@ -1600,29 +1607,29 @@ ON_EXIT: + **/ + EFI_STATUS + PxeBcRegisterIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_IPv6_ADDRESS *Address ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_IPv6_ADDRESS *Address + ) + { +- EFI_IP6_PROTOCOL *Ip6; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- EFI_IP6_CONFIG_POLICY Policy; +- EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; +- EFI_IPv6_ADDRESS GatewayAddr; +- UINTN DataSize; +- EFI_EVENT MappedEvt; +- EFI_STATUS Status; +- BOOLEAN NoGateway; +- EFI_IPv6_ADDRESS *Ip6Addr; +- UINTN Index; +- +- Status = EFI_SUCCESS; +- MappedEvt = NULL; +- Ip6Addr = NULL; +- DataSize = sizeof (EFI_IP6_CONFIG_POLICY); +- Ip6Cfg = Private->Ip6Cfg; +- Ip6 = Private->Ip6; +- NoGateway = FALSE; ++ EFI_IP6_PROTOCOL *Ip6; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ EFI_IP6_CONFIG_POLICY Policy; ++ EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; ++ EFI_IPv6_ADDRESS GatewayAddr; ++ UINTN DataSize; ++ EFI_EVENT MappedEvt; ++ EFI_STATUS Status; ++ BOOLEAN NoGateway; ++ EFI_IPv6_ADDRESS *Ip6Addr; ++ UINTN Index; ++ ++ Status = EFI_SUCCESS; ++ MappedEvt = NULL; ++ Ip6Addr = NULL; ++ DataSize = sizeof (EFI_IP6_CONFIG_POLICY); ++ Ip6Cfg = Private->Ip6Cfg; ++ Ip6 = Private->Ip6; ++ NoGateway = FALSE; + + ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); + CopyMem (&CfgAddr.Address, Address, sizeof (EFI_IPv6_ADDRESS)); +@@ -1648,7 +1655,7 @@ PxeBcRegisterIp6Address ( + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypePolicy, +- sizeof(EFI_IP6_CONFIG_POLICY), ++ sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { +@@ -1674,22 +1681,22 @@ PxeBcRegisterIp6Address ( + } + + Private->IsAddressOk = FALSE; +- Status = Ip6Cfg->RegisterDataNotify ( +- Ip6Cfg, +- Ip6ConfigDataTypeManualAddress, +- MappedEvt +- ); +- if (EFI_ERROR(Status)) { ++ Status = Ip6Cfg->RegisterDataNotify ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeManualAddress, ++ MappedEvt ++ ); ++ if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, +- sizeof(EFI_IP6_CONFIG_MANUAL_ADDRESS), ++ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS), + &CfgAddr + ); +- if (EFI_ERROR(Status) && Status != EFI_NOT_READY) { ++ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + goto ON_EXIT; + } else if (Status == EFI_NOT_READY) { + // +@@ -1698,17 +1705,18 @@ PxeBcRegisterIp6Address ( + while (!Private->IsAddressOk) { + Ip6->Poll (Ip6); + } ++ + // + // Check whether the IP6 address setting is successed. + // + DataSize = 0; +- Status = Ip6Cfg->GetData ( +- Ip6Cfg, +- Ip6ConfigDataTypeManualAddress, +- &DataSize, +- NULL +- ); +- if (Status != EFI_BUFFER_TOO_SMALL || DataSize == 0) { ++ Status = Ip6Cfg->GetData ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeManualAddress, ++ &DataSize, ++ NULL ++ ); ++ if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) { + Status = EFI_DEVICE_ERROR; + goto ON_EXIT; + } +@@ -1717,11 +1725,12 @@ PxeBcRegisterIp6Address ( + if (Ip6Addr == NULL) { + return EFI_OUT_OF_RESOURCES; + } ++ + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, + &DataSize, +- (VOID*) Ip6Addr ++ (VOID *)Ip6Addr + ); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; +@@ -1733,6 +1742,7 @@ PxeBcRegisterIp6Address ( + break; + } + } ++ + if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) { + Status = EFI_ABORTED; + goto ON_EXIT; +@@ -1763,9 +1773,11 @@ ON_EXIT: + ); + gBS->CloseEvent (MappedEvt); + } ++ + if (Ip6Addr != NULL) { + FreePool (Ip6Addr); + } ++ + return Status; + } + +@@ -1780,16 +1792,16 @@ ON_EXIT: + **/ + EFI_STATUS + PxeBcSetIp6Policy ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- EFI_IP6_CONFIG_POLICY Policy; +- EFI_STATUS Status; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- UINTN DataSize; ++ EFI_IP6_CONFIG_POLICY Policy; ++ EFI_STATUS Status; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ UINTN DataSize; + +- Ip6Cfg = Private->Ip6Cfg; +- DataSize = sizeof (EFI_IP6_CONFIG_POLICY); ++ Ip6Cfg = Private->Ip6Cfg; ++ DataSize = sizeof (EFI_IP6_CONFIG_POLICY); + + // + // Get and store the current policy of IP6 driver. +@@ -1809,7 +1821,7 @@ PxeBcSetIp6Policy ( + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypePolicy, +- sizeof(EFI_IP6_CONFIG_POLICY), ++ sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { +@@ -1834,11 +1846,11 @@ PxeBcSetIp6Policy ( + **/ + EFI_STATUS + PxeBcSetIp6Address ( +- IN PXEBC_PRIVATE_DATA *Private ++ IN PXEBC_PRIVATE_DATA *Private + ) + { +- EFI_STATUS Status; +- EFI_DHCP6_PROTOCOL *Dhcp6; ++ EFI_STATUS Status; ++ EFI_DHCP6_PROTOCOL *Dhcp6; + + Dhcp6 = Private->Dhcp6; + +@@ -1885,47 +1897,48 @@ PxeBcSetIp6Address ( + EFI_STATUS + EFIAPI + PxeBcDhcp6CallBack ( +- IN EFI_DHCP6_PROTOCOL *This, +- IN VOID *Context, +- IN EFI_DHCP6_STATE CurrentState, +- IN EFI_DHCP6_EVENT Dhcp6Event, +- IN EFI_DHCP6_PACKET *Packet, +- OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL ++ IN EFI_DHCP6_PROTOCOL *This, ++ IN VOID *Context, ++ IN EFI_DHCP6_STATE CurrentState, ++ IN EFI_DHCP6_EVENT Dhcp6Event, ++ IN EFI_DHCP6_PACKET *Packet, ++ OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL + ) + { +- PXEBC_PRIVATE_DATA *Private; +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; +- EFI_DHCP6_PACKET *SelectAd; +- EFI_STATUS Status; +- BOOLEAN Received; ++ PXEBC_PRIVATE_DATA *Private; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; ++ EFI_DHCP6_PACKET *SelectAd; ++ EFI_STATUS Status; ++ BOOLEAN Received; + + if ((Dhcp6Event != Dhcp6RcvdAdvertise) && + (Dhcp6Event != Dhcp6SelectAdvertise) && + (Dhcp6Event != Dhcp6SendSolicit) && + (Dhcp6Event != Dhcp6SendRequest) && +- (Dhcp6Event != Dhcp6RcvdReply)) { ++ (Dhcp6Event != Dhcp6RcvdReply)) ++ { + return EFI_SUCCESS; + } + + ASSERT (Packet != NULL); + +- Private = (PXEBC_PRIVATE_DATA *) Context; +- Mode = Private->PxeBc.Mode; +- Callback = Private->PxeBcCallback; ++ Private = (PXEBC_PRIVATE_DATA *)Context; ++ Mode = Private->PxeBc.Mode; ++ Callback = Private->PxeBcCallback; + + // + // Callback to user when any traffic occurred if has. + // +- if (Dhcp6Event != Dhcp6SelectAdvertise && Callback != NULL) { +- Received = (BOOLEAN) (Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply); +- Status = Callback->Callback ( +- Callback, +- Private->Function, +- Received, +- Packet->Length, +- (EFI_PXE_BASE_CODE_PACKET *) &Packet->Dhcp6 +- ); ++ if ((Dhcp6Event != Dhcp6SelectAdvertise) && (Callback != NULL)) { ++ Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply); ++ Status = Callback->Callback ( ++ Callback, ++ Private->Function, ++ Received, ++ Packet->Length, ++ (EFI_PXE_BASE_CODE_PACKET *)&Packet->Dhcp6 ++ ); + if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + return EFI_ABORTED; + } +@@ -1934,108 +1947,114 @@ PxeBcDhcp6CallBack ( + Status = EFI_SUCCESS; + + switch (Dhcp6Event) { ++ case Dhcp6SendSolicit: ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // ++ Status = EFI_ABORTED; ++ break; ++ } + +- case Dhcp6SendSolicit: +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { + // +- // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // Record the first Solicate msg time + // +- Status = EFI_ABORTED; +- break; +- } +- +- // +- // Record the first Solicate msg time +- // +- if (Private->SolicitTimes == 0) { +- CalcElapsedTime (Private); +- Private->SolicitTimes++; +- } +- // +- // Cache the dhcp discover packet to mode data directly. +- // +- CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length); +- break; ++ if (Private->SolicitTimes == 0) { ++ CalcElapsedTime (Private); ++ Private->SolicitTimes++; ++ } + +- case Dhcp6RcvdAdvertise: +- Status = EFI_NOT_READY; +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { + // +- // Ignore the incoming packets which exceed the maximum length. ++ // Cache the dhcp discover packet to mode data directly. + // ++ CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length); + break; +- } +- if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { ++ ++ case Dhcp6RcvdAdvertise: ++ Status = EFI_NOT_READY; ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // Ignore the incoming packets which exceed the maximum length. ++ // ++ break; ++ } ++ ++ if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { ++ // ++ // Cache the dhcp offers to OfferBuffer[] for select later, and record ++ // the OfferIndex and OfferCount. ++ // ++ PxeBcCacheDhcp6Offer (Private, Packet); ++ } ++ ++ break; ++ ++ case Dhcp6SendRequest: ++ if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ // ++ // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // ++ Status = EFI_ABORTED; ++ break; ++ } ++ + // +- // Cache the dhcp offers to OfferBuffer[] for select later, and record +- // the OfferIndex and OfferCount. ++ // Store the request packet as seed packet for discover. + // +- PxeBcCacheDhcp6Offer (Private, Packet); +- } +- break; ++ if (Private->Dhcp6Request != NULL) { ++ FreePool (Private->Dhcp6Request); ++ } ++ ++ Private->Dhcp6Request = AllocateZeroPool (Packet->Size); ++ if (Private->Dhcp6Request != NULL) { ++ CopyMem (Private->Dhcp6Request, Packet, Packet->Size); ++ } ++ ++ break; + +- case Dhcp6SendRequest: +- if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) { ++ case Dhcp6SelectAdvertise: + // +- // If the to be sent packet exceeds the maximum length, abort the DHCP process. ++ // Select offer by the default policy or by order, and record the SelectIndex ++ // and SelectProxyType. + // +- Status = EFI_ABORTED; +- break; +- } ++ PxeBcSelectDhcp6Offer (Private); + +- // +- // Store the request packet as seed packet for discover. +- // +- if (Private->Dhcp6Request != NULL) { +- FreePool (Private->Dhcp6Request); +- } +- Private->Dhcp6Request = AllocateZeroPool (Packet->Size); +- if (Private->Dhcp6Request != NULL) { +- CopyMem (Private->Dhcp6Request, Packet, Packet->Size); +- } +- break; ++ if (Private->SelectIndex == 0) { ++ Status = EFI_ABORTED; ++ } else { ++ ASSERT (NewPacket != NULL); ++ SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; ++ *NewPacket = AllocateZeroPool (SelectAd->Size); ++ ASSERT (*NewPacket != NULL); ++ if (*NewPacket == NULL) { ++ return EFI_ABORTED; ++ } + +- case Dhcp6SelectAdvertise: +- // +- // Select offer by the default policy or by order, and record the SelectIndex +- // and SelectProxyType. +- // +- PxeBcSelectDhcp6Offer (Private); ++ CopyMem (*NewPacket, SelectAd, SelectAd->Size); ++ } + +- if (Private->SelectIndex == 0) { +- Status = EFI_ABORTED; +- } else { +- ASSERT (NewPacket != NULL); +- SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; +- *NewPacket = AllocateZeroPool (SelectAd->Size); +- ASSERT (*NewPacket != NULL); +- if (*NewPacket == NULL) { +- return EFI_ABORTED; ++ break; ++ ++ case Dhcp6RcvdReply: ++ // ++ // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data ++ // without verification. ++ // ++ ASSERT (Private->SelectIndex != 0); ++ Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE); ++ if (EFI_ERROR (Status)) { ++ Status = EFI_ABORTED; + } +- CopyMem (*NewPacket, SelectAd, SelectAd->Size); +- } +- break; + +- case Dhcp6RcvdReply: +- // +- // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data +- // without verification. +- // +- ASSERT (Private->SelectIndex != 0); +- Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE); +- if (EFI_ERROR (Status)) { +- Status = EFI_ABORTED; +- } +- break; ++ break; + +- default: +- ASSERT (0); ++ default: ++ ASSERT (0); + } + + return Status; + } + +- + /** + Build and send out the request packet for the bootfile, and parse the reply. + +@@ -2053,37 +2072,37 @@ PxeBcDhcp6CallBack ( + **/ + EFI_STATUS + PxeBcDhcp6Discover ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN UINT16 Type, +- IN UINT16 *Layer, +- IN BOOLEAN UseBis, +- IN EFI_IP_ADDRESS *DestIp ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT16 Type, ++ IN UINT16 *Layer, ++ IN BOOLEAN UseBis, ++ IN EFI_IP_ADDRESS *DestIp + ) + { +- EFI_PXE_BASE_CODE_UDP_PORT SrcPort; +- EFI_PXE_BASE_CODE_UDP_PORT DestPort; +- EFI_PXE_BASE_CODE_MODE *Mode; +- EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; +- EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; +- UINTN DiscoverLen; +- EFI_DHCP6_PACKET *Request; +- UINTN RequestLen; +- EFI_DHCP6_PACKET *Reply; +- UINT8 *RequestOpt; +- UINT8 *DiscoverOpt; +- UINTN ReadSize; +- UINT16 OpCode; +- UINT16 OpLen; +- UINT32 Xid; +- EFI_STATUS Status; +- +- PxeBc = &Private->PxeBc; +- Mode = PxeBc->Mode; +- Request = Private->Dhcp6Request; +- SrcPort = PXEBC_BS_DISCOVER_PORT; +- DestPort = PXEBC_BS_DISCOVER_PORT; +- +- if (!UseBis && Layer != NULL) { ++ EFI_PXE_BASE_CODE_UDP_PORT SrcPort; ++ EFI_PXE_BASE_CODE_UDP_PORT DestPort; ++ EFI_PXE_BASE_CODE_MODE *Mode; ++ EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; ++ EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover; ++ UINTN DiscoverLen; ++ EFI_DHCP6_PACKET *Request; ++ UINTN RequestLen; ++ EFI_DHCP6_PACKET *Reply; ++ UINT8 *RequestOpt; ++ UINT8 *DiscoverOpt; ++ UINTN ReadSize; ++ UINT16 OpCode; ++ UINT16 OpLen; ++ UINT32 Xid; ++ EFI_STATUS Status; ++ ++ PxeBc = &Private->PxeBc; ++ Mode = PxeBc->Mode; ++ Request = Private->Dhcp6Request; ++ SrcPort = PXEBC_BS_DISCOVER_PORT; ++ DestPort = PXEBC_BS_DISCOVER_PORT; ++ ++ if (!UseBis && (Layer != NULL)) { + *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK; + } + +@@ -2108,10 +2127,11 @@ PxeBcDhcp6Discover ( + RequestLen = DiscoverLen; + + while (RequestLen < Request->Length) { +- OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode); +- OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen); +- if (OpCode != EFI_DHCP6_IA_TYPE_NA && +- OpCode != EFI_DHCP6_IA_TYPE_TA) { ++ OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode); ++ OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen); ++ if ((OpCode != EFI_DHCP6_IA_TYPE_NA) && ++ (OpCode != EFI_DHCP6_IA_TYPE_TA)) ++ { + // + // Copy all the options except IA option. + // +@@ -2119,6 +2139,7 @@ PxeBcDhcp6Discover ( + DiscoverOpt += (OpLen + 4); + DiscoverLen += (OpLen + 4); + } ++ + RequestOpt += (OpLen + 4); + RequestLen += (OpLen + 4); + } +@@ -2134,7 +2155,7 @@ PxeBcDhcp6Discover ( + NULL, + NULL, + &DiscoverLen, +- (VOID *) Discover ++ (VOID *)Discover + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; +@@ -2150,7 +2171,8 @@ PxeBcDhcp6Discover ( + } else { + Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer; + } +- ReadSize = (UINTN) Reply->Size; ++ ++ ReadSize = (UINTN)Reply->Size; + + // + // Start Udp6Read instance +@@ -2170,7 +2192,7 @@ PxeBcDhcp6Discover ( + NULL, + NULL, + &ReadSize, +- (VOID *) &Reply->Dhcp6 ++ (VOID *)&Reply->Dhcp6 + ); + // + // Stop Udp6Read instance +@@ -2190,7 +2212,6 @@ ON_ERROR: + return Status; + } + +- + /** + Start the DHCPv6 S.A.R.R. process to acquire the IPv6 address and other PXE boot information. + +@@ -2203,35 +2224,35 @@ ON_ERROR: + **/ + EFI_STATUS + PxeBcDhcp6Sarr ( +- IN PXEBC_PRIVATE_DATA *Private, +- IN EFI_DHCP6_PROTOCOL *Dhcp6 ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN EFI_DHCP6_PROTOCOL *Dhcp6 + ) + { +- EFI_PXE_BASE_CODE_MODE *PxeMode; +- EFI_DHCP6_CONFIG_DATA Config; +- EFI_DHCP6_MODE_DATA Mode; +- EFI_DHCP6_RETRANSMISSION *Retransmit; +- EFI_DHCP6_PACKET_OPTION *OptList[PXEBC_DHCP6_OPTION_MAX_NUM]; +- UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE]; +- UINT32 OptCount; +- EFI_STATUS Status; +- EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; +- EFI_STATUS TimerStatus; +- EFI_EVENT Timer; +- UINT64 GetMappingTimeOut; +- UINTN DataSize; +- EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; +- +- Status = EFI_SUCCESS; +- PxeMode = Private->PxeBc.Mode; +- Ip6Cfg = Private->Ip6Cfg; +- Timer = NULL; ++ EFI_PXE_BASE_CODE_MODE *PxeMode; ++ EFI_DHCP6_CONFIG_DATA Config; ++ EFI_DHCP6_MODE_DATA Mode; ++ EFI_DHCP6_RETRANSMISSION *Retransmit; ++ EFI_DHCP6_PACKET_OPTION *OptList[PXEBC_DHCP6_OPTION_MAX_NUM]; ++ UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE]; ++ UINT32 OptCount; ++ EFI_STATUS Status; ++ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; ++ EFI_STATUS TimerStatus; ++ EFI_EVENT Timer; ++ UINT64 GetMappingTimeOut; ++ UINTN DataSize; ++ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; ++ ++ Status = EFI_SUCCESS; ++ PxeMode = Private->PxeBc.Mode; ++ Ip6Cfg = Private->Ip6Cfg; ++ Timer = NULL; + + // + // Build option list for the request packet. + // +- OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer); +- ASSERT (OptCount> 0); ++ OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer); ++ ASSERT (OptCount > 0); + + Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION)); + if (Retransmit == NULL) { +@@ -2274,7 +2295,6 @@ PxeBcDhcp6Sarr ( + ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); + ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); + +- + // + // Start DHCPv6 S.A.R.R. process to acquire IPv6 address. + // +@@ -2290,12 +2310,12 @@ PxeBcDhcp6Sarr ( + // Get Duplicate Address Detection Transmits count. + // + DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); +- Status = Ip6Cfg->GetData ( +- Ip6Cfg, +- Ip6ConfigDataTypeDupAddrDetectTransmits, +- &DataSize, +- &DadXmits +- ); ++ Status = Ip6Cfg->GetData ( ++ Ip6Cfg, ++ Ip6ConfigDataTypeDupAddrDetectTransmits, ++ &DataSize, ++ &DadXmits ++ ); + if (EFI_ERROR (Status)) { + Dhcp6->Configure (Dhcp6, NULL); + return Status; +@@ -2308,7 +2328,7 @@ PxeBcDhcp6Sarr ( + } + + GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY; +- Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut); ++ Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Timer); + Dhcp6->Configure (Dhcp6, NULL); +@@ -2316,7 +2336,6 @@ PxeBcDhcp6Sarr ( + } + + do { +- + TimerStatus = gBS->CheckEvent (Timer); + if (!EFI_ERROR (TimerStatus)) { + Status = Dhcp6->Start (Dhcp6); +@@ -2325,10 +2344,12 @@ PxeBcDhcp6Sarr ( + + gBS->CloseEvent (Timer); + } ++ + if (EFI_ERROR (Status)) { + if (Status == EFI_ICMP_ERROR) { + PxeMode->IcmpErrorReceived = TRUE; + } ++ + Dhcp6->Configure (Dhcp6, NULL); + return Status; + } +@@ -2354,9 +2375,11 @@ PxeBcDhcp6Sarr ( + if (Mode.ClientId != NULL) { + FreePool (Mode.ClientId); + } ++ + if (Mode.Ia != NULL) { + FreePool (Mode.Ia); + } ++ + // + // Check the selected offer whether BINL retry is needed. + // +-- +2.41.0 + diff --git a/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch new file mode 100644 index 0000000..13da096 --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch @@ -0,0 +1,1644 @@ +From b77856122fdf9928a44a2d2715c67d629fdcd647 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 1/3] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 51: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21993 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [1/3] fd847768217905003d065a542a020985c976b7ab (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21993 +CVE: CVE-2023-45230 +Upstream: Merged +Conflicts: Only whitespace issues caused by the 'uncrustify' tool. + +commit f31453e8d6542461d92d835e0b79fec8b039174d +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:43 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535 + + Bug Details: + PixieFail Bug #2 + CVE-2023-45230 + CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H + CWE-119 Improper Restriction of Operations within the Bounds + of a Memory Buffer + + Changes Overview: + > -UINT8 * + > +EFI_STATUS + > Dhcp6AppendOption ( + > - IN OUT UINT8 *Buf, + > - IN UINT16 OptType, + > - IN UINT16 OptLen, + > - IN UINT8 *Data + > + IN OUT EFI_DHCP6_PACKET *Packet, + > + IN OUT UINT8 **PacketCursor, + > + IN UINT16 OptType, + > + IN UINT16 OptLen, + > + IN UINT8 *Data + > ); + + Dhcp6AppendOption() and variants can return errors now. All callsites + are adapted accordingly. + + It gets passed in EFI_DHCP6_PACKET as additional parameter ... + + > + // + > + // Verify the PacketCursor is within the packet + > + // + > + if ( (*PacketCursor < Packet->Dhcp6.Option) + > + || (*PacketCursor >= Packet->Dhcp6.Option + + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) + > + { + > + return EFI_INVALID_PARAMETER; + > + } + + ... so it can look at Packet->Size when checking buffer space. + Also to allow Packet->Length updates. + + Lots of checks added. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 49 +++- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 409 +++++++++++++++++++---------- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 382 +++++++++++++++++++++------ + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 82 +++--- + 4 files changed, 676 insertions(+), 246 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +index f88b00ad04..ec0ed5d8f5 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +@@ -47,9 +47,52 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE; + #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S') + #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I') + +-#define DHCP6_PACKET_ALL 0 +-#define DHCP6_PACKET_STATEFUL 1 +-#define DHCP6_PACKET_STATELESS 2 ++// ++// For more information on DHCP options see RFC 8415, Section 21.1 ++// ++// The format of DHCP options is: ++// ++// 0 1 2 3 ++// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | option-code | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | option-data | ++// | (option-len octets) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16)) ++#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16)) ++ ++// ++// Combined size of Code and Length ++// ++#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \ ++ DHCP6_SIZE_OF_OPT_LEN) ++ ++STATIC_ASSERT ( ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4, ++ "Combined size of Code and Length must be 4 per RFC 8415" ++ ); ++ ++// ++// Offset to the length is just past the code ++// ++#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE) ++STATIC_ASSERT ( ++ DHCP6_OPT_LEN_OFFSET (0) == 2, ++ "Offset of length is + 2 past start of option" ++ ); ++ ++#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) ++STATIC_ASSERT ( ++ DHCP6_OPT_DATA_OFFSET (0) == 4, ++ "Offset to option data should be +4 from start of option" ++ ); ++ ++#define DHCP6_PACKET_ALL 0 ++#define DHCP6_PACKET_STATEFUL 1 ++#define DHCP6_PACKET_STATELESS 2 + + #define DHCP6_BASE_PACKET_SIZE 1024 + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index c20876d5a5..2976684aba 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -3,9 +3,9 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent +- + **/ + + #include "Dhcp6Impl.h" +@@ -946,7 +946,8 @@ Dhcp6SendSolicitMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -960,26 +961,38 @@ Dhcp6SendSolicitMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -987,28 +1000,26 @@ Dhcp6SendSolicitMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1022,10 +1033,8 @@ Dhcp6SendSolicitMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1037,6 +1046,14 @@ Dhcp6SendSolicitMsg ( + Elapsed, + Instance->Config->SolicitRetransmission + ); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + /** +@@ -1128,7 +1145,8 @@ Dhcp6SendRequestMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1142,33 +1160,49 @@ Dhcp6SendRequestMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -1176,18 +1210,18 @@ Dhcp6SendRequestMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1196,8 +1230,7 @@ Dhcp6SendRequestMsg ( + Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet); + + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1213,14 +1246,21 @@ Dhcp6SendRequestMsg ( + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); + + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1286,7 +1326,8 @@ Dhcp6SendDeclineMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE; +@@ -1300,42 +1341,58 @@ Dhcp6SendDeclineMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType); ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, ++ DecIa, ++ 0, ++ 0, ++ Packet->Dhcp6.Header.MessageType ++ ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1349,16 +1406,22 @@ Dhcp6SendDeclineMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1420,7 +1483,8 @@ Dhcp6SendReleaseMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE; +@@ -1434,45 +1498,61 @@ Dhcp6SendReleaseMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // ServerId is extracted from packet, it's network order. + // +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType); ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, ++ RelIa, ++ 0, ++ 0, ++ Packet->Dhcp6.Header.MessageType ++ ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- // +- // Determine the size/length of packet +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1482,16 +1562,22 @@ Dhcp6SendReleaseMsg ( + Instance->IaCb.Ia->State = Dhcp6Releasing; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1551,7 +1637,8 @@ Dhcp6SendRenewRebindMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1565,26 +1652,38 @@ Dhcp6SendRenewRebindMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + if (!RebindRequest) { + // +@@ -1600,18 +1699,22 @@ Dhcp6SendRenewRebindMsg ( + Dhcp6OptServerId + ); + if (Option == NULL) { +- FreePool (Packet); +- return EFI_DEVICE_ERROR; ++ Status = EFI_DEVICE_ERROR; ++ goto ON_ERROR; + } + + ServerId = (EFI_DHCP6_DUID *) (Option + 2); + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptServerId), + ServerId->Length, + ServerId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + + // +@@ -1620,18 +1723,18 @@ Dhcp6SendRenewRebindMsg ( + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1641,10 +1744,8 @@ Dhcp6SendRenewRebindMsg ( + Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; + + Status = Dhcp6CallbackUser (Instance, Event, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1661,16 +1762,22 @@ Dhcp6SendRenewRebindMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + /** +@@ -1834,7 +1941,8 @@ Dhcp6SendInfoRequestMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1851,26 +1959,38 @@ Dhcp6SendInfoRequestMsg ( + + if (SendClientId) { + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + OptionRequest->OpCode, + OptionRequest->OpLen, + OptionRequest->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. +@@ -1878,18 +1998,18 @@ Dhcp6SendInfoRequestMsg ( + for (Index = 0; Index < OptionCount; Index++) { + + UserOpt = OptionList[Index]; +- Cursor = Dhcp6AppendOption( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // +@@ -1901,16 +2021,22 @@ Dhcp6SendInfoRequestMsg ( + // Send info-request packet with no state. + // + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +@@ -1962,7 +2088,8 @@ Dhcp6SendConfirmMsg ( + // + Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); + if (Packet == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; + } + + Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; +@@ -1976,54 +2103,64 @@ Dhcp6SendConfirmMsg ( + Cursor = Packet->Dhcp6.Option; + + Length = HTONS (ClientId->Length); +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + HTONS (Dhcp6OptClientId), + Length, + ClientId->Duid + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendETOption ( +- Cursor, ++ Status = Dhcp6AppendETOption ( ++ Packet, ++ &Cursor, + Instance, + &Elapsed + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + +- Cursor = Dhcp6AppendIaOption ( +- Cursor, ++ Status = Dhcp6AppendIaOption ( ++ Packet, ++ &Cursor, + Instance->IaCb.Ia, + Instance->IaCb.T1, + Instance->IaCb.T2, + Packet->Dhcp6.Header.MessageType + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + + // + // Append user-defined when configurate Dhcp6 service. + // + for (Index = 0; Index < Instance->Config->OptionCount; Index++) { + UserOpt = Instance->Config->OptionList[Index]; +- Cursor = Dhcp6AppendOption ( +- Cursor, ++ Status = Dhcp6AppendOption ( ++ Packet, ++ &Cursor, + UserOpt->OpCode, + UserOpt->OpLen, + UserOpt->Data + ); ++ if (EFI_ERROR (Status)) { ++ goto ON_ERROR; ++ } + } + +- // +- // Determine the size/length of packet. +- // +- Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option); + ASSERT (Packet->Size > Packet->Length + 8); + + // + // Callback to user with the packet to be sent and check the user's feedback. + // + Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -2037,16 +2174,22 @@ Dhcp6SendConfirmMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // + // Enqueue the sent packet for the retransmission in case reply timeout. + // + return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index d249a1cca7..484c360a96 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -601,24 +601,33 @@ Dhcp6OnTransmitted ( + + + /** +- Append the option to Buf, and move Buf to the end. ++ Append the option to Buf, update the length of packet, and move Buf to the end. + +- @param[in, out] Buf The pointer to the buffer. +- @param[in] OptType The option type. +- @param[in] OptLen The length of option contents. +- @param[in] Data The pointer to the option content. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. ++ @param[in] OptType The option type. ++ @param[in] OptLen The length of option contents. ++ @param[in] Data The pointer to the option content. + +- @return Buf The position to append the next option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendOption ( +- IN OUT UINT8 *Buf, +- IN UINT16 OptType, +- IN UINT16 OptLen, +- IN UINT8 *Data ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN UINT16 OptType, ++ IN UINT16 OptLen, ++ IN UINT8 *Data + ) + { ++ UINT32 Length; ++ UINT32 BytesNeeded; ++ + // + // The format of Dhcp6 option: + // +@@ -631,35 +640,94 @@ Dhcp6AppendOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + +- ASSERT (OptLen != 0); ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Data == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (OptLen == 0) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Calculate the bytes needed for the option ++ // ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS (OptLen); ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; ++ CopyMem (*PacketCursor, Data, NTOHS (OptLen)); ++ *PacketCursor += NTOHS (OptLen); + +- WriteUnaligned16 ((UINT16 *) Buf, OptType); +- Buf += 2; +- WriteUnaligned16 ((UINT16 *) Buf, OptLen); +- Buf += 2; +- CopyMem (Buf, Data, NTOHS (OptLen)); +- Buf += NTOHS (OptLen); ++ // Update the packet length by the length of the option + 4 bytes ++ Packet->Length += BytesNeeded; + +- return Buf; ++ return EFI_SUCCESS; + } + + /** + Append the appointed IA Address option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] IaAddr The pointer to the IA Address. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaAddrOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA_ADDRESS *IaAddr, +- IN UINT32 MessageType +-) ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA_ADDRESS *IaAddr, ++ IN UINT32 MessageType ++ ) + { ++ UINT32 BytesNeeded; ++ UINT32 Length; + + // The format of the IA Address option is: + // +@@ -682,17 +750,60 @@ Dhcp6AppendIaAddrOption ( + // . . + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (IaAddr == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ BytesNeeded += sizeof (EFI_IPv6_ADDRESS); ++ // ++ // Even if the preferred-lifetime is 0, it still needs to store it. ++ // ++ BytesNeeded += sizeof (IaAddr->PreferredLifetime); ++ // ++ // Even if the valid-lifetime is 0, it still needs to store it. ++ // ++ BytesNeeded += sizeof (IaAddr->ValidLifetime); ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of Ia Address option type + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptIaAddr)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS))); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS))); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + +- CopyMem (Buf, &IaAddr->IpAddress, sizeof(EFI_IPv6_ADDRESS)); +- Buf += sizeof(EFI_IPv6_ADDRESS); ++ CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS)); ++ *PacketCursor += sizeof (EFI_IPv6_ADDRESS); + + // + // Fill the value of preferred-lifetime and valid-lifetime. +@@ -700,43 +811,59 @@ Dhcp6AppendIaAddrOption ( + // should set to 0 when initiate a Confirm message. + // + if (MessageType != Dhcp6MsgConfirm) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->PreferredLifetime)); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime)); + } +- Buf += 4; ++ ++ *PacketCursor += sizeof (IaAddr->PreferredLifetime); + + if (MessageType != Dhcp6MsgConfirm) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (IaAddr->ValidLifetime)); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime)); + } +- Buf += 4; + +- return Buf; ++ *PacketCursor += sizeof (IaAddr->ValidLifetime); ++ ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; ++ ++ return EFI_SUCCESS; + } + + + /** + Append the appointed Ia option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Ia The pointer to the Ia. + @param[in] T1 The time of T1. + @param[in] T2 The time of T2. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA *Ia, +- IN UINT32 T1, +- IN UINT32 T2, +- IN UINT32 MessageType ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA *Ia, ++ IN UINT32 T1, ++ IN UINT32 T2, ++ IN UINT32 MessageType + ) + { +- UINT8 *AddrOpt; +- UINT16 *Len; +- UINTN Index; ++ UINT8 *AddrOpt; ++ UINT16 *Len; ++ UINTN Index; ++ UINT32 BytesNeeded; ++ UINT32 Length; ++ EFI_STATUS Status; + + // + // The format of IA_NA and IA_TA option: +@@ -757,68 +884,126 @@ Dhcp6AppendIaOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Ia == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ BytesNeeded += sizeof (Ia->Descriptor.IaId); ++ // ++ // + N for the IA_NA-options/IA_TA-options ++ // Dhcp6AppendIaAddrOption will need to check the length for each address ++ // ++ if (Ia->Descriptor.Type == Dhcp6OptIana) { ++ BytesNeeded += sizeof (T1) + sizeof (T2); ++ } ++ ++ // ++ // Space remaining in the packet ++ // ++ Length = (UINT16)(Packet->Size - Packet->Length); ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of Ia option type + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Ia->Descriptor.Type)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + + // + // Fill the len of Ia option later, keep the pointer first + // +- Len = (UINT16 *) Buf; +- Buf += 2; ++ Len = (UINT16 *)*PacketCursor; ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + + // + // Fill the value of iaid + // +- WriteUnaligned32 ((UINT32 *) Buf, HTONL (Ia->Descriptor.IaId)); +- Buf += 4; ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId)); ++ *PacketCursor += sizeof (Ia->Descriptor.IaId); + + // + // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified. + // + if (Ia->Descriptor.Type == Dhcp6OptIana) { +- WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff)); +- Buf += 4; +- WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff)); +- Buf += 4; ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff)); ++ *PacketCursor += sizeof (T1); ++ WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff)); ++ *PacketCursor += sizeof (T2); + } + + // + // Fill all the addresses belong to the Ia + // + for (Index = 0; Index < Ia->IaAddressCount; Index++) { +- AddrOpt = (UINT8 *) Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS); +- Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *) AddrOpt, MessageType); ++ AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS); ++ Status = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } + } + + // + // Fill the value of Ia option length + // +- *Len = HTONS ((UINT16) (Buf - (UINT8 *) Len - 2)); ++ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); ++ ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; + +- return Buf; ++ return EFI_SUCCESS; + } + + /** + Append the appointed Elapsed time option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Instance The pointer to the Dhcp6 instance. + @param[out] Elapsed The pointer to the elapsed time value in +- the generated packet. ++ the generated packet. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendETOption ( +- IN OUT UINT8 *Buf, +- IN DHCP6_INSTANCE *Instance, +- OUT UINT16 **Elapsed ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN DHCP6_INSTANCE *Instance, ++ OUT UINT16 **Elapsed + ) + { ++ UINT32 BytesNeeded; ++ UINT32 Length; ++ + // + // The format of elapsed time option: + // +@@ -830,27 +1015,70 @@ Dhcp6AppendETOption ( + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // + ++ // ++ // Verify the arguments are valid ++ // ++ if (Packet == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((PacketCursor == NULL) || (*PacketCursor == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Instance == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if ((Elapsed == NULL)) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ // ++ // Verify the PacketCursor is within the packet ++ // ++ if ( (*PacketCursor < Packet->Dhcp6.Option) ++ || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) ++ { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN; ++ // ++ // + 2 for elapsed-time ++ // ++ BytesNeeded += sizeof (UINT16); ++ // ++ // Space remaining in the packet ++ // ++ Length = Packet->Size - Packet->Length; ++ if (Length < BytesNeeded) { ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ + // + // Fill the value of elapsed-time option type. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptElapsedTime)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_CODE; + + // + // Fill the len of elapsed-time option, which is fixed. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS(2)); +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2)); ++ *PacketCursor += DHCP6_SIZE_OF_OPT_LEN; + + // + // Fill in elapsed time value with 0 value for now. The actual value is + // filled in later just before the packet is transmitted. + // +- WriteUnaligned16 ((UINT16 *) Buf, HTONS(0)); +- *Elapsed = (UINT16 *) Buf; +- Buf += 2; ++ WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0)); ++ *Elapsed = (UINT16 *)*PacketCursor; ++ *PacketCursor += sizeof (UINT16); + +- return Buf; ++ Packet->Length += BytesNeeded; ++ ++ return EFI_SUCCESS; + } + + /** +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +index 2f18eb3609..af68f77e8b 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +@@ -161,69 +161,85 @@ Dhcp6OnTransmitted ( + ); + + /** +- Append the appointed option to the buf, and move the buf to the end. +- +- @param[in, out] Buf The pointer to buffer. +- @param[in] OptType The option type. +- @param[in] OptLen The length of option content.s +- @param[in] Data The pointer to the option content. +- +- @return Buf The position to append the next option. +- ++ Append the option to Buf, update the length of packet, and move Buf to the end. ++ ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. ++ @param[in] OptType The option type. ++ @param[in] OptLen The length of option contents. ++ @param[in] Data The pointer to the option content. ++ ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendOption ( +- IN OUT UINT8 *Buf, +- IN UINT16 OptType, +- IN UINT16 OptLen, +- IN UINT8 *Data ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN UINT16 OptType, ++ IN UINT16 OptLen, ++ IN UINT8 *Data + ); + + /** +- Append the Ia option to Buf, and move Buf to the end. +- +- @param[in, out] Buf The pointer to the position to append. ++ Append the appointed Ia option to Buf, update the Ia option length, and move Buf ++ to the end of the option. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ will be updated. ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Ia The pointer to the Ia. + @param[in] T1 The time of T1. + @param[in] T2 The time of T2. + @param[in] MessageType Message type of DHCP6 package. + +- @return Buf The position to append the next Ia option. +- ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendIaOption ( +- IN OUT UINT8 *Buf, +- IN EFI_DHCP6_IA *Ia, +- IN UINT32 T1, +- IN UINT32 T2, +- IN UINT32 MessageType ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN EFI_DHCP6_IA *Ia, ++ IN UINT32 T1, ++ IN UINT32 T2, ++ IN UINT32 MessageType + ); + + /** + Append the appointed Elapsed time option to Buf, and move Buf to the end. + +- @param[in, out] Buf The pointer to the position to append. ++ @param[in, out] Packet A pointer to the packet, on success Packet->Length ++ @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor ++ will be moved to the end of the option. + @param[in] Instance The pointer to the Dhcp6 instance. + @param[out] Elapsed The pointer to the elapsed time value in + the generated packet. + +- @return Buf The position to append the next Ia option. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + + **/ +-UINT8 * ++EFI_STATUS + Dhcp6AppendETOption ( +- IN OUT UINT8 *Buf, +- IN DHCP6_INSTANCE *Instance, +- OUT UINT16 **Elapsed ++ IN OUT EFI_DHCP6_PACKET *Packet, ++ IN OUT UINT8 **PacketCursor, ++ IN DHCP6_INSTANCE *Instance, ++ OUT UINT16 **Elapsed + ); + + /** + Set the elapsed time based on the given instance and the pointer to the + elapsed time option. + +- @param[in] Elapsed The pointer to the position to append. +- @param[in] Instance The pointer to the Dhcp6 instance. ++ @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid ++ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option. ++ @retval EFI_SUCCESS The option is appended successfully. + **/ + VOID + SetElapsedTime ( +-- +2.41.0 + diff --git a/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch new file mode 100644 index 0000000..ccef9e0 --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch @@ -0,0 +1,630 @@ +From 6156d5f9f05f5620e8bcdd9e0d641d85db031e67 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 3/3] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit + Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 51: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21993 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [3/3] fce1c72df05d0e611aa2dc0203bae058bb0a0868 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-21993 +CVE: CVE-2023-45230 +Upstream: Merged + +commit 5f3658197bf29c83b3349b0ab1d99cdb0c3814bc +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:45 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535 + + Confirms that reported issue... + + "Buffer overflow in the DHCPv6 client via a long Server ID option" + + ..has been corrected by the provided patch. + + Tests the following functions to ensure they appropriately handle + untrusted data (either too long or too small) to prevent a buffer + overflow: + + Dhcp6AppendOption + Dhcp6AppendETOption + Dhcp6AppendIaOption + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../GoogleTest/Dhcp6DxeGoogleTest.cpp | 20 + + .../GoogleTest/Dhcp6DxeGoogleTest.inf | 43 ++ + .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++ + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + 4 files changed, 542 insertions(+) + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp + +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp +new file mode 100644 +index 0000000000..9aeced2f91 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp +@@ -0,0 +1,20 @@ ++/** @file ++ Acts as the main entry point for the tests for the Dhcp6Dxe module. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Run the tests ++//////////////////////////////////////////////////////////////////////////////// ++int ++main ( ++ int argc, ++ char *argv[] ++ ) ++{ ++ testing::InitGoogleTest (&argc, argv); ++ return RUN_ALL_TESTS (); ++} +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +new file mode 100644 +index 0000000000..8e9119a371 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +@@ -0,0 +1,43 @@ ++## @file ++# Unit test suite for the Dhcp6Dxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++ INF_VERSION = 0x00010017 ++ BASE_NAME = Dhcp6DxeGoogleTest ++ FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9 ++ VERSION_STRING = 1.0 ++ MODULE_TYPE = HOST_APPLICATION ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 AARCH64 ++# ++[Sources] ++ Dhcp6DxeGoogleTest.cpp ++ Dhcp6IoGoogleTest.cpp ++ ../Dhcp6Io.c ++ ../Dhcp6Utility.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ NetworkPkg/NetworkPkg.dec ++ ++[LibraryClasses] ++ GoogleTestLib ++ DebugLib ++ NetLib ++ PcdLib ++ ++[Protocols] ++ gEfiDhcp6ServiceBindingProtocolGuid ++ ++[Pcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType ++ ++[Guids] ++ gZeroGuid +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +new file mode 100644 +index 0000000000..7ee40e4af4 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +@@ -0,0 +1,478 @@ ++/** @file ++ Tests for Dhcp6Io.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include ++ #include "../Dhcp6Impl.h" ++ #include "../Dhcp6Utility.h" ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Defines ++//////////////////////////////////////////////////////////////////////// ++ ++#define DHCP6_PACKET_MAX_LEN 1500 ++ ++//////////////////////////////////////////////////////////////////////// ++//////////////////////////////////////////////////////////////////////// ++// Symbol Definitions ++// These functions are not directly under test - but required to compile ++//////////////////////////////////////////////////////////////////////// ++ ++// This definition is used by this test but is also required to compile ++// by Dhcp6Io.c ++EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = { ++ { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 } ++}; ++ ++EFI_STATUS ++EFIAPI ++UdpIoSendDatagram ( ++ IN UDP_IO *UdpIo, ++ IN NET_BUF *Packet, ++ IN UDP_END_POINT *EndPoint OPTIONAL, ++ IN EFI_IP_ADDRESS *Gateway OPTIONAL, ++ IN UDP_IO_CALLBACK CallBack, ++ IN VOID *Context ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++EFIAPI ++UdpIoRecvDatagram ( ++ IN UDP_IO *UdpIo, ++ IN UDP_IO_CALLBACK CallBack, ++ IN VOID *Context, ++ IN UINT32 HeadLen ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendOptionTest Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that is too small by a duid that is too large ++TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_DHCP6_DUID *UntrustedDuid; ++ EFI_STATUS Status; ++ ++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID)); ++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL); ++ ++ UntrustedDuid->Length = NTOHS (0xFFFF); ++ ++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendOption ( ++ Dhcp6AppendOptionTest::Packet, ++ &Cursor, ++ HTONS (Dhcp6OptServerId), ++ UntrustedDuid->Length, ++ UntrustedDuid->Duid ++ ); ++ ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that is large enough ++TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_DHCP6_DUID *UntrustedDuid; ++ EFI_STATUS Status; ++ UINTN OriginalLength; ++ ++ UINT8 Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID)); ++ ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL); ++ ++ UntrustedDuid->Length = NTOHS (sizeof (Duid)); ++ CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid)); ++ ++ Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendOption ( ++ Dhcp6AppendOptionTest::Packet, ++ &Cursor, ++ HTONS (Dhcp6OptServerId), ++ UntrustedDuid->Length, ++ UntrustedDuid->Duid ++ ); ++ ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4); ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendETOption Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendETOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that is too small by a duid that is too large ++TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ DHCP6_INSTANCE Instance; ++ UINT16 ElapsedTimeVal; ++ UINT16 *ElapsedTime; ++ ++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option; ++ ElapsedTime = &ElapsedTimeVal; ++ ++ Packet->Length = Packet->Size - 2; ++ ++ Status = Dhcp6AppendETOption ( ++ Dhcp6AppendETOptionTest::Packet, ++ &Cursor, ++ &Instance, // Instance is not used in this function ++ &ElapsedTime ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that is large enough ++TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ DHCP6_INSTANCE Instance; ++ UINT16 ElapsedTimeVal; ++ UINT16 *ElapsedTime; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option; ++ ElapsedTime = &ElapsedTimeVal; ++ ExpectedSize = 6; ++ OriginalLength = Packet->Length; ++ ++ Status = Dhcp6AppendETOption ( ++ Dhcp6AppendETOptionTest::Packet, ++ &Cursor, ++ &Instance, // Instance is not used in this function ++ &ElapsedTime ++ ); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6AppendIaOption Tests ++//////////////////////////////////////////////////////////////////////// ++ ++class Dhcp6AppendIaOptionTest : public ::testing::Test { ++public: ++ UINT8 *Buffer = NULL; ++ EFI_DHCP6_PACKET *Packet; ++ EFI_DHCP6_IA *Ia; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN); ++ ASSERT_NE (Buffer, (UINT8 *)NULL); ++ ++ Packet = (EFI_DHCP6_PACKET *)Buffer; ++ Packet->Size = DHCP6_PACKET_MAX_LEN; ++ ++ Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2); ++ ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL); ++ ++ CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS)); ++ CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS)); ++ ++ Ia->IaAddressCount = 2; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ if (Buffer != NULL) { ++ FreePool (Buffer); ++ } ++ ++ if (Ia != NULL) { ++ FreePool (Ia); ++ } ++ } ++}; ++ ++// Test Description: ++// Attempt to append an option to a packet that doesn't have enough space ++// for the option header ++TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ ++ Packet->Length = Packet->Size - 2; ++ ++ Ia->Descriptor.Type = Dhcp6OptIana; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0x12345678, ++ 0x11111111, ++ Dhcp6OptIana ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++// Test Description: ++// Attempt to append an option to a packet that doesn't have enough space ++// for the option header ++TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ ++ // Use up nearly all the space in the packet ++ Packet->Length = Packet->Size - 2; ++ ++ Ia->Descriptor.Type = Dhcp6OptIata; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0, ++ 0, ++ Dhcp6OptIata ++ ); ++ ++ // verify that we error out because the packet is too small for the option header ++ ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL); ++ ++ // reset the length ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++} ++ ++TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ // ++ // 2 bytes for the option header type ++ // ++ ExpectedSize = 2; ++ // ++ // 2 bytes for the option header length ++ // ++ ExpectedSize += 2; ++ // ++ // 4 bytes for the IAID ++ // ++ ExpectedSize += 4; ++ // ++ // + 4 bytes for the T1 ++ // ++ ExpectedSize += 4; ++ // ++ // + 4 bytes for the T2 ++ // ++ ExpectedSize += 4; ++ // ++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ // + 2 bytes for the option header type ++ // + 2 bytes for the option header length ++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address ++ // ++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ Ia->Descriptor.Type = Dhcp6OptIana; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0x12345678, ++ 0x12345678, ++ Dhcp6OptIana ++ ); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++} ++ ++TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) { ++ UINT8 *Cursor; ++ EFI_STATUS Status; ++ UINTN ExpectedSize; ++ UINTN OriginalLength; ++ ++ // ++ // 2 bytes for the option header type ++ // ++ ExpectedSize = 2; ++ // ++ // 2 bytes for the option header length ++ // ++ ExpectedSize += 2; ++ // ++ // 4 bytes for the IAID ++ // ++ ExpectedSize += 4; ++ // ++ // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ // + 2 bytes for the option header type ++ // + 2 bytes for the option header length ++ // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address ++ // ++ ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2; ++ ++ Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ OriginalLength = Packet->Length; ++ ++ Ia->Descriptor.Type = Dhcp6OptIata; ++ Ia->Descriptor.IaId = 0x12345678; ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6AppendIaOptionTest::Packet, ++ &Cursor, ++ Ia, ++ 0, ++ 0, ++ Dhcp6OptIata ++ ); ++ ++ // verify that the pointer to cursor moved by the expected amount ++ ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize); ++ ++ // verify that the length of the packet is now the expected amount ++ ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize); ++ ++ // verify that the status is EFI_SUCCESS ++ ASSERT_EQ (Status, EFI_SUCCESS); ++} +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 1aeca5c5b3..20bc90b172 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -24,6 +24,7 @@ + # + # Build HOST_APPLICATION that tests NetworkPkg + # ++ NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +-- +2.41.0 + diff --git a/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch new file mode 100644 index 0000000..3af6219 --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch @@ -0,0 +1,168 @@ +From 02266fef2b5320a41f79cebd4b6c5a83f1036427 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 2/3] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 60: NetworkPkg: Apply uncrustify changes +RH-Jira: RHEL-22002 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [2/3] 3d71d4ca4e6cc0deb9af78b3b7901a93120de210 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-22002 +CVE: CVE-2022-45234 +Upstream: Merged + +commit 1b53515d53d303166b2bbd31e2cc7f16fd0aecd7 +Author: Doug Flick +Date: Fri Jan 26 05:54:52 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539 + + Bug Details: + PixieFail Bug #6 + CVE-2023-45234 + CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H + CWE-119 Improper Restriction of Operations within the Bounds of + a Memory Buffer + + Buffer overflow when processing DNS Servers option in a DHCPv6 + Advertise message + + Change Overview: + + Introduces a function to cache the Dns Server and perform sanitizing + on the incoming DnsServerLen to ensure that the length is valid + + > + EFI_STATUS + > + PxeBcCacheDnsServerAddresses ( + > + IN PXEBC_PRIVATE_DATA *Private, + > + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + > + ) + + Additional code cleanup + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++--- + 1 file changed, 65 insertions(+), 6 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 425e0cf806..2b2d372889 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -3,6 +3,7 @@ + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
++ Copyright (c) Microsoft Corporation + + SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer ( + } + } + ++/** ++ Cache the DHCPv6 DNS Server addresses ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. ++ ++ @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted ++ option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)). ++**/ ++EFI_STATUS ++PxeBcCacheDnsServerAddresses ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6 ++ ) ++{ ++ UINT16 DnsServerLen; ++ ++ DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen); ++ // ++ // Make sure that the number is nonzero ++ // ++ if (DnsServerLen == 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16) ++ // ++ if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ // This code is currently written to only support a single DNS Server instead ++ // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior ++ // would be to allocate the full space requested, CopyMem all of the data, ++ // and then add a DnsServerCount field to Private and update additional code ++ // that depends on this. ++ // ++ // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen ++ // ++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 ++ // ++ Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS)); ++ if (Private->DnsServer == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ // ++ // Intentionally only copy over the first server address. ++ // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen ++ // ++ CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); ++ ++ return EFI_SUCCESS; ++} ++ + /** + Handle the DHCPv6 offer packet. + +@@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer ( + UINT32 SelectIndex; + UINT32 Index; + ++ ASSERT (Private != NULL); + ASSERT (Private->SelectIndex > 0); + SelectIndex = (UINT32)(Private->SelectIndex - 1); + ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); +@@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer ( + Status = EFI_SUCCESS; + + // +- // First try to cache DNS server address if DHCP6 offer provides. ++ // First try to cache DNS server addresses if DHCP6 offer provides. + // + if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) { +- Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen)); +- if (Private->DnsServer == NULL) { +- return EFI_OUT_OF_RESOURCES; ++ Status = PxeBcCacheDnsServerAddresses (Private, Cache6); ++ if (EFI_ERROR (Status)) { ++ return Status; + } +- +- CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS)); + } + + if (Cache6->OfferType == PxeOfferTypeDhcpBinl) { +-- +2.41.0 + diff --git a/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch new file mode 100644 index 0000000..b5cefa6 --- /dev/null +++ b/SOURCES/edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch @@ -0,0 +1,512 @@ +From 35e5b7bfce3e681396e135895982efbe1738abe5 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 3/3] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 60: NetworkPkg: Apply uncrustify changes +RH-Jira: RHEL-22002 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Oliver Steffen +RH-Commit: [3/3] c9a2a4b0845baab4528dfab21dbc9f508318f301 (jmaloy/jons_fork) + +JIRA: https://issues.redhat.com/browse/RHEL-22002 +CVE: CVE-2022-45234 +Upstream: Merged + +commit 458c582685fc0e8057d2511c5a0394078d988c17 +Author: Doug Flick +Date: Fri Jan 26 05:54:53 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539 + + Unit tests to that the bug.. + + Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise + message + + ..has been patched + + This contains tests for the following functions: + PxeBcHandleDhcp6Offer + PxeBcCacheDnsServerAddresses + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Test/NetworkPkgHostTest.dsc | 2 + + .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 300 ++++++++++++++++++ + .../GoogleTest/PxeBcDhcp6GoogleTest.h | 50 +++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 ++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 48 +++ + 5 files changed, 419 insertions(+) + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp + create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf + +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 20bc90b172..c8a991e5c1 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -25,6 +25,8 @@ + # Build HOST_APPLICATION that tests NetworkPkg + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf ++ NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf ++ NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +new file mode 100644 +index 0000000000..8260eeee50 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +@@ -0,0 +1,300 @@ ++/** @file ++ Host based unit test for PxeBcDhcp6.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include "../PxeBcImpl.h" ++ #include "../PxeBcDhcp6.h" ++ #include "PxeBcDhcp6GoogleTest.h" ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// Definitions ++/////////////////////////////////////////////////////////////////////////////// ++ ++#define PACKET_SIZE (1500) ++ ++typedef struct { ++ UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03) ++ UINT16 OptionLen; // The length of the option (e.g., 16 bytes) ++ UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier ++} DHCP6_OPTION_SERVER_ID; ++ ++/////////////////////////////////////////////////////////////////////////////// ++/// Symbol Definitions ++/////////////////////////////////////////////////////////////////////////////// ++ ++EFI_STATUS ++MockUdpWrite ( ++ IN EFI_PXE_BASE_CODE_PROTOCOL *This, ++ IN UINT16 OpFlags, ++ IN EFI_IP_ADDRESS *DestIp, ++ IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, ++ IN EFI_IP_ADDRESS *GatewayIp OPTIONAL, ++ IN EFI_IP_ADDRESS *SrcIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, ++ IN UINTN *HeaderSize OPTIONAL, ++ IN VOID *HeaderPtr OPTIONAL, ++ IN UINTN *BufferSize, ++ IN VOID *BufferPtr ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++MockUdpRead ( ++ IN EFI_PXE_BASE_CODE_PROTOCOL *This, ++ IN UINT16 OpFlags, ++ IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL, ++ IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL, ++ IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL, ++ IN UINTN *HeaderSize OPTIONAL, ++ IN VOID *HeaderPtr OPTIONAL, ++ IN OUT UINTN *BufferSize, ++ IN VOID *BufferPtr ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++EFI_STATUS ++MockConfigure ( ++ IN EFI_UDP6_PROTOCOL *This, ++ IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++// Needed by PxeBcSupport ++EFI_STATUS ++EFIAPI ++QueueDpc ( ++ IN EFI_TPL DpcTpl, ++ IN EFI_DPC_PROCEDURE DpcProcedure, ++ IN VOID *DpcContext OPTIONAL ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcHandleDhcp6OfferTest Tests ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcHandleDhcp6OfferTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ EFI_PXE_BASE_CODE_MODE Mode = { 0 }; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE); ++ ++ // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL ++ // The function under test really only needs the following: ++ // UdpWrite ++ // UdpRead ++ ++ Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite; ++ Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead; ++ ++ // Need to setup EFI_UDP6_PROTOCOL ++ // The function under test really only needs the following: ++ // Configure ++ ++ Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure; ++ Private.Udp6Read = &Udp6Read; ++ ++ // Need to setup the EFI_PXE_BASE_CODE_MODE ++ Private.PxeBc.Mode = &Mode; ++ ++ // for this test it doesn't really matter what the Dhcpv6 ack is set to ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++// Note: ++// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a ++// properly setup Private structure. Attempting to properly test this function ++// without a signficant refactor is a fools errand. Instead, we will test ++// that we can prevent an overflow in the function. ++TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) { ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337); ++ ++ ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR); ++} ++ ++class PxeBcCacheDnsServerAddressesTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ } ++}; ++ ++// Test Description ++// Test that we cache the DNS server address from the DHCPv6 offer packet ++TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) { ++ UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF }; ++ EFI_DHCP6_PACKET_OPTION *Option; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern)); ++ ASSERT_NE (Option, nullptr); ++ ++ Option->OpCode = DHCP6_OPT_SERVER_ID; ++ Option->OpLen = NTOHS (sizeof (SearchPattern)); ++ CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern)); ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option; ++ ++ Private.DnsServer = nullptr; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS); ++ ASSERT_NE (Private.DnsServer, nullptr); ++ ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++ ++ if (Option) { ++ FreePool (Option); ++ } ++} ++// Test Description ++// Test that we can prevent an overflow in the function ++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR); ++ ASSERT_EQ (Private.DnsServer, nullptr); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} ++ ++// Test Description ++// Test that we can prevent an underflow in the function ++TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR); ++ ASSERT_EQ (Private.DnsServer, nullptr); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} ++ ++// Test Description ++// Test that we can handle recursive dns (multiple dns entries) ++TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) { ++ EFI_DHCP6_PACKET_OPTION Option = { 0 }; ++ PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL; ++ ++ Private.SelectIndex = 1; // SelectIndex is 1-based ++ Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6; ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option; ++ // Setup the DHCPv6 offer packet ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID; ++ ++ EFI_IPv6_ADDRESS addresses[2] = { ++ // 2001:db8:85a3::8a2e:370:7334 ++ { 0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34 }, ++ // fe80::d478:91c3:ecd7:4ff9 ++ { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9 } ++ }; ++ ++ CopyMem (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof (addresses)); ++ ++ Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof (addresses)); ++ ++ Private.DnsServer = NULL; ++ ++ ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS); ++ ++ ASSERT_NE (Private.DnsServer, nullptr); ++ ++ // ++ // This is expected to fail until DnsServer supports multiple DNS servers ++ // ++ // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886 ++ // ++ // Disabling: ++ // ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0); ++ ++ if (Private.DnsServer) { ++ FreePool (Private.DnsServer); ++ } ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +new file mode 100644 +index 0000000000..b17c314791 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +@@ -0,0 +1,50 @@ ++/** @file ++ This file exposes the internal interfaces which may be unit tested ++ for the PxeBcDhcp6Dxe driver. ++ ++ Copyright (c) Microsoft Corporation.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef PXE_BC_DHCP6_GOOGLE_TEST_H_ ++#define PXE_BC_DHCP6_GOOGLE_TEST_H_ ++ ++// ++// Minimal includes needed to compile ++// ++#include ++#include "../PxeBcImpl.h" ++ ++/** ++ Handle the DHCPv6 offer packet. ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ ++ @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully. ++ @retval EFI_NO_RESPONSE No response to the following request packet. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet. ++ ++**/ ++EFI_STATUS ++PxeBcHandleDhcp6Offer ( ++ IN PXEBC_PRIVATE_DATA *Private ++ ); ++ ++/** ++ Cache the DHCPv6 Server address ++ ++ @param[in] Private The pointer to PXEBC_PRIVATE_DATA. ++ @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE. ++ ++ @retval EFI_SUCCESS Cache the DHCPv6 Server address successfully. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_DEVICE_ERROR Failed to cache the DHCPv6 Server address. ++**/ ++EFI_STATUS ++PxeBcCacheDnsServerAddresses ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN PXEBC_DHCP6_PACKET_CACHE *Cache6 ++ ); ++ ++#endif // PXE_BC_DHCP6_GOOGLE_TEST_H_ +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp +new file mode 100644 +index 0000000000..cc4fdf525b +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp +@@ -0,0 +1,19 @@ ++/** @file ++ Acts as the main entry point for the tests for the UefiPxeBcDxe module. ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Run the tests ++//////////////////////////////////////////////////////////////////////////////// ++int ++main ( ++ int argc, ++ char *argv[] ++ ) ++{ ++ testing::InitGoogleTest (&argc, argv); ++ return RUN_ALL_TESTS (); ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf +new file mode 100644 +index 0000000000..301dcdf611 +--- /dev/null ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf +@@ -0,0 +1,48 @@ ++## @file ++# Unit test suite for the UefiPxeBcDxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++INF_VERSION = 0x00010005 ++BASE_NAME = UefiPxeBcDxeGoogleTest ++FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF ++MODULE_TYPE = HOST_APPLICATION ++VERSION_STRING = 1.0 ++ ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 ++# ++ ++[Sources] ++ UefiPxeBcDxeGoogleTest.cpp ++ PxeBcDhcp6GoogleTest.cpp ++ PxeBcDhcp6GoogleTest.h ++ ../PxeBcDhcp6.c ++ ../PxeBcSupport.c ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec ++ NetworkPkg/NetworkPkg.dec ++ ++[LibraryClasses] ++ GoogleTestLib ++ DebugLib ++ NetLib ++ PcdLib ++ ++[Protocols] ++ gEfiDhcp6ServiceBindingProtocolGuid ++ gEfiDns6ServiceBindingProtocolGuid ++ gEfiDns6ProtocolGuid ++ ++[Pcd] ++ gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType ++ ++[Guids] ++ gZeroGuid +-- +2.41.0 + diff --git a/SPECS/edk2.spec b/SPECS/edk2.spec index 1b47976..c6515a5 100644 --- a/SPECS/edk2.spec +++ b/SPECS/edk2.spec @@ -7,7 +7,7 @@ ExclusiveArch: x86_64 aarch64 Name: edk2 Version: %{GITDATE}git%{GITCOMMIT} -Release: 6%{?dist}.3 +Release: 6%{?dist}.6 Summary: UEFI firmware for 64-bit virtual machines Group: Applications/Emulators License: BSD-2-Clause-Patent and OpenSSL and MIT @@ -64,6 +64,18 @@ Patch30: edk2-UefiCpuPkg-MpInitLib-fix-apic-mode-for-cpu-hotplug.patch Patch31: old.patch # For RHEL-20351 - [rhel8] guest fails to boot due to ASSERT error [rhel-8.9.0.z] Patch32: old2.patch +# For RHEL-21993 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8.9.0.z] +Patch33: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch +# For RHEL-21993 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8.9.0.z] +Patch34: edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch +# For RHEL-21993 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8.9.0.z] +Patch35: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch +# For RHEL-22002 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8.9.0.z] +Patch36: edk2-NetworkPkg-Apply-uncrustify-chang1.patch +# For RHEL-22002 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8.9.0.z] +Patch37: edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch +# For RHEL-22002 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8.9.0.z] +Patch38: edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch # python3-devel and libuuid-devel are required for building tools. @@ -508,6 +520,20 @@ true %endif %changelog +* Tue Feb 27 2024 Jon Maloy - 20220126gitbb1bba3d77-6.el8_9.6 +- edk2-NetworkPkg-Apply-uncrustify-chang1.patch [RHEL-22002] +- edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234.patch [RHEL-22002] +- edk2-NetworkPkg-UefiPxeBcDxe-SECUR-PATCH-CVE-2023-45234_U.patch [RHEL-22002] +- Resolves: RHEL-22002 + (CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-8.9.0.z]) + +* Wed Feb 14 2024 Jon Maloy - 20220126gitbb1bba3d77-6.el8_9.4 +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch [RHEL-21993] +- edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch [RHEL-21993] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch [RHEL-21993] +- Resolves: RHEL-21993 + (CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-8.9.0.z]) + * Mon Jan 15 2024 Jon Maloy - 20220126gitbb1bba3d77-6.el8_9.3 - old.patch [RHEL-20351] - old2.patch [RHEL-20351]