diff --git a/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch b/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch new file mode 100644 index 0000000..e6e6dbc --- /dev/null +++ b/edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch @@ -0,0 +1,170 @@ +From 0d85ac65b3e469e879f687150d0a25e6dbd6cac1 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 02/18] NetworkPkg: : Add Unit tests to CI and create Host Test + DSC + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [2/18] 331bea0d7e46de0e35e595ad08c94eec99c80cd8 + +JIRA: https://issues.redhat.com/browse/RHEL-21843 +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.39.3 + diff --git a/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch b/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch new file mode 100644 index 0000000..217f755 --- /dev/null +++ b/edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch @@ -0,0 +1,170 @@ +From 3c1cf95b979cea6b0dee6e107756558a7a71d4ac Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 14/18] NetworkPkg: : Adds a SecurityFix.yaml file + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [14/18] dddbcbe14e38dc1bb03acf4622d6285090c4bb02 + +JIRA: https://issues.redhat.com/browse/RHEL-21853 +CVE: CVE-2022-45235 +Upstream: Merged + +commit 1d0b95f6457d225c5108302a9da74b4ed7aa5a38 +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:57 2024 +0800 + + NetworkPkg: : Adds a SecurityFix.yaml file + + This creates / adds a security file that tracks the security fixes + found in this package and can be used to find the fixes that were + applied. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/SecurityFixes.yaml | 123 ++++++++++++++++++++++++++++++++++ + 1 file changed, 123 insertions(+) + create mode 100644 NetworkPkg/SecurityFixes.yaml + +diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml +new file mode 100644 +index 0000000000..7e900483fe +--- /dev/null ++++ b/NetworkPkg/SecurityFixes.yaml +@@ -0,0 +1,123 @@ ++## @file ++# Security Fixes for SecurityPkg ++# ++# Copyright (c) Microsoft Corporation ++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++CVE_2023_45229: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests" ++ cve: CVE-2023-45229 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 01 - edk2/NetworkPkg: Out-of-bounds read when processing IA_NA/IA_TA options in a DHCPv6 Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4534 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45229 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45230: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests" ++ cve: CVE-2023-45230 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 02 - edk2/NetworkPkg: Buffer overflow in the DHCPv6 client via a long Server ID option" ++ note: ++ files_impacted: ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Io.c ++ - NetworkPkg\Dhcp6Dxe\Dhcp6Impl.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4535 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45230 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45231: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests" ++ cve: CVE-2023-45231 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 03 - edk2/NetworkPkg: Out-of-bounds read when handling a ND Redirect message with truncated options" ++ note: ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4536 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45231 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45232: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests" ++ cve: CVE-2023-45232 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 04 - edk2/NetworkPkg: Infinite loop when parsing unknown options in the Destination Options header" ++ note: ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ - NetworkPkg/Ip6Dxe/Ip6Option.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4537 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45232 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45233: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests" ++ cve: CVE-2023-45233 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 05 - edk2/NetworkPkg: Infinite loop when parsing a PadN option in the Destination Options header " ++ note: This was fixed along with CVE-2023-45233 ++ files_impacted: ++ - NetworkPkg/Ip6Dxe/Ip6Option.c ++ - NetworkPkg/Ip6Dxe/Ip6Option.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4538 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45233 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45234: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45234 Unit Tests" ++ cve: CVE-2023-45234 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 06 - edk2/NetworkPkg: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4539 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45234 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html ++CVE_2023_45235: ++ commit_titles: ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Patch" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45235 Unit Tests" ++ cve: CVE-2023-45235 ++ date_reported: 2023-08-28 13:56 UTC ++ description: "Bug 07 - edk2/NetworkPkg: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message" ++ note: ++ files_impacted: ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h ++ links: ++ - https://bugzilla.tianocore.org/show_bug.cgi?id=4540 ++ - https://nvd.nist.gov/vuln/detail/CVE-2023-45235 ++ - http://www.openwall.com/lists/oss-security/2024/01/16/2 ++ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html ++ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch b/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch new file mode 100644 index 0000000..8a7951c --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch @@ -0,0 +1,69 @@ +From 3ab0e3be00cc74b39db482e33bfe923f70768ae4 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 17/18] NetworkPkg: Dhcp6Dxe: Packet-Length is not updated + before appending + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [17/18] c13c96534ecea4c43ca98cecf0789b07680958ca + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 75deaf5c3c0d164c61653258c331151241bb69d8 +Author: Doug Flick +Date: Tue Feb 13 10:46:02 2024 -0800 + + NetworkPkg: Dhcp6Dxe: Packet-Length is not updated before appending + + In order for Dhcp6AppendIaAddrOption (..) to safely append the IA + Address option, the Packet-Length field must be updated before appending + the option. + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index e4e0725622..f38e3ee3fe 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -924,6 +924,11 @@ Dhcp6AppendIaOption ( + *PacketCursor += sizeof (T2); + } + ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; ++ + // + // Fill all the addresses belong to the Ia + // +@@ -935,11 +940,6 @@ Dhcp6AppendIaOption ( + } + } + +- // +- // Update the packet length +- // +- Packet->Length += BytesNeeded; +- + // + // Fill the value of Ia option length + // +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch b/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch new file mode 100644 index 0000000..822d4b0 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch @@ -0,0 +1,162 @@ +From bb9d1831fd53d43889112a2e30a52b2c4504fdae Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 16/18] NetworkPkg: Dhcp6Dxe: Removes duplicate check and + replaces with macro + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [16/18] 61914482aa965883b1ec3f29cf6143b67e88742a + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit af3fad99d6088881562e50149f414f76a5be0140 +Author: Doug Flick +Date: Tue Feb 13 10:46:01 2024 -0800 + + NetworkPkg: Dhcp6Dxe: Removes duplicate check and replaces with macro + + Removes duplicate check after merge + + > + > // + > // 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; + > } + > + + Converts the check to a macro and replaces all instances of the check + with the macro + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 44 +++++++++++++----------------- + 1 file changed, 19 insertions(+), 25 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +index 705c665c51..e4e0725622 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -10,6 +10,16 @@ + + #include "Dhcp6Impl.h" + ++// ++// Verifies the packet cursor is within the packet ++// otherwise it is invalid ++// ++#define IS_INVALID_PACKET_CURSOR(PacketCursor, Packet) \ ++ (((*PacketCursor) < (Packet)->Dhcp6.Option) || \ ++ ((*PacketCursor) >= (Packet)->Dhcp6.Option + ((Packet)->Size - sizeof(EFI_DHCP6_HEADER))) \ ++ ) \ ++ ++ + /** + Generate client Duid in the format of Duid-llt. + +@@ -638,9 +648,7 @@ Dhcp6AppendOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -657,15 +665,6 @@ Dhcp6AppendOption ( + 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); +@@ -744,9 +743,7 @@ Dhcp6AppendIaAddrOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -877,9 +874,7 @@ Dhcp6AppendIaOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +@@ -941,14 +936,14 @@ Dhcp6AppendIaOption ( + } + + // +- // Fill the value of Ia option length ++ // Update the packet length + // +- *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); ++ Packet->Length += BytesNeeded; + + // +- // Update the packet length ++ // Fill the value of Ia option length + // +- Packet->Length += BytesNeeded; ++ *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2)); + + return EFI_SUCCESS; + } +@@ -957,6 +952,7 @@ Dhcp6AppendIaOption ( + Append the appointed Elapsed time option to Buf, 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] Instance The pointer to the Dhcp6 instance. +@@ -1012,9 +1008,7 @@ Dhcp6AppendETOption ( + // + // Verify the PacketCursor is within the packet + // +- if ( (*PacketCursor < Packet->Dhcp6.Option) +- || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER)))) +- { ++ if (IS_INVALID_PACKET_CURSOR (PacketCursor, Packet)) { + return EFI_INVALID_PARAMETER; + } + +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch new file mode 100644 index 0000000..0e4a60a --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch @@ -0,0 +1,618 @@ +From c1700b34913109cd9600f58f1fa6b82b08ce3795 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 9 Feb 2024 17:57:07 -0500 +Subject: [PATCH 04/18] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [4/18] 23b6841dbb01249055b8040d85995c366bd94252 + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0 +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:46 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534 + + Bug Details: + PixieFail Bug #1 + CVE-2023-45229 + CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N + CWE-125 Out-of-bounds Read + + Change Overview: + + Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking + the Inner Option from a DHCP6 Option. + + > + > EFI_STATUS + > Dhcp6SeekInnerOptionSafe ( + > IN UINT16 IaType, + > IN UINT8 *Option, + > IN UINT32 OptionLen, + > OUT UINT8 **IaInnerOpt, + > OUT UINT16 *IaInnerLen + > ); + > + + Lots of code cleanup to improve code readability. + + 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 | 138 +++++++++++++++++++--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 203 +++++++++++++++++++++----------- + 2 files changed, 256 insertions(+), 85 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +index f2422c2f28..220e7c68f1 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +@@ -45,6 +45,20 @@ 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 ++ ++#define DHCP6_BASE_PACKET_SIZE 1024 ++ ++#define DHCP6_PORT_CLIENT 546 ++#define DHCP6_PORT_SERVER 547 ++ ++#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20) ++ ++#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE) ++#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE) ++ + // + // For more information on DHCP options see RFC 8415, Section 21.1 + // +@@ -59,12 +73,10 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE; + // | (option-len octets) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // +-#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16)) +-#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16)) ++#define DHCP6_SIZE_OF_OPT_CODE (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode)) ++#define DHCP6_SIZE_OF_OPT_LEN (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen)) + +-// + // Combined size of Code and Length +-// + #define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \ + DHCP6_SIZE_OF_OPT_LEN) + +@@ -73,34 +85,122 @@ STATIC_ASSERT ( + "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) ++#define DHCP6_OFFSET_OF_OPT_LEN(a) (a + DHCP6_SIZE_OF_OPT_CODE) + STATIC_ASSERT ( +- DHCP6_OPT_LEN_OFFSET (0) == 2, ++ DHCP6_OFFSET_OF_OPT_LEN (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) ++#define DHCP6_OFFSET_OF_OPT_DATA(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) + STATIC_ASSERT ( +- DHCP6_OPT_DATA_OFFSET (0) == 4, ++ DHCP6_OFFSET_OF_OPT_DATA (0) == 4, + "Offset to option data should be +4 from start of option" + ); ++// ++// Identity Association options (both NA (Non-Temporary) and TA (Temporary Association)) ++// are defined in RFC 8415 and are a deriviation of a TLV stucture ++// For more information on IA_NA see Section 21.4 ++// For more information on IA_TA see Section 21.5 ++// ++// ++// The format of IA_NA and IA_TA option: ++// ++// 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_IA_NA | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | IAID (4 octets) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | T1 (only for IA_NA) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | T2 (only for IA_NA) | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | | ++// . IA_NA-options/IA_TA-options . ++// . . ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_SIZE_OF_IAID (sizeof(UINT32)) ++#define DHCP6_SIZE_OF_TIME_INTERVAL (sizeof(UINT32)) + +-#define DHCP6_PACKET_ALL 0 +-#define DHCP6_PACKET_STATEFUL 1 +-#define DHCP6_PACKET_STATELESS 2 ++// Combined size of IAID, T1, and T2 ++#define DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 (DHCP6_SIZE_OF_IAID + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL) ++STATIC_ASSERT ( ++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12, ++ "Combined size of IAID, T1, T2 must be 12 per RFC 8415" ++ ); + +-#define DHCP6_BASE_PACKET_SIZE 1024 ++// This is the size of IA_TA without options ++#define DHCP6_MIN_SIZE_OF_IA_TA (DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_IAID) ++STATIC_ASSERT ( ++ DHCP6_MIN_SIZE_OF_IA_TA == 8, ++ "Minimum combined size of IA_TA per RFC 8415" ++ ); + +-#define DHCP6_PORT_CLIENT 546 +-#define DHCP6_PORT_SERVER 547 ++// Offset to a IA_TA inner option ++#define DHCP6_OFFSET_OF_IA_TA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_TA) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8, ++ "Offset of IA_TA Inner option is + 8 past start of option" ++ ); + +-#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20) ++// This is the size of IA_NA without options (16) ++#define DHCP6_MIN_SIZE_OF_IA_NA DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 ++STATIC_ASSERT ( ++ DHCP6_MIN_SIZE_OF_IA_NA == 16, ++ "Minimum combined size of IA_TA per RFC 8415" ++ ); + +-#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE) +-#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE) ++#define DHCP6_OFFSET_OF_IA_NA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_NA) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16, ++ "Offset of IA_NA Inner option is + 16 past start of option" ++ ); ++ ++#define DHCP6_OFFSET_OF_IA_NA_T1(a) (a + \ ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \ ++ DHCP6_SIZE_OF_IAID) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8, ++ "Offset of IA_NA Inner option is + 8 past start of option" ++ ); ++ ++#define DHCP6_OFFSET_OF_IA_NA_T2(a) (a + \ ++ DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN +\ ++ DHCP6_SIZE_OF_IAID + \ ++ DHCP6_SIZE_OF_TIME_INTERVAL) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12, ++ "Offset of IA_NA Inner option is + 12 past start of option" ++ ); ++ ++// ++// For more information see RFC 8415 Section 21.13 ++// ++// The format of the Status Code Option: ++// ++// 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_STATUS_CODE | option-len | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | status-code | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ++// . . ++// . status-message . ++// . . ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN) ++STATIC_ASSERT ( ++ DHCP6_OFFSET_OF_STATUS_CODE (0) == 4, ++ "Offset of status is + 4 past start of option" ++ ); + + extern EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress; + extern EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate; +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index bf5aa7a769..89d16484a5 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -598,8 +598,8 @@ Dhcp6UpdateIaInfo ( + // The inner options still start with 2 bytes option-code and 2 bytes option-len. + // + if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { +- T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8))); +- T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12))); ++ T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option)))); ++ T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option)))); + // + // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2, + // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes +@@ -609,13 +609,14 @@ Dhcp6UpdateIaInfo ( + return EFI_DEVICE_ERROR; + } + +- IaInnerOpt = Option + 16; +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 12); ++ IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); ++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2); + } else { +- T1 = 0; +- T2 = 0; +- IaInnerOpt = Option + 8; +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4); ++ T1 = 0; ++ T2 = 0; ++ ++ IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); ++ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID); + } + + // +@@ -641,7 +642,7 @@ Dhcp6UpdateIaInfo ( + Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + + if (Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -661,6 +662,87 @@ Dhcp6UpdateIaInfo ( + return Status; + } + ++/** ++ Seeks the Inner Options from a DHCP6 Option ++ ++ @param[in] IaType The type of the IA option. ++ @param[in] Option The pointer to the DHCP6 Option. ++ @param[in] OptionLen The length of the DHCP6 Option. ++ @param[out] IaInnerOpt The pointer to the IA inner option. ++ @param[out] IaInnerLen The length of the IA inner option. ++ ++ @retval EFI_SUCCESS Seek the inner option successfully. ++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error, ++ the pointers are not modified ++**/ ++EFI_STATUS ++Dhcp6SeekInnerOptionSafe ( ++ IN UINT16 IaType, ++ IN UINT8 *Option, ++ IN UINT32 OptionLen, ++ OUT UINT8 **IaInnerOpt, ++ OUT UINT16 *IaInnerLen ++ ) ++{ ++ UINT16 IaInnerLenTmp; ++ UINT8 *IaInnerOptTmp; ++ ++ if (Option == NULL) { ++ ASSERT (Option != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaInnerOpt == NULL) { ++ ASSERT (IaInnerOpt != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaInnerLen == NULL) { ++ ASSERT (IaInnerLen != NULL); ++ return EFI_DEVICE_ERROR; ++ } ++ ++ if (IaType == Dhcp6OptIana) { ++ // Verify we have a fully formed IA_NA ++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ // ++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); ++ ++ // Verify the IaInnerLen is valid. ++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option))); ++ if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2; ++ } else if (IaType == Dhcp6OptIata) { ++ // Verify the OptionLen is valid. ++ if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); ++ ++ // Verify the IaInnerLen is valid. ++ IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); ++ if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ IaInnerLenTmp -= DHCP6_SIZE_OF_IAID; ++ } else { ++ return EFI_DEVICE_ERROR; ++ } ++ ++ *IaInnerOpt = IaInnerOptTmp; ++ *IaInnerLen = IaInnerLenTmp; ++ ++ return EFI_SUCCESS; ++} ++ + /** + Seek StatusCode Option in package. A Status Code option may appear in the + options field of a DHCP message and/or in the options field of another option. +@@ -684,6 +766,12 @@ Dhcp6SeekStsOption ( + UINT8 *IaInnerOpt; + UINT16 IaInnerLen; + UINT16 StsCode; ++ UINT32 OptionLen; ++ ++ // OptionLen is the length of the Options excluding the DHCP header. ++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last ++ // byte of the Option[] field. ++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header); + + // + // Seek StatusCode option directly in DHCP message body. That is, search in +@@ -691,12 +779,12 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ OptionLen, + Dhcp6OptStatusCode + ); + + if (*Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (*Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -707,7 +795,7 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekIaOption ( + Packet->Dhcp6.Option, +- Packet->Length - sizeof (EFI_DHCP6_HEADER), ++ OptionLen, + &Instance->Config->IaDescriptor + ); + if (*Option == NULL) { +@@ -715,52 +803,35 @@ Dhcp6SeekStsOption ( + } + + // +- // The format of the IA_NA option is: ++ // Calculate the distance from Packet->Dhcp6.Option to the IA option. + // +- // 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_IA_NA | option-len | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | IAID (4 octets) | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | T1 | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | T2 | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | | +- // . IA_NA-options . +- // . . +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is ++ // the size of the whole packet, including the DHCP header, and Packet->Length ++ // is the length of the DHCP message body, excluding the DHCP header. + // +- // The format of the IA_TA option is: ++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of ++ // DHCP6 option area to the start of the IA option. + // +- // 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_IA_TA | option-len | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | IAID (4 octets) | +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +- // | | +- // . IA_TA-options . +- // . . +- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the ++ // IA option to the end of the DHCP6 option area, thus subtract the space ++ // up until this option + // ++ OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option); + + // +- // sizeof (option-code + option-len + IaId) = 8 +- // sizeof (option-code + option-len + IaId + T1) = 12 +- // sizeof (option-code + option-len + IaId + T1 + T2) = 16 +- // +- // The inner options still start with 2 bytes option-code and 2 bytes option-len. ++ // Seek the inner option + // +- if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { +- IaInnerOpt = *Option + 16; +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12); +- } else { +- IaInnerOpt = *Option + 8; +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4); ++ if (EFI_ERROR ( ++ Dhcp6SeekInnerOptionSafe ( ++ Instance->Config->IaDescriptor.Type, ++ *Option, ++ OptionLen, ++ &IaInnerOpt, ++ &IaInnerLen ++ ) ++ )) ++ { ++ return EFI_DEVICE_ERROR; + } + + // +@@ -784,7 +855,7 @@ Dhcp6SeekStsOption ( + // + *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + if (*Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (*Option))))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -1105,7 +1176,7 @@ Dhcp6SendRequestMsg ( + // + Option = Dhcp6SeekOption ( + Instance->AdSelect->Dhcp6.Option, +- Instance->AdSelect->Length - 4, ++ Instance->AdSelect->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1289,7 +1360,7 @@ Dhcp6SendDeclineMsg ( + // + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1448,7 +1519,7 @@ Dhcp6SendReleaseMsg ( + // + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -1673,7 +1744,7 @@ Dhcp6SendRenewRebindMsg ( + + Option = Dhcp6SeekOption ( + LastReply->Dhcp6.Option, +- LastReply->Length - 4, ++ LastReply->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + if (Option == NULL) { +@@ -2208,7 +2279,7 @@ Dhcp6HandleReplyMsg ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptRapidCommit + ); + +@@ -2354,7 +2425,7 @@ Dhcp6HandleReplyMsg ( + // + // Any error status code option is found. + // +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE (Option))))); + switch (StsCode) { + case Dhcp6StsUnspecFail: + // +@@ -2487,7 +2558,7 @@ Dhcp6SelectAdvertiseMsg ( + // + Option = Dhcp6SeekOption ( + AdSelect->Dhcp6.Option, +- AdSelect->Length - 4, ++ AdSelect->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerUnicast + ); + +@@ -2498,7 +2569,7 @@ Dhcp6SelectAdvertiseMsg ( + return EFI_OUT_OF_RESOURCES; + } + +- CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS)); ++ CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA (Option), sizeof (EFI_IPv6_ADDRESS)); + } + + // +@@ -2551,7 +2622,7 @@ Dhcp6HandleAdvertiseMsg ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptRapidCommit + ); + +@@ -2645,7 +2716,7 @@ Dhcp6HandleAdvertiseMsg ( + CopyMem (Instance->AdSelect, Packet, Packet->Size); + + if (Option != NULL) { +- Instance->AdPref = *(Option + 4); ++ Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA (Option)); + } + } else { + // +@@ -2714,11 +2785,11 @@ Dhcp6HandleStateful ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptClientId + ); + +- if ((Option == NULL) || (CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0)) { ++ if ((Option == NULL) || (CompareMem (DHCP6_OFFSET_OF_OPT_DATA (Option), ClientId->Duid, ClientId->Length) != 0)) { + goto ON_CONTINUE; + } + +@@ -2727,7 +2798,7 @@ Dhcp6HandleStateful ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN, + Dhcp6OptServerId + ); + +@@ -2832,7 +2903,7 @@ Dhcp6HandleStateless ( + // + Option = Dhcp6SeekOption ( + Packet->Dhcp6.Option, +- Packet->Length - 4, ++ Packet->Length - sizeof (EFI_DHCP6_HEADER), + Dhcp6OptServerId + ); + +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch new file mode 100644 index 0000000..afb800a --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch @@ -0,0 +1,257 @@ +From dcfd5b6e28536e5b28fb4c47ec57f8d106b6b181 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 15/18] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 + Related Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [15/18] e2fe2033c2f90145249d9416a539d5b2fc52596a + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 1c440a5eceedc64e892877eeac0f1a4938f5abbb +Author: Doug Flick +Date: Tue Feb 13 10:46:00 2024 -0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Related Patch + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4673 + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534 + + This was not part of the Quarkslab bugs however the same pattern + as CVE-2023-45229 exists in Dhcp6UpdateIaInfo. + + This patch replaces the code in question with the safe function + created to patch CVE-2023-45229 + + > + > if (EFI_ERROR ( + > Dhcp6SeekInnerOptionSafe ( + > Instance->Config->IaDescriptor.Type, + > Option, + > OptionLen, + > &IaInnerOpt, + > &IaInnerLen + > ) + > )) + > { + > return EFI_DEVICE_ERROR; + > } + > + + Additionally corrects incorrect usage of macro to read the status + + > - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN + (Option))); + > + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) + DHCP6_OFFSET_OF_STATUS_CODE (Option)); + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 70 ++++++++++++++++++++++++++--------- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.h | 22 +++++++++++ + 2 files changed, 75 insertions(+), 17 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index 3b8feb4a20..a9bffae353 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -528,13 +528,23 @@ Dhcp6UpdateIaInfo ( + { + EFI_STATUS Status; + UINT8 *Option; ++ UINT32 OptionLen; + UINT8 *IaInnerOpt; + UINT16 IaInnerLen; + UINT16 StsCode; + UINT32 T1; + UINT32 T2; + ++ T1 = 0; ++ T2 = 0; ++ + ASSERT (Instance->Config != NULL); ++ ++ // OptionLen is the length of the Options excluding the DHCP header. ++ // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last ++ // byte of the Option[] field. ++ OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header); ++ + // + // If the reply was received in response to a solicit with rapid commit option, + // request, renew or rebind message, the client updates the information it has +@@ -549,13 +559,29 @@ Dhcp6UpdateIaInfo ( + // + Option = Dhcp6SeekIaOption ( + Packet->Dhcp6.Option, +- Packet->Length - sizeof (EFI_DHCP6_HEADER), ++ OptionLen, + &Instance->Config->IaDescriptor + ); + if (Option == NULL) { + return EFI_DEVICE_ERROR; + } + ++ // ++ // Calculate the distance from Packet->Dhcp6.Option to the IA option. ++ // ++ // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is ++ // the size of the whole packet, including the DHCP header, and Packet->Length ++ // is the length of the DHCP message body, excluding the DHCP header. ++ // ++ // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of ++ // DHCP6 option area to the start of the IA option. ++ // ++ // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the ++ // IA option to the end of the DHCP6 option area, thus subtract the space ++ // up until this option ++ // ++ OptionLen = OptionLen - (UINT32)(Option - Packet->Dhcp6.Option); ++ + // + // The format of the IA_NA option is: + // +@@ -591,32 +617,32 @@ Dhcp6UpdateIaInfo ( + // + + // +- // sizeof (option-code + option-len + IaId) = 8 +- // sizeof (option-code + option-len + IaId + T1) = 12 +- // sizeof (option-code + option-len + IaId + T1 + T2) = 16 +- // +- // The inner options still start with 2 bytes option-code and 2 bytes option-len. ++ // Seek the inner option + // ++ if (EFI_ERROR ( ++ Dhcp6SeekInnerOptionSafe ( ++ Instance->Config->IaDescriptor.Type, ++ Option, ++ OptionLen, ++ &IaInnerOpt, ++ &IaInnerLen ++ ) ++ )) ++ { ++ return EFI_DEVICE_ERROR; ++ } ++ + if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) { + T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1 (Option)))); + T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2 (Option)))); + // + // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2, + // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes +- // the remainder of the message as though the server had not included the invalid IA_NA option. ++ // the remainder of the message as though the server had not included the invalid IA_NA option. + // + if ((T1 > T2) && (T2 > 0)) { + return EFI_DEVICE_ERROR; + } +- +- IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2); +- } else { +- T1 = 0; +- T2 = 0; +- +- IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); +- IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID); + } + + // +@@ -642,7 +668,7 @@ Dhcp6UpdateIaInfo ( + Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode); + + if (Option != NULL) { +- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); ++ StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE (Option)))); + if (StsCode != Dhcp6StsSuccess) { + return EFI_DEVICE_ERROR; + } +@@ -703,15 +729,21 @@ Dhcp6SeekInnerOptionSafe ( + } + + if (IaType == Dhcp6OptIana) { ++ // + // Verify we have a fully formed IA_NA ++ // + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) { + return EFI_DEVICE_ERROR; + } + ++ // ++ // Get the IA Inner Option and Length + // + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT (Option); + ++ // + // Verify the IaInnerLen is valid. ++ // + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN (Option))); + if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) { + return EFI_DEVICE_ERROR; +@@ -719,14 +751,18 @@ Dhcp6SeekInnerOptionSafe ( + + IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2; + } else if (IaType == Dhcp6OptIata) { ++ // + // Verify the OptionLen is valid. ++ // + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) { + return EFI_DEVICE_ERROR; + } + + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option); + ++ // + // Verify the IaInnerLen is valid. ++ // + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))); + if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) { + return EFI_DEVICE_ERROR; +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h +index 051a652f2b..ab0e1ac27f 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h +@@ -217,4 +217,26 @@ Dhcp6OnTimerTick ( + IN VOID *Context + ); + ++/** ++ Seeks the Inner Options from a DHCP6 Option ++ ++ @param[in] IaType The type of the IA option. ++ @param[in] Option The pointer to the DHCP6 Option. ++ @param[in] OptionLen The length of the DHCP6 Option. ++ @param[out] IaInnerOpt The pointer to the IA inner option. ++ @param[out] IaInnerLen The length of the IA inner option. ++ ++ @retval EFI_SUCCESS Seek the inner option successfully. ++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error, ++ the pointers are not modified ++**/ ++EFI_STATUS ++Dhcp6SeekInnerOptionSafe ( ++ IN UINT16 IaType, ++ IN UINT8 *Option, ++ IN UINT32 OptionLen, ++ OUT UINT8 **IaInnerOpt, ++ OUT UINT16 *IaInnerLen ++ ); ++ + #endif +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Un.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Un.patch new file mode 100644 index 0000000..7a477bc --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Un.patch @@ -0,0 +1,565 @@ +From 76930459d2e3f82e10968ec8904e45c8bac77fd8 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 9 Feb 2024 17:57:07 -0500 +Subject: [PATCH 05/18] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [5/18] 7421b6f8d8e6bc3d8ea4aaf90f65608136b968b2 + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 07362769ab7a7d74dbea1c7a7a3662c7b5d1f097 +Author: Doug Flick via groups.io +Date: Fri Jan 26 05:54:47 2024 +0800 + + NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests + + REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534 + + These tests confirm that the report bug... + + "Out-of-bounds read when processing IA_NA/IA_TA options in a + DHCPv6 Advertise message" + + ..has been patched. + + The following functions are tested to confirm an out of bounds read is + patched and that the correct statuses are returned: + + Dhcp6SeekInnerOptionSafe + Dhcp6SeekStsOption + + TCBZ4534 + CVE-2023-45229 + CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N + CWE-125 Out-of-bounds Read + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 2 +- + .../GoogleTest/Dhcp6DxeGoogleTest.inf | 1 + + .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 365 +++++++++++++++++- + .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h | 58 +++ + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + 5 files changed, 424 insertions(+), 3 deletions(-) + create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index 89d16484a5..3b8feb4a20 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +@@ -816,7 +816,7 @@ Dhcp6SeekStsOption ( + // IA option to the end of the DHCP6 option area, thus subtract the space + // up until this option + // +- OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option); ++ OptionLen = OptionLen - (UINT32)(*Option - Packet->Dhcp6.Option); + + // + // Seek the inner option +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +index 8e9119a371..12532ed30c 100644 +--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf +@@ -18,6 +18,7 @@ + [Sources] + Dhcp6DxeGoogleTest.cpp + Dhcp6IoGoogleTest.cpp ++ Dhcp6IoGoogleTest.h + ../Dhcp6Io.c + ../Dhcp6Utility.c + +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +index 7ee40e4af4..7db253a7b8 100644 +--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp +@@ -13,6 +13,7 @@ extern "C" { + #include + #include "../Dhcp6Impl.h" + #include "../Dhcp6Utility.h" ++ #include "Dhcp6IoGoogleTest.h" + } + + //////////////////////////////////////////////////////////////////////// +@@ -21,7 +22,35 @@ extern "C" { + + #define DHCP6_PACKET_MAX_LEN 1500 + ++// This definition is used by this test but is also required to compile ++// by Dhcp6Io.c ++#define DHCPV6_OPTION_IA_NA 3 ++#define DHCPV6_OPTION_IA_TA 4 ++ ++#define SEARCH_PATTERN 0xDEADC0DE ++#define SEARCH_PATTERN_LEN sizeof(SEARCH_PATTERN) ++ + //////////////////////////////////////////////////////////////////////// ++// Test structures for IA_NA and IA_TA options ++//////////////////////////////////////////////////////////////////////// ++typedef struct { ++ UINT16 Code; ++ UINT16 Len; ++ UINT32 IAID; ++} DHCPv6_OPTION; ++ ++typedef struct { ++ DHCPv6_OPTION Header; ++ UINT32 T1; ++ UINT32 T2; ++ UINT8 InnerOptions[0]; ++} DHCPv6_OPTION_IA_NA; ++ ++typedef struct { ++ DHCPv6_OPTION Header; ++ UINT8 InnerOptions[0]; ++} DHCPv6_OPTION_IA_TA; ++ + //////////////////////////////////////////////////////////////////////// + // Symbol Definitions + // These functions are not directly under test - but required to compile +@@ -210,7 +239,7 @@ TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) { + Status = Dhcp6AppendETOption ( + Dhcp6AppendETOptionTest::Packet, + &Cursor, +- &Instance, // Instance is not used in this function ++ &Instance, // Instance is not used in this function + &ElapsedTime + ); + +@@ -240,7 +269,7 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) { + Status = Dhcp6AppendETOption ( + Dhcp6AppendETOptionTest::Packet, + &Cursor, +- &Instance, // Instance is not used in this function ++ &Instance, // Instance is not used in this function + &ElapsedTime + ); + +@@ -476,3 +505,335 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) { + // verify that the status is EFI_SUCCESS + ASSERT_EQ (Status, EFI_SUCCESS); + } ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6SeekInnerOptionSafe Tests ++//////////////////////////////////////////////////////////////////////// ++ ++// Define a fixture for your tests if needed ++class Dhcp6SeekInnerOptionSafeTest : public ::testing::Test { ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description: ++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IANA option is found. ++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAValidOptionExpectSuccess) { ++ EFI_STATUS Result; ++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 }; ++ UINT32 OptionLength = sizeof (Option); ++ DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ ++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT8 *InnerOptionPtr = NULL; ++ UINT16 InnerOptionLength = 0; ++ ++ OptionPtr->Header.Code = Dhcp6OptIana; ++ OptionPtr->Header.Len = HTONS (4 + 12); // Valid length has to be more than 12 ++ OptionPtr->Header.IAID = 0x12345678; ++ OptionPtr->T1 = 0x11111111; ++ OptionPtr->T2 = 0x22222222; ++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength); ++ ++ Result = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIana, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Result, EFI_SUCCESS); ++ ASSERT_EQ (InnerOptionLength, 4); ++ ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0); ++} ++ ++// Test Description: ++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_DEIVCE_ERROR when the IANA option size is invalid. ++TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAInvalidSizeExpectFail) { ++ // Lets add an inner option of bytes we expect to find ++ EFI_STATUS Status; ++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 }; ++ UINT32 OptionLength = sizeof (Option); ++ DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ ++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT8 *InnerOptionPtr = NULL; ++ UINT16 InnerOptionLength = 0; ++ ++ OptionPtr->Header.Code = Dhcp6OptIana; ++ OptionPtr->Header.Len = HTONS (4); // Set the length to lower than expected (12) ++ OptionPtr->Header.IAID = 0x12345678; ++ OptionPtr->T1 = 0x11111111; ++ OptionPtr->T2 = 0x22222222; ++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength); ++ ++ // Set the InnerOptionLength to be less than the size of the option ++ Status = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIana, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Status, EFI_DEVICE_ERROR); ++ ++ // Now set the OptionLength to be less than the size of the option ++ OptionLength = sizeof (DHCPv6_OPTION_IA_NA) - 1; ++ Status = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIana, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Status, EFI_DEVICE_ERROR); ++} ++ ++// Test Description: ++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option is found ++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAValidOptionExpectSuccess) { ++ // Lets add an inner option of bytes we expect to find ++ EFI_STATUS Status; ++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 }; ++ UINT32 OptionLength = sizeof (Option); ++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ ++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT8 *InnerOptionPtr = NULL; ++ UINT16 InnerOptionLength = 0; ++ ++ OptionPtr->Header.Code = Dhcp6OptIata; ++ OptionPtr->Header.Len = HTONS (4 + 4); // Valid length has to be more than 4 ++ OptionPtr->Header.IAID = 0x12345678; ++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength); ++ ++ Status = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIata, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ASSERT_EQ (InnerOptionLength, 4); ++ ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0); ++} ++ ++// Test Description: ++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid. ++TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAInvalidSizeExpectFail) { ++ // Lets add an inner option of bytes we expect to find ++ EFI_STATUS Status; ++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 }; ++ UINT32 OptionLength = sizeof (Option); ++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ ++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT8 *InnerOptionPtr = NULL; ++ UINT16 InnerOptionLength = 0; ++ ++ OptionPtr->Header.Code = Dhcp6OptIata; ++ OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4) ++ OptionPtr->Header.IAID = 0x12345678; ++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength); ++ ++ Status = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIata, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Status, EFI_DEVICE_ERROR); ++ ++ // Now lets try modifying the OptionLength to be less than the size of the option ++ OptionLength = sizeof (DHCPv6_OPTION_IA_TA) - 1; ++ Status = Dhcp6SeekInnerOptionSafe ( ++ Dhcp6OptIata, ++ Option, ++ OptionLength, ++ &InnerOptionPtr, ++ &InnerOptionLength ++ ); ++ ASSERT_EQ (Status, EFI_DEVICE_ERROR); ++} ++ ++// Test Description: ++// This test verifies that any other Option Type fails ++TEST_F (Dhcp6SeekInnerOptionSafeTest, InvalidOption) { ++ // Lets add an inner option of bytes we expect to find ++ EFI_STATUS Result; ++ UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 }; ++ UINT32 OptionLength = sizeof (Option); ++ DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ ++ UINTN SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT8 *InnerOptionPtr = NULL; ++ UINT16 InnerOptionLength = 0; ++ ++ OptionPtr->Header.Code = 0xC0DE; ++ OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4) ++ OptionPtr->Header.IAID = 0x12345678; ++ CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength); ++ ++ Result = Dhcp6SeekInnerOptionSafe (0xC0DE, Option, OptionLength, &InnerOptionPtr, &InnerOptionLength); ++ ASSERT_EQ (Result, EFI_DEVICE_ERROR); ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Dhcp6SeekStsOption Tests ++//////////////////////////////////////////////////////////////////////// ++ ++#define PACKET_SIZE (1500) ++ ++class Dhcp6SeekStsOptionTest : public ::testing::Test { ++public: ++ DHCP6_INSTANCE Instance = { 0 }; ++ EFI_DHCP6_PACKET *Packet = NULL; ++ EFI_DHCP6_CONFIG_DATA Config = { 0 }; ++ ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Allocate a packet ++ Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE); ++ ASSERT_NE (Packet, nullptr); ++ ++ // Initialize the packet ++ Packet->Size = PACKET_SIZE; ++ ++ Instance.Config = &Config; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ FreePool (Packet); ++ } ++}; ++ ++// Test Description: ++// This test verifies that Dhcp6SeekStsOption returns EFI_DEVICE_ERROR when the option is invalid ++// This verifies that the calling function is working as expected ++TEST_F (Dhcp6SeekStsOptionTest, SeekIATAOptionExpectFail) { ++ EFI_STATUS Status; ++ UINT8 *Option = NULL; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ UINT16 SearchPatternLength = SEARCH_PATTERN_LEN; ++ UINT16 *Len = NULL; ++ EFI_DHCP6_IA Ia = { 0 }; ++ ++ Ia.Descriptor.Type = DHCPV6_OPTION_IA_TA; ++ Ia.IaAddressCount = 1; ++ Ia.IaAddress[0].PreferredLifetime = 0xDEADBEEF; ++ Ia.IaAddress[0].ValidLifetime = 0xDEADAAAA; ++ Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress; ++ ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ ++ Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option; ++ ++ // Let's append the option to the packet ++ Status = Dhcp6AppendOption ( ++ Dhcp6SeekStsOptionTest::Packet, ++ &Option, ++ Dhcp6OptStatusCode, ++ SearchPatternLength, ++ (UINT8 *)&SearchPattern ++ ); ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // Inner option length - this will be overwritten later ++ Len = (UINT16 *)(Option + 2); ++ ++ // Fill in the inner IA option ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6SeekStsOptionTest::Packet, ++ &Option, ++ &Ia, ++ 0x12345678, ++ 0x11111111, ++ 0x22222222 ++ ); ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ // overwrite the len of inner Ia option ++ *Len = HTONS (3); ++ ++ Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_TA; ++ ++ Option = NULL; ++ Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option); ++ ++ ASSERT_EQ (Status, EFI_DEVICE_ERROR); ++} ++ ++// Test Description: ++// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid. ++TEST_F (Dhcp6SeekStsOptionTest, SeekIANAOptionExpectSuccess) { ++ EFI_STATUS Status = EFI_NOT_FOUND; ++ UINT8 *Option = NULL; ++ UINT32 SearchPattern = SEARCH_PATTERN; ++ UINT16 SearchPatternLength = SEARCH_PATTERN_LEN; ++ EFI_DHCP6_IA Ia = { 0 }; ++ ++ Ia.Descriptor.Type = DHCPV6_OPTION_IA_NA; ++ Ia.IaAddressCount = 1; ++ Ia.IaAddress[0].PreferredLifetime = 0x11111111; ++ Ia.IaAddress[0].ValidLifetime = 0x22222222; ++ Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress; ++ Packet->Length = sizeof (EFI_DHCP6_HEADER); ++ ++ Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option; ++ ++ Status = Dhcp6AppendOption ( ++ Dhcp6SeekStsOptionTest::Packet, ++ &Option, ++ Dhcp6OptStatusCode, ++ SearchPatternLength, ++ (UINT8 *)&SearchPattern ++ ); ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ Status = Dhcp6AppendIaOption ( ++ Dhcp6SeekStsOptionTest::Packet, ++ &Option, ++ &Ia, ++ 0x12345678, ++ 0x11111111, ++ 0x22222222 ++ ); ++ ASSERT_EQ (Status, EFI_SUCCESS); ++ ++ Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_NA; ++ ++ Option = NULL; ++ Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option); ++ ++ ASSERT_EQ (Status, EFI_SUCCESS); ++} +diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h +new file mode 100644 +index 0000000000..aed3b89082 +--- /dev/null ++++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h +@@ -0,0 +1,58 @@ ++/** @file ++ Acts as header for private functions under test in Dhcp6Io.c ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef DHCP6_IO_GOOGLE_TEST_H_ ++#define DHCP6_IO_GOOGLE_TEST_H_ ++ ++//////////////////////////////////////////////////////////////////////////////// ++// These are the functions that are being unit tested ++//////////////////////////////////////////////////////////////////////////////// ++ ++#include ++ ++/** ++ Seeks the Inner Options from a DHCP6 Option ++ ++ @param[in] IaType The type of the IA option. ++ @param[in] Option The pointer to the DHCP6 Option. ++ @param[in] OptionLen The length of the DHCP6 Option. ++ @param[out] IaInnerOpt The pointer to the IA inner option. ++ @param[out] IaInnerLen The length of the IA inner option. ++ ++ @retval EFI_SUCCESS Seek the inner option successfully. ++ @retval EFI_DEVICE_ERROR The OptionLen is invalid. ++*/ ++EFI_STATUS ++Dhcp6SeekInnerOptionSafe ( ++ UINT16 IaType, ++ UINT8 *Option, ++ UINT32 OptionLen, ++ UINT8 **IaInnerOpt, ++ UINT16 *IaInnerLen ++ ); ++ ++/** ++ Seek StatusCode Option in package. A Status Code option may appear in the ++ options field of a DHCP message and/or in the options field of another option. ++ See details in section 22.13, RFC3315. ++ ++ @param[in] Instance The pointer to the Dhcp6 instance. ++ @param[in] Packet The pointer to reply messages. ++ @param[out] Option The pointer to status code option. ++ ++ @retval EFI_SUCCESS Seek status code option successfully. ++ @retval EFI_DEVICE_ERROR An unexpected error. ++ ++**/ ++EFI_STATUS ++Dhcp6SeekStsOption ( ++ IN DHCP6_INSTANCE *Instance, ++ IN EFI_DHCP6_PACKET *Packet, ++ OUT UINT8 **Option ++ ); ++ ++#endif // DHCP6_IO_GOOGLE_TEST_H +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 20bc90b172..24dee654df 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -16,6 +16,7 @@ + SKUID_IDENTIFIER = DEFAULT + + !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc ++ + [Packages] + MdePkg/MdePkg.dec + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch new file mode 100644 index 0000000..a5ba9c7 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch @@ -0,0 +1,1631 @@ +From ad79184c7d5d9f95af057b31036167627e92deba Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 01/18] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [1/18] 0c3dc6f4652f517fcfbe21a5faab4d1eea934f58 + +JIRA: https://issues.redhat.com/browse/RHEL-21843 +CVE: CVE-2023-45230 +Upstream: Merged + +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 | 43 +++ + NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 409 +++++++++++++++++++---------- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 373 +++++++++++++++++++++----- + NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 82 +++--- + 4 files changed, 668 insertions(+), 239 deletions(-) + +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +index 0eb9c669b5..f2422c2f28 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +@@ -45,6 +45,49 @@ 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') + ++// ++// 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 +diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +index dcd01e6268..bf5aa7a769 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" +@@ -930,7 +930,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; +@@ -944,54 +945,64 @@ 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. + // + 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; + } + + // +@@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg ( + Instance->StartTime = 0; + + Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg ( + Elapsed, + Instance->Config->SolicitRetransmission + ); ++ ++ON_ERROR: ++ ++ if (Packet) { ++ FreePool (Packet); ++ } ++ ++ return Status; + } + + /** +@@ -1110,7 +1127,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; +@@ -1124,51 +1142,67 @@ 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. + // + 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); + + // +@@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg ( + Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet); + + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1194,14 +1227,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; + } + + /** +@@ -1266,7 +1306,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; +@@ -1280,42 +1321,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; + } + + // +@@ -1329,16 +1386,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; + } + + /** +@@ -1399,7 +1462,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; +@@ -1413,45 +1477,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; + } + + // +@@ -1461,16 +1541,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; + } + + /** +@@ -1529,7 +1615,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; +@@ -1543,26 +1630,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) { + // +@@ -1578,18 +1677,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; ++ } + } + + // +@@ -1597,18 +1700,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); + + // +@@ -1618,10 +1721,8 @@ Dhcp6SendRenewRebindMsg ( + Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; + + Status = Dhcp6CallbackUser (Instance, Event, &Packet); +- + if (EFI_ERROR (Status)) { +- FreePool (Packet); +- return Status; ++ goto ON_ERROR; + } + + // +@@ -1638,16 +1739,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; + } + + /** +@@ -1811,7 +1918,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; +@@ -1828,44 +1936,56 @@ 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. + // + 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); + + // +@@ -1877,16 +1997,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; + } + + /** +@@ -1937,7 +2063,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; +@@ -1951,54 +2078,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; + } + + // +@@ -2012,16 +2149,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 e6368b5b1c..705c665c51 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +@@ -577,24 +577,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: + // +@@ -607,35 +616,95 @@ 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 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: + // + // 0 1 2 3 +@@ -657,17 +726,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. +@@ -675,44 +787,58 @@ 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; ++ *PacketCursor += sizeof (IaAddr->ValidLifetime); ++ ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; + +- return Buf; ++ 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: +@@ -733,32 +859,74 @@ 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); + } + + // +@@ -766,35 +934,51 @@ Dhcp6AppendIaOption ( + // + 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); ++ 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)); + +- return Buf; ++ // ++ // Update the packet length ++ // ++ Packet->Length += BytesNeeded; ++ ++ 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: + // +@@ -806,27 +990,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 046454ff4a..06947f6c1f 100644 +--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h ++++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +@@ -160,69 +160,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.39.3 + diff --git a/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch new file mode 100644 index 0000000..f4d0419 --- /dev/null +++ b/edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch @@ -0,0 +1,630 @@ +From c4b0517aaa38857640b4b08b55803ae8a833c1e7 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 8 Feb 2024 10:35:14 -0500 +Subject: [PATCH 03/18] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [3/18] 0fe85bcd3683b2424bcd91ad1495d1b79eb07405 + +JIRA: https://issues.redhat.com/browse/RHEL-21843 +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.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch new file mode 100644 index 0000000..bbda006 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch @@ -0,0 +1,78 @@ +From d51f47c8654f44a787d70b675830ebc7a4ea74f6 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 15 Feb 2024 11:51:09 -0500 +Subject: [PATCH 06/18] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [6/18] 58ad218f1216ac1ea34ca01ef8cc21e207e2eaf2 + +JIRA: https://issues.redhat.com/browse/RHEL-21845 +CVE: CVE-2022-45231 +Upstream: Merged + +commit bbfee34f4188ac00371abe1389ae9c9fb989a0cd +Author: Doug Flick +Date: Fri Jan 26 05:54:48 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536 + + Bug Overview: + PixieFail Bug #3 + CVE-2023-45231 + CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N + CWE-125 Out-of-bounds Read + + Out-of-bounds read when handling a ND Redirect message with truncated + options + + Change Overview: + + Adds a check to prevent truncated options from being parsed + + // + + // Cannot process truncated options. + + // Cannot process options with a length of 0 as there is no Type + field. + + // + + if (OptionLen < sizeof (IP6_OPTION_HEADER)) { + + return FALSE; + + } + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Ip6Dxe/Ip6Option.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c +index 199eea124d..8718d5d875 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c +@@ -137,6 +137,14 @@ Ip6IsNDOptionValid ( + return FALSE; + } + ++ // ++ // Cannot process truncated options. ++ // Cannot process options with a length of 0 as there is no Type field. ++ // ++ if (OptionLen < sizeof (IP6_OPTION_HEADER)) { ++ return FALSE; ++ } ++ + Offset = 0; + + // +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch new file mode 100644 index 0000000..307d160 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch @@ -0,0 +1,277 @@ +From a5757e84bd77ad98580c50ba81da2d1daf0f147a Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 14 Feb 2024 12:24:44 -0500 +Subject: [PATCH 07/18] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit + Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [7/18] 57d08b408b30ea98de1e5dfd74f8892b66c0867c + +JIRA: https://issues.redhat.com/browse/RHEL-21845 +CVE: CVE-2022-45231 +Upstream: Merged + +commit 6f77463d72807ec7f4ed6518c3dac29a1040df9f +Author: Doug Flick +Date: Fri Jan 26 05:54:49 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536 + + Validates that the patch for... + + Out-of-bounds read when handling a ND Redirect message with truncated + options + + .. has been fixed + + Tests the following function to ensure that an out of bounds read does + not occur + Ip6OptionValidation + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 20 +++ + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 42 ++++++ + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++ + NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 + + 4 files changed, 192 insertions(+) + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp + +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp +new file mode 100644 +index 0000000000..6ebfd5fdfb +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp +@@ -0,0 +1,20 @@ ++/** @file ++ Acts as the main entry point for the tests for the Ip6Dxe 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/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +new file mode 100644 +index 0000000000..6e4de0745f +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +@@ -0,0 +1,42 @@ ++## @file ++# Unit test suite for the Ip6Dxe using Google Test ++# ++# Copyright (c) Microsoft Corporation.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++## ++[Defines] ++ INF_VERSION = 0x00010017 ++ BASE_NAME = Ip6DxeUnitTest ++ FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A ++ 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] ++ Ip6DxeGoogleTest.cpp ++ Ip6OptionGoogleTest.cpp ++ ../Ip6Option.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/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +new file mode 100644 +index 0000000000..f2cd90e1a9 +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +@@ -0,0 +1,129 @@ ++/** @file ++ Tests for Ip6Option.c. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++#include ++ ++extern "C" { ++ #include ++ #include ++ #include ++ #include "../Ip6Impl.h" ++ #include "../Ip6Option.h" ++} ++ ++///////////////////////////////////////////////////////////////////////// ++// Defines ++/////////////////////////////////////////////////////////////////////// ++ ++#define IP6_PREFIX_INFO_OPTION_DATA_LEN 32 ++#define OPTION_HEADER_IP6_PREFIX_DATA_LEN (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN) ++ ++//////////////////////////////////////////////////////////////////////// ++// Symbol Definitions ++// These functions are not directly under test - but required to compile ++//////////////////////////////////////////////////////////////////////// ++UINT32 mIp6Id; ++ ++EFI_STATUS ++Ip6SendIcmpError ( ++ IN IP6_SERVICE *IpSb, ++ IN NET_BUF *Packet, ++ IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL, ++ IN EFI_IPv6_ADDRESS *DestinationAddress, ++ IN UINT8 Type, ++ IN UINT8 Code, ++ IN UINT32 *Pointer OPTIONAL ++ ) ++{ ++ // .. ++ return EFI_SUCCESS; ++} ++ ++//////////////////////////////////////////////////////////////////////// ++// Ip6OptionValidation Tests ++//////////////////////////////////////////////////////////////////////// ++ ++// Define a fixture for your tests if needed ++class Ip6OptionValidationTest : public ::testing::Test { ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description: ++// Null option should return false ++TEST_F (Ip6OptionValidationTest, NullOptionShouldReturnFalse) { ++ UINT8 *option = nullptr; ++ UINT16 optionLen = 10; // Provide a suitable length ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Truncated option should return false ++TEST_F (Ip6OptionValidationTest, TruncatedOptionShouldReturnFalse) { ++ UINT8 option[] = { 0x01 }; // Provide a truncated option ++ UINT16 optionLen = 1; ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with zero length should return false ++TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 0; ++ UINT8 option[sizeof (IP6_OPTION_HEADER)]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER); ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with valid length should return true ++TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 4; // Length 4 * 8 = 32 ++ UINT8 option[OPTION_HEADER_IP6_PREFIX_DATA_LEN]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ ++ EXPECT_TRUE (Ip6IsNDOptionValid (option, IP6_PREFIX_INFO_OPTION_DATA_LEN)); ++} ++ ++// Test Description: ++// Ip6OptionPrefixInfo Option with invalid length should return false ++TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) { ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPrefixInfo; ++ optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid) ++ UINT8 option[sizeof (IP6_OPTION_HEADER)]; ++ ++ CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER)); ++ UINT16 optionLen = sizeof (IP6_OPTION_HEADER); ++ ++ EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); ++} +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index 24dee654df..7fa7b0f9d5 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -26,6 +26,7 @@ + # Build HOST_APPLICATION that tests NetworkPkg + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf ++ NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf + + # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests. + [LibraryClasses] +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch new file mode 100644 index 0000000..d70602f --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch @@ -0,0 +1,377 @@ +From ff4f1d8227c6c4c89060e24df37defec6d7a07e2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 15 Feb 2024 11:51:09 -0500 +Subject: [PATCH 08/18] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [8/18] c7bf831954da5b678450f1ba8e34371645959c81 + +JIRA: https://issues.redhat.com/browse/RHEL-21847 +CVE: CVE-2022-45232 +Upstream: Merged + +JIRA: https://issues.redhat.com/browse/RHEL-21849 +CVE: CVE-2022-45233 +Upstream: Merged + +commit 4df0229ef992d4f2721a8508787ebf9dc81fbd6e +Author: Doug Flick +Date: Fri Jan 26 05:54:50 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537 + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538 + + Bug Details: + PixieFail Bug #4 + CVE-2023-45232 + CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop') + + Infinite loop when parsing unknown options in the Destination Options + header + + PixieFail Bug #5 + CVE-2023-45233 + CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop') + + Infinite loop when parsing a PadN option in the Destination Options + header + + Change Overview: + + Most importantly this change corrects the following incorrect math + and cleans up the code. + + > // It is a PadN option + > // + > - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2); + > + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length; + > + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + + > case Ip6OptionSkip: + > - Offset = (UINT8)(Offset + *(Option + Offset + 1)); + > OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length; + > Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + + Additionally, this change also corrects incorrect math where the calling + function was calculating the HDR EXT optionLen as a uint8 instead of a + uint16 + + > - OptionLen = (UINT8)((*Option + 1) * 8 - 2); + > + OptionLen = IP6_HDR_EXT_LEN (*Option) - + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN; + + Additionally this check adds additional logic to santize the incoming + data + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + NetworkPkg/Ip6Dxe/Ip6Nd.h | 35 ++++++++++++++++ + NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++----- + NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++ + 3 files changed, 171 insertions(+), 11 deletions(-) + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h +index 860934a167..bf64e9114e 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h +@@ -56,13 +56,48 @@ VOID + VOID *Context + ); + ++// ++// Per RFC8200 Section 4.2 ++// ++// Two of the currently-defined extension headers -- the Hop-by-Hop ++// Options header and the Destination Options header -- carry a variable ++// number of type-length-value (TLV) encoded "options", of the following ++// format: ++// ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - ++// | Option Type | Opt Data Len | Option Data ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - - ++// ++// Option Type 8-bit identifier of the type of option. ++// ++// Opt Data Len 8-bit unsigned integer. Length of the Option ++// Data field of this option, in octets. ++// ++// Option Data Variable-length field. Option-Type-specific ++// data. ++// + typedef struct _IP6_OPTION_HEADER { ++ /// ++ /// identifier of the type of option. ++ /// + UINT8 Type; ++ /// ++ /// Length of the Option Data field of this option, in octets. ++ /// + UINT8 Length; ++ /// ++ /// Option-Type-specific data. ++ /// + } IP6_OPTION_HEADER; + + STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long."); + ++#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length) ++STATIC_ASSERT ( ++ IP6_NEXT_OPTION_OFFSET (0, 0) == 2, ++ "The next option is minimally the combined size of the option tag and length" ++ ); ++ + typedef struct _IP6_ETHE_ADDR_OPTION { + UINT8 Type; + UINT8 Length; +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c +index 8718d5d875..fd97ce116f 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.c ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.c +@@ -17,7 +17,8 @@ + @param[in] IpSb The IP6 service data. + @param[in] Packet The to be validated packet. + @param[in] Option The first byte of the option. +- @param[in] OptionLen The length of the whole option. ++ @param[in] OptionLen The length of all options, expressed in byte length of octets. ++ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255. + @param[in] Pointer Identifies the octet offset within + the invoking packet where the error was detected. + +@@ -31,12 +32,33 @@ Ip6IsOptionValid ( + IN IP6_SERVICE *IpSb, + IN NET_BUF *Packet, + IN UINT8 *Option, +- IN UINT8 OptionLen, ++ IN UINT16 OptionLen, + IN UINT32 Pointer + ) + { +- UINT8 Offset; +- UINT8 OptionType; ++ UINT16 Offset; ++ UINT8 OptionType; ++ UINT8 OptDataLen; ++ ++ if (Option == NULL) { ++ ASSERT (Option != NULL); ++ return FALSE; ++ } ++ ++ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) { ++ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH); ++ return FALSE; ++ } ++ ++ if (Packet == NULL) { ++ ASSERT (Packet != NULL); ++ return FALSE; ++ } ++ ++ if (IpSb == NULL) { ++ ASSERT (IpSb != NULL); ++ return FALSE; ++ } + + Offset = 0; + +@@ -54,7 +76,8 @@ Ip6IsOptionValid ( + // + // It is a PadN option + // +- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2); ++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length; ++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + break; + case Ip6OptionRouterAlert: + // +@@ -69,7 +92,8 @@ Ip6IsOptionValid ( + // + switch (OptionType & Ip6OptionMask) { + case Ip6OptionSkip: +- Offset = (UINT8)(Offset + *(Option + Offset + 1)); ++ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length; ++ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); + break; + case Ip6OptionDiscard: + return FALSE; +@@ -308,7 +332,7 @@ Ip6IsExtsValid ( + UINT32 Pointer; + UINT32 Offset; + UINT8 *Option; +- UINT8 OptionLen; ++ UINT16 OptionLen; + BOOLEAN Flag; + UINT8 CountD; + UINT8 CountA; +@@ -385,6 +409,36 @@ Ip6IsExtsValid ( + // Fall through + // + case IP6_DESTINATION: ++ // ++ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23 ++ // ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // | Next Header | Hdr Ext Len | | ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++ // | | ++ // . . ++ // . Options . ++ // . . ++ // | | ++ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // ++ // ++ // Next Header 8-bit selector. Identifies the type of header ++ // immediately following the Destination Options ++ // header. Uses the same values as the IPv4 ++ // Protocol field [RFC-1700 et seq.]. ++ // ++ // Hdr Ext Len 8-bit unsigned integer. Length of the ++ // Destination Options header in 8-octet units, not ++ // including the first 8 octets. ++ // ++ // Options Variable-length field, of length such that the ++ // complete Destination Options header is an ++ // integer multiple of 8 octets long. Contains one ++ // or more TLV-encoded options, as described in ++ // section 4.2. ++ // ++ + if (*NextHeader == IP6_DESTINATION) { + CountD++; + } +@@ -398,7 +452,7 @@ Ip6IsExtsValid ( + + Offset++; + Option = ExtHdrs + Offset; +- OptionLen = (UINT8)((*Option + 1) * 8 - 2); ++ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR); + Option++; + Offset++; + +@@ -430,7 +484,7 @@ Ip6IsExtsValid ( + // + // Ignore the routing header and proceed to process the next header. + // +- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8; ++ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen); + + if (UnFragmentLen != NULL) { + *UnFragmentLen = Offset; +@@ -441,7 +495,7 @@ Ip6IsExtsValid ( + // to the packet's source address, pointing to the unrecognized routing + // type. + // +- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER); ++ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER); + if ((IpSb != NULL) && (Packet != NULL) && + !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) + { +@@ -527,7 +581,7 @@ Ip6IsExtsValid ( + // + // RFC2402, Payload length is specified in 32-bit words, minus "2". + // +- OptionLen = (UINT8)((*Option + 2) * 4); ++ OptionLen = ((UINT16)(*Option + 2) * 4); + Offset = Offset + OptionLen; + break; + +diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h +index bd8e223c8a..fb07c28f5a 100644 +--- a/NetworkPkg/Ip6Dxe/Ip6Option.h ++++ b/NetworkPkg/Ip6Dxe/Ip6Option.h +@@ -12,6 +12,77 @@ + + #define IP6_FRAGMENT_OFFSET_MASK (~0x3) + ++// ++// For more information see RFC 8200, Section 4.3, 4.4, and 4.6 ++// ++// This example format is from section 4.6 ++// This does not apply to fragment headers ++// ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | Next Header | Hdr Ext Len | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ++// | | ++// . . ++// . Header-Specific Data . ++// . . ++// | | ++// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// ++// Next Header 8-bit selector. Identifies the type of ++// header immediately following the extension ++// header. Uses the same values as the IPv4 ++// Protocol field [IANA-PN]. ++// ++// Hdr Ext Len 8-bit unsigned integer. Length of the ++// Destination Options header in 8-octet units, ++// not including the first 8 octets. ++ ++// ++// These defines apply to the following: ++// 1. Hop by Hop ++// 2. Routing ++// 3. Destination ++// ++typedef struct _IP6_EXT_HDR { ++ /// ++ /// The Next Header field identifies the type of header immediately ++ /// ++ UINT8 NextHeader; ++ /// ++ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options ++ /// ++ UINT8 HdrExtLen; ++ /// ++ /// Header-Specific Data ++ /// ++} IP6_EXT_HDR; ++ ++STATIC_ASSERT ( ++ sizeof (IP6_EXT_HDR) == 2, ++ "The combined size of Next Header and Len is two 8 bit fields" ++ ); ++ ++// ++// IPv6 extension headers contain an 8-bit length field which describes the size of ++// the header. However, the length field only includes the size of the extension ++// header options, not the size of the first 8 bytes of the header. Therefore, in ++// order to calculate the full size of the extension header, we add 1 (to account ++// for the first 8 bytes omitted by the length field reporting) and then multiply ++// by 8 (since the size is represented in 8-byte units). ++// ++// a is the length field of the extension header (UINT8) ++// The result may be up to 2046 octets (UINT16) ++// ++#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8) ++ ++// This is the maxmimum length permissible by a extension header ++// Length is UINT8 of 8 octets not including the first 8 octets ++#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR)) ++STATIC_ASSERT ( ++ IP6_MAX_EXT_DATA_LENGTH == 2046, ++ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2" ++ ); ++ + typedef struct _IP6_FRAGMENT_HEADER { + UINT8 NextHeader; + UINT8 Reserved; +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch new file mode 100644 index 0000000..6d2cd51 --- /dev/null +++ b/edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch @@ -0,0 +1,430 @@ +From dab03ad5334af1c93797119f2eeda6ce757461f8 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 14 Feb 2024 20:25:29 -0500 +Subject: [PATCH 09/18] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit + Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [9/18] f68829a7f34f5a09a02d28cc5cfd109f90c442da + +JIRA: https://issues.redhat.com/browse/RHEL-21847 +CVE: CVE-2022-45232 +Upstream: Merged + +commit c9c87f08dd6ace36fa843424522c3558a8374cac +Author: Doug Flick +Date: Fri Jan 26 05:54:51 2024 +0800 + + NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537 + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538 + + Unit tests to confirm that.. + Infinite loop when parsing unknown options in the Destination Options + header + + and + + Infinite loop when parsing a PadN option in the Destination Options + header + + ... have been patched + + This patch tests the following functions: + Ip6IsOptionValid + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + +Signed-off-by: Jon Maloy +--- + .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 10 +- + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 278 ++++++++++++++++++ + .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h | 40 +++ + 3 files changed, 324 insertions(+), 4 deletions(-) + create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h + +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +index 6e4de0745f..ba29dbabad 100644 +--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +@@ -1,13 +1,13 @@ + ## @file +-# Unit test suite for the Ip6Dxe using Google Test ++# Unit test suite for the Ip6DxeGoogleTest using Google Test + # + # Copyright (c) Microsoft Corporation.
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + ## + [Defines] + INF_VERSION = 0x00010017 +- BASE_NAME = Ip6DxeUnitTest +- FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A ++ BASE_NAME = Ip6DxeGoogleTest ++ FILE_GUID = AE39981C-B7FE-41A8-A9C2-F41910477CA3 + VERSION_STRING = 1.0 + MODULE_TYPE = HOST_APPLICATION + # +@@ -16,9 +16,11 @@ + # VALID_ARCHITECTURES = IA32 X64 AARCH64 + # + [Sources] ++ ../Ip6Option.c ++ Ip6OptionGoogleTest.h + Ip6DxeGoogleTest.cpp + Ip6OptionGoogleTest.cpp +- ../Ip6Option.c ++ Ip6OptionGoogleTest.h + + [Packages] + MdePkg/MdePkg.dec +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +index f2cd90e1a9..29f8a4a96e 100644 +--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp +@@ -12,6 +12,7 @@ extern "C" { + #include + #include "../Ip6Impl.h" + #include "../Ip6Option.h" ++ #include "Ip6OptionGoogleTest.h" + } + + ///////////////////////////////////////////////////////////////////////// +@@ -127,3 +128,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) + + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); + } ++ ++//////////////////////////////////////////////////////////////////////// ++// Ip6IsOptionValid Tests ++//////////////////////////////////////////////////////////////////////// ++ ++// Define a fixture for your tests if needed ++class Ip6IsOptionValidTest : public ::testing::Test { ++protected: ++ // Add any setup code if needed ++ virtual void ++ SetUp ( ++ ) ++ { ++ // Initialize any resources or variables ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description ++// Verify that a NULL option is Invalid ++TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ IP6_SERVICE *IpSb = NULL; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 0 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly ++ ++ // This should be a valid option even though the length is 0 ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 1 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that an unknown option with a length of 2 and type of does not cause an infinite loop ++TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 2; // Valid length for an unknown option ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that Ip6OptionPad1 is valid with a length of 0 ++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPad1; ++ optionHeader.Length = 0; ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that Ip6OptionPadN doesn't overflow with various lengths ++TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = Ip6OptionPadN; ++ optionHeader.Length = 0xFF; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFE; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFD; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFC; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify an unknown option doesn't cause an infinite loop with various lengths ++TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) { ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ IP6_OPTION_HEADER optionHeader; ++ ++ optionHeader.Type = 23; // Unknown Option ++ optionHeader.Length = 0xFF; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFE; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFD; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++ ++ optionHeader.Length = 0xFC; ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0)); ++} ++ ++// Test Description ++// Verify that the function supports multiple options ++TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) { ++ UINT16 HdrLen; ++ NET_BUF Packet = { 0 }; ++ // we need to define enough of the packet to make the function work ++ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above ++ UINT32 DeadCode = 0xDeadC0de; ++ // Don't actually use this pointer, just pass it to the function, nothing will be done with it ++ IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode; ++ ++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 }; ++ EFI_IP6_HEADER Ip6Header = { 0 }; ++ ++ Ip6Header.SourceAddress = SourceAddress; ++ Ip6Header.DestinationAddress = DestinationAddress; ++ Packet.Ip.Ip6 = &Ip6Header; ++ ++ UINT8 ExtHdr[1024] = { 0 }; ++ UINT8 *Cursor = ExtHdr; ++ IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr; ++ ++ // Let's start chaining options ++ ++ Option->Type = 23; // Unknown Option ++ Option->Length = 0xFC; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionPad1; ++ ++ Cursor += sizeof (1); ++ ++ // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionRouterAlert; ++ Option->Length = 4; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 4; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionPadN; ++ Option->Length = 0xFC; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC; ++ ++ Option = (IP6_OPTION_HEADER *)Cursor; ++ Option->Type = Ip6OptionRouterAlert; ++ Option->Length = 4; ++ ++ Cursor += sizeof (IP6_OPTION_HEADER) + 4; ++ ++ // Total 524 ++ ++ HdrLen = (UINT16)(Cursor - ExtHdr); ++ ++ EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0)); ++} +diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h +new file mode 100644 +index 0000000000..0509b6ae30 +--- /dev/null ++++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h +@@ -0,0 +1,40 @@ ++/** @file ++ Exposes the functions needed to test the Ip6Option module. ++ ++ Copyright (c) Microsoft Corporation ++ SPDX-License-Identifier: BSD-2-Clause-Patent ++**/ ++ ++#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_ ++#define IP6_OPTION_HEADER_GOOGLE_TEST_H_ ++ ++#include ++#include "../Ip6Impl.h" ++ ++/** ++ Validate the IP6 option format for both the packets we received ++ and that we will transmit. It will compute the ICMPv6 error message fields ++ if the option is malformatted. ++ ++ @param[in] IpSb The IP6 service data. ++ @param[in] Packet The to be validated packet. ++ @param[in] Option The first byte of the option. ++ @param[in] OptionLen The length of the whole option. ++ @param[in] Pointer Identifies the octet offset within ++ the invoking packet where the error was detected. ++ ++ ++ @retval TRUE The option is properly formatted. ++ @retval FALSE The option is malformatted. ++ ++**/ ++BOOLEAN ++Ip6IsOptionValid ( ++ IN IP6_SERVICE *IpSb, ++ IN NET_BUF *Packet, ++ IN UINT8 *Option, ++ IN UINT16 OptionLen, ++ IN UINT32 Pointer ++ ); ++ ++#endif // __IP6_OPTION_HEADER_GOOGLE_TEST_H__ +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch new file mode 100644 index 0000000..b62e054 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch @@ -0,0 +1,168 @@ +From 1afdf854f67fbaeea47f15efa0c34c0f1fe6a504 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 10/18] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [10/18] c7527c63ebe3afb55a2ef78103c1a57de26c36b7 + +JIRA: https://issues.redhat.com/browse/RHEL-21851 +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.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch new file mode 100644 index 0000000..bd66c13 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch @@ -0,0 +1,511 @@ +From d60257df151a6c58aefe74c2d2baee59344318d2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 11/18] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [11/18] b917383d597172d4bf75548d9b281d08bf34e299 + +JIRA: https://issues.redhat.com/browse/RHEL-21851 +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 | 1 + + .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 300 ++++++++++++++++++ + .../GoogleTest/PxeBcDhcp6GoogleTest.h | 50 +++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 ++ + .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 48 +++ + 5 files changed, 418 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 7fa7b0f9d5..a0273c4310 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -27,6 +27,7 @@ + # + 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.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch new file mode 100644 index 0000000..43c0be5 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch @@ -0,0 +1,257 @@ +From b57bd437db8cff7b7a206e3cd694b7821014ba53 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 12/18] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 + Patch + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [12/18] 310a770792d1a81dbf54ee372f926541309492e8 + +JIRA: https://issues.redhat.com/browse/RHEL-21853 +CVE: CVE-2022-45235 +Upstream: Merged + +commit fac297724e6cc343430cd0104e55cd7a96d1151e +Author: Doug Flick +Date: Fri Jan 26 05:54:55 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540 + + Bug Details: + PixieFail Bug #7 + CVE-2023-45235 + 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 handling Server ID option from a DHCPv6 proxy + Advertise message + + Change Overview: + + Performs two checks + + 1. Checks that the length of the duid is accurate + > + // + > + // Check that the minimum and maximum requirements are met + > + // + > + if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || + (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { + > + Status = EFI_INVALID_PARAMETER; + > + goto ON_ERROR; + > + } + + 2. Ensures that the amount of data written to the buffer is tracked and + never exceeds that + > + // + > + // Check that the option length is valid. + > + // + > + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) + > DiscoverLenNeeded) { + > + Status = EFI_OUT_OF_RESOURCES; + > + goto ON_ERROR; + > + } + + Additional code clean up and fix for memory leak in case Option was NULL + + 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 | 77 ++++++++++++++++++++++------ + NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++ + 2 files changed, 78 insertions(+), 16 deletions(-) + +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +index 2b2d372889..7fd1281c11 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c +@@ -887,6 +887,7 @@ PxeBcRequestBootService ( + EFI_STATUS Status; + EFI_DHCP6_PACKET *IndexOffer; + UINT8 *Option; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Request = Private->Dhcp6Request; +@@ -899,7 +900,8 @@ PxeBcRequestBootService ( + return EFI_DEVICE_ERROR; + } + +- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET)); ++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); ++ Discover = AllocateZeroPool (DiscoverLenNeeded); + if (Discover == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -924,16 +926,34 @@ PxeBcRequestBootService ( + DHCP6_OPT_SERVER_ID + ); + if (Option == NULL) { +- return EFI_NOT_FOUND; ++ Status = EFI_NOT_FOUND; ++ goto ON_ERROR; + } + + // + // Add Server ID Option. + // + OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen); +- CopyMem (DiscoverOpt, Option, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ ++ // ++ // Check that the minimum and maximum requirements are met ++ // ++ if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) || (OpLen > PXEBC_MAX_SIZE_OF_DUID)) { ++ Status = EFI_INVALID_PARAMETER; ++ goto ON_ERROR; ++ } ++ ++ // ++ // Check that the option length is valid. ++ // ++ if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ ++ CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + while (RequestLen < Request->Length) { +@@ -944,16 +964,24 @@ PxeBcRequestBootService ( + (OpCode != DHCP6_OPT_SERVER_ID) + ) + { ++ // ++ // Check that the option length is valid. ++ // ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option and Server ID + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + +- RequestOpt += (OpLen + 4); +- RequestLen += (OpLen + 4); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + // +@@ -2154,6 +2182,7 @@ PxeBcDhcp6Discover ( + UINT16 OpLen; + UINT32 Xid; + EFI_STATUS Status; ++ UINTN DiscoverLenNeeded; + + PxeBc = &Private->PxeBc; + Mode = PxeBc->Mode; +@@ -2169,7 +2198,8 @@ PxeBcDhcp6Discover ( + return EFI_DEVICE_ERROR; + } + +- Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET)); ++ DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET); ++ Discover = AllocateZeroPool (DiscoverLenNeeded); + if (Discover == NULL) { + return EFI_OUT_OF_RESOURCES; + } +@@ -2185,22 +2215,37 @@ PxeBcDhcp6Discover ( + DiscoverLen = sizeof (EFI_DHCP6_HEADER); + RequestLen = DiscoverLen; + ++ // ++ // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence, ++ // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are ++ // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes, ++ // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with ++ // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously ++ // generated and sent. ++ // ++ // Therefore while this code looks like it could overflow, in practice it's not possible. ++ // + 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)) + { ++ if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) { ++ Status = EFI_OUT_OF_RESOURCES; ++ goto ON_ERROR; ++ } ++ + // + // Copy all the options except IA option. + // +- CopyMem (DiscoverOpt, RequestOpt, OpLen + 4); +- DiscoverOpt += (OpLen + 4); +- DiscoverLen += (OpLen + 4); ++ CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + +- RequestOpt += (OpLen + 4); +- RequestLen += (OpLen + 4); ++ RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); ++ RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN); + } + + Status = PxeBc->UdpWrite ( +diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h +index c86f6d391b..6357d27fae 100644 +--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h ++++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h +@@ -34,6 +34,23 @@ + #define PXEBC_ADDR_START_DELIMITER '[' + #define PXEBC_ADDR_END_DELIMITER ']' + ++// ++// A DUID consists of a 2-octet type code represented in network byte ++// order, followed by a variable number of octets that make up the ++// actual identifier. The length of the DUID (not including the type ++// code) is at least 1 octet and at most 128 octets. ++// ++#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1) ++#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128) ++ ++// ++// This define represents the combineds code and length field from ++// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1 ++// ++#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN \ ++ (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \ ++ sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen)) ++ + #define GET_NEXT_DHCP6_OPTION(Opt) \ + (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \ + sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1) +-- +2.39.3 + diff --git a/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch new file mode 100644 index 0000000..3297cc0 --- /dev/null +++ b/edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch @@ -0,0 +1,409 @@ +From 59b9d468ebf6be2a5c53d7979c12040f9b41c2c2 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 13/18] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 + Unit Tests + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [13/18] 074410155526b2ee2a74cf161ea46385932da059 + +JIRA: https://issues.redhat.com/browse/RHEL-21853 +CVE: CVE-2022-45235 +Upstream: Merged + +commit ff2986358f75d8f58ef08a66fe673539c9c48f41 +Author: Doug Flick +Date: Fri Jan 26 05:54:56 2024 +0800 + + NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests + + REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540 + + Unit tests to confirm that the bug.. + + Buffer overflow when handling Server ID option from a DHCPv6 proxy + Advertise message + + ..has been patched. + + This patch contains unit tests for the following functions: + PxeBcRequestBootService + PxeBcDhcp6Discover + + 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 | 5 +- + .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 278 +++++++++++++++++- + .../GoogleTest/PxeBcDhcp6GoogleTest.h | 18 ++ + 3 files changed, 298 insertions(+), 3 deletions(-) + +diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc +index a0273c4310..fa301a7a52 100644 +--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc ++++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc +@@ -27,7 +27,10 @@ + # + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf + NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf +- NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf ++ NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf { ++ ++ UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.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 +index 8260eeee50..bd423ebadf 100644 +--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp +@@ -4,7 +4,9 @@ + Copyright (c) Microsoft Corporation + SPDX-License-Identifier: BSD-2-Clause-Patent + **/ +-#include ++#include ++#include ++#include + + extern "C" { + #include +@@ -19,7 +21,8 @@ extern "C" { + // Definitions + /////////////////////////////////////////////////////////////////////////////// + +-#define PACKET_SIZE (1500) ++#define PACKET_SIZE (1500) ++#define REQUEST_OPTION_LENGTH (120) + + typedef struct { + UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03) +@@ -76,6 +79,26 @@ MockConfigure ( + } + + // Needed by PxeBcSupport ++EFI_STATUS ++PxeBcDns6 ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN CHAR16 *HostName, ++ OUT EFI_IPv6_ADDRESS *IpAddress ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ ++UINT32 ++PxeBcBuildDhcp6Options ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ OUT EFI_DHCP6_PACKET_OPTION **OptList, ++ IN UINT8 *Buffer ++ ) ++{ ++ return EFI_SUCCESS; ++} ++ + EFI_STATUS + EFIAPI + QueueDpc ( +@@ -159,6 +182,10 @@ TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) { + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR); + } + ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcCacheDnsServerAddresses Tests ++/////////////////////////////////////////////////////////////////////////////// ++ + class PxeBcCacheDnsServerAddressesTest : public ::testing::Test { + public: + PXEBC_PRIVATE_DATA Private = { 0 }; +@@ -298,3 +325,250 @@ TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) { + FreePool (Private.DnsServer); + } + } ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcRequestBootServiceTest Test Cases ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcRequestBootServiceTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ ++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; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) { ++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl; ++ ++ DHCP6_OPTION_SERVER_ID Server = { 0 }; ++ ++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID); ++ Server.OptionLen = HTONS (16); // valid length ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &Server, sizeof (Server)); ++ Cursor += sizeof (Server); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) { ++ PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl; ++ ++ DHCP6_OPTION_SERVER_ID Server = { 0 }; ++ ++ Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID); ++ Server.OptionLen = HTONS (1500); // This length would overflow without a check ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &Server, sizeof (Server)); ++ Cursor += sizeof (Server); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ // This is going to be stopped by the duid overflow check ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_INVALID_PARAMETER); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) { ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = 0; // valid length ++ ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index]; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS); ++} ++ ++TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) { ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = 1500; // this length would overflow without a check ++ ++ UINT8 Index = 0; ++ ++ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index]; ++ ++ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ // Update the packet length ++ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet); ++ Packet->Size = PACKET_SIZE; ++ ++ ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES); ++} ++ ++/////////////////////////////////////////////////////////////////////////////// ++// PxeBcDhcp6Discover Test ++/////////////////////////////////////////////////////////////////////////////// ++ ++class PxeBcDhcp6DiscoverTest : public ::testing::Test { ++public: ++ PXEBC_PRIVATE_DATA Private = { 0 }; ++ EFI_UDP6_PROTOCOL Udp6Read; ++ ++protected: ++ MockUefiRuntimeServicesTableLib RtServicesMock; ++ ++ // 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; ++ } ++ ++ // Add any cleanup code if needed ++ virtual void ++ TearDown ( ++ ) ++ { ++ if (Private.Dhcp6Request != NULL) { ++ FreePool (Private.Dhcp6Request); ++ } ++ ++ // Clean up any resources or variables ++ } ++}; ++ ++// Test Description ++// This will cause an overflow by an untrusted packet during the option parsing ++TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) { ++ EFI_IPv6_ADDRESS DestIp = { 0 }; ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = HTONS (0xFFFF); // overflow ++ ++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request); ++ ++ EXPECT_CALL (RtServicesMock, gRT_GetTime) ++ .WillOnce (::testing::Return (0)); ++ ++ ASSERT_EQ ( ++ PxeBcDhcp6Discover ( ++ &(PxeBcDhcp6DiscoverTest::Private), ++ 0, ++ NULL, ++ FALSE, ++ (EFI_IP_ADDRESS *)&DestIp ++ ), ++ EFI_OUT_OF_RESOURCES ++ ); ++} ++ ++// Test Description ++// This will test that we can handle a packet with a valid option length ++TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) { ++ EFI_IPv6_ADDRESS DestIp = { 0 }; ++ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter ++ ++ RequestOpt.OpCode = HTONS (0x1337); ++ RequestOpt.OpLen = HTONS (0x30); ++ ++ UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option); ++ ++ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt)); ++ Cursor += sizeof (RequestOpt); ++ ++ Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request); ++ ++ EXPECT_CALL (RtServicesMock, gRT_GetTime) ++ .WillOnce (::testing::Return (0)); ++ ++ ASSERT_EQ ( ++ PxeBcDhcp6Discover ( ++ &(PxeBcDhcp6DiscoverTest::Private), ++ 0, ++ NULL, ++ FALSE, ++ (EFI_IP_ADDRESS *)&DestIp ++ ), ++ EFI_SUCCESS ++ ); ++} +diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +index b17c314791..0d825e4425 100644 +--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h ++++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h +@@ -47,4 +47,22 @@ PxeBcCacheDnsServerAddresses ( + IN PXEBC_DHCP6_PACKET_CACHE *Cache6 + ); + ++/** ++ Build and send out the request packet for the bootfile, and parse the reply. ++ ++ @param[in] Private The pointer to PxeBc private data. ++ @param[in] Index PxeBc option boot item type. ++ ++ @retval EFI_SUCCESS Successfully discovered the boot file. ++ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. ++ @retval EFI_NOT_FOUND Can't get the PXE reply packet. ++ @retval Others Failed to discover the boot file. ++ ++**/ ++EFI_STATUS ++PxeBcRequestBootService ( ++ IN PXEBC_PRIVATE_DATA *Private, ++ IN UINT32 Index ++ ); ++ + #endif // PXE_BC_DHCP6_GOOGLE_TEST_H_ +-- +2.39.3 + diff --git a/edk2-NetworkPkg-Updating-SecurityFixes.yaml.patch b/edk2-NetworkPkg-Updating-SecurityFixes.yaml.patch new file mode 100644 index 0000000..39cb6d1 --- /dev/null +++ b/edk2-NetworkPkg-Updating-SecurityFixes.yaml.patch @@ -0,0 +1,51 @@ +From ababd8837103d4e504cc5d044a13fb9516543795 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Fri, 16 Feb 2024 10:48:05 -0500 +Subject: [PATCH 18/18] NetworkPkg: : Updating SecurityFixes.yaml + +RH-Author: Jon Maloy +RH-MergeRequest: 54: NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch +RH-Jira: RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek +RH-Commit: [18/18] e77d4ea79359b99e7d1073251d67909c2bfdb879 + +JIRA: https://issues.redhat.com/browse/RHEL-21841 +CVE: CVE-2023-45229 +Upstream: Merged + +commit 5fd3078a2e08f607dc86a16c1b184b6e30a34a49 +Author: Doug Flick +Date: Tue Feb 13 10:46:03 2024 -0800 + + NetworkPkg: : Updating SecurityFixes.yaml + + This captures the related security change for Dhcp6Dxe that is related + to CVE-2023-45229 + + Cc: Saloni Kasbekar + Cc: Zachary Clark-williams + Signed-off-by: Doug Flick [MSFT] + Reviewed-by: Saloni Kasbekar + Reviewed-by: Leif Lindholm + +Signed-off-by: Jon Maloy +--- + NetworkPkg/SecurityFixes.yaml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml +index 7e900483fe..fa42025e0d 100644 +--- a/NetworkPkg/SecurityFixes.yaml ++++ b/NetworkPkg/SecurityFixes.yaml +@@ -8,6 +8,7 @@ CVE_2023_45229: + commit_titles: + - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch" + - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests" ++ - "NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Related Patch" + cve: CVE-2023-45229 + date_reported: 2023-08-28 13:56 UTC + description: "Bug 01 - edk2/NetworkPkg: Out-of-bounds read when processing IA_NA/IA_TA options in a DHCPv6 Advertise message" +-- +2.39.3 + diff --git a/edk2.spec b/edk2.spec index e949af0..aef2af2 100644 --- a/edk2.spec +++ b/edk2.spec @@ -20,7 +20,7 @@ ExclusiveArch: x86_64 aarch64 Name: edk2 Version: %{GITDATE} -Release: 5%{?dist} +Release: 6%{?dist} Summary: UEFI firmware for 64-bit virtual machines License: BSD-2-Clause-Patent and Apache-2.0 and MIT URL: http://www.tianocore.org @@ -120,6 +120,150 @@ Patch50: edk2-MdePkg-ArchitecturalMsr.h-add-defines-for-MTRR-cache.patch Patch51: edk2-UefiCpuPkg-MtrrLib.h-use-cache-type-defines-from-Arc.patch # For RHEL-21704 - vGPU VM take several minutes to show tianocore logo if firmware is ovmf Patch52: edk2-OvmfPkg-Sec-use-cache-type-defines-from-Architectura.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch53: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch54: edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch55: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch56: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch57: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Un.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch58: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch59: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch60: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch61: edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch62: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch63: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch64: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch65: edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch66: edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch67: edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch68: edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch69: edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch +# For RHEL-21841 - CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21843 - CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9] +# For RHEL-21845 - CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9] +# For RHEL-21847 - CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9] +# For RHEL-21849 - TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9] +# For RHEL-21851 - CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9] +# For RHEL-21853 - TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9] +Patch70: edk2-NetworkPkg-Updating-SecurityFixes.yaml.patch # python3-devel and libuuid-devel are required for building tools. # python3-devel is also needed for varstore template generation and @@ -453,6 +597,40 @@ install -m 0644 \ %changelog +* Thu Feb 22 2024 Miroslav Rezanina - 20231122-6 +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Pa.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Add-Unit-tests-to-CI-and-create-Host-Test.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45230-Un.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Pa.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Un.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Patc.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45231-Unit.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Patc.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Ip6Dxe-SECURITY-PATCH-CVE-2023-45232-Unit.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p2.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p3.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-UefiPxeBcDxe-SECURITY-PATCH-CVE-2023-4523p4.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Adds-a-SecurityFix.yaml-file.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-SECURITY-PATCH-CVE-2023-45229-Re.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-Removes-duplicate-check-and-repl.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Dhcp6Dxe-Packet-Length-is-not-updated-bef.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- edk2-NetworkPkg-Updating-SecurityFixes.yaml.patch [RHEL-21841 RHEL-21843 RHEL-21845 RHEL-21847 RHEL-21849 RHEL-21851 RHEL-21853] +- Resolves: RHEL-21841 + (CVE-2023-45229 edk2: Integer underflow when processing IA_NA/IA_TA options in a DHCPv6 Advertise message [rhel-9]) +- Resolves: RHEL-21843 + (CVE-2023-45230 edk2: Buffer overflow in the DHCPv6 client via a long Server ID option [rhel-9]) +- Resolves: RHEL-21845 + (CVE-2023-45231 edk2: Out of Bounds read when handling a ND Redirect message with truncated options [rhel-9]) +- Resolves: RHEL-21847 + (CVE-2023-45232 edk2: Infinite loop when parsing unknown options in the Destination Options header [rhel-9]) +- Resolves: RHEL-21849 + (TRIAGE CVE-2023-45233 edk2: Infinite loop when parsing a PadN option in the Destination Options header [rhel-9]) +- Resolves: RHEL-21851 + (CVE-2023-45234 edk2: Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message [rhel-9]) +- Resolves: RHEL-21853 + (TRIAGE CVE-2023-45235 edk2: Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message [rhel-9]) + * Mon Feb 19 2024 Miroslav Rezanina - 20231122-5 - edk2-SecurityPkg-DxeTpm2MeasureBootLib-SECURITY-PATCH-4118.patch [RHEL-21157] - edk2-SecurityPkg-DxeTpmMeasureBootLib-SECURITY-PATCH-4118.patch [RHEL-21157]