public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack
@ 2024-01-24  3:33 Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
                   ` (14 more replies)
  0 siblings, 15 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams,
	Michael D Kinney, Liming Gao, Zhiguang Liu

The security patches contained in this series with the exception of
"MdePkg/Test: Add gRT_GetTime Google Test Mock" and
"NetworkPkg: : Adds a SecurityFix.yaml file" have been reviewed
during GHSA-hc6x-cw6p-gj7h infosec review.

This patch series contains the following security patches for the
security vulnerabilities found by QuarksLab in the EDK II Network
Stack:

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

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

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

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')

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')

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

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

NetworkPkg:
Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

MdePkg:
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>

Doug Flick (8):
  NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch
  NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests
  NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
  NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
  NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
  NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
  NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
  NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests

Douglas Flick [MSFT] (6):
  NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
  NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
  NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
  NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
  MdePkg: Test: Add gRT_GetTime Google Test Mock
  NetworkPkg: : Adds a SecurityFix.yaml file

 NetworkPkg/Test/NetworkPkgHostTest.dsc        | 105 +++
 .../GoogleTest/Dhcp6DxeGoogleTest.inf         |  44 +
 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf    |  44 +
 .../GoogleTest/UefiPxeBcDxeGoogleTest.inf     |  48 +
 .../Library/MockUefiRuntimeServicesTableLib.h |   7 +
 NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h               | 143 +++
 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h            |  78 +-
 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h   |  58 ++
 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h   |  40 +
 NetworkPkg/Ip6Dxe/Ip6Option.h                 |  89 ++
 .../GoogleTest/PxeBcDhcp6GoogleTest.h         |  68 ++
 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h          |  17 +
 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c                 | 612 ++++++++-----
 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c            | 373 ++++++--
 NetworkPkg/Ip6Dxe/Ip6Option.c                 |  84 +-
 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c          | 148 ++-
 .../MockUefiRuntimeServicesTableLib.cpp       |   5 +-
 .../GoogleTest/Dhcp6DxeGoogleTest.cpp         |  20 +
 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 839 ++++++++++++++++++
 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp    |  20 +
 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 411 +++++++++
 NetworkPkg/NetworkPkg.ci.yaml                 | 118 ++-
 NetworkPkg/SecurityFixes.yaml                 | 123 +++
 .../GoogleTest/PxeBcDhcp6GoogleTest.cpp       | 574 ++++++++++++
 .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp     |  19 +
 25 files changed, 3686 insertions(+), 401 deletions(-)
 create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
 create mode 100644 NetworkPkg/SecurityFixes.yaml
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp

-- 
2.43.0


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114252): https://edk2.groups.io/g/devel/message/114252
Mute This Topic: https://groups.io/mt/103926729/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 11:30   ` Gerd Hoffmann
  2024-01-24  3:33 ` [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535

SECURITY PATCH - Patch

TCBZ4535
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h    |  43 +++
 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h |  78 +++---
 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c      | 409 +++++++++++++++++++----------
 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 373 +++++++++++++++++++++-----
 4 files changed, 666 insertions(+), 237 deletions(-)

diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
index 0eb9c669b5a1..f2422c2f2827 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/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
index 046454ff4ac2..06947f6c1fcf 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.
+  Append the option to Buf, update the length of packet, and move 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.
+  @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 (
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
index dcd01e6268b1..bf5aa7a769de 100644
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
@@ -3,9 +3,9 @@
 
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+  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 e6368b5b1c6c..705c665c519d 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;
+  }
 
-  WriteUnaligned16 ((UINT16 *)Buf, OptType);
-  Buf += 2;
-  WriteUnaligned16 ((UINT16 *)Buf, OptLen);
-  Buf += 2;
-  CopyMem (Buf, Data, NTOHS (OptLen));
-  Buf += NTOHS (OptLen);
+  if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
 
-  return Buf;
+  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);
+
+  // Update the packet length by the length of the option + 4 bytes
+  Packet->Length += BytesNeeded;
+
+  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);
 
-  return Buf;
+  //
+  // Update the packet length
+  //
+  Packet->Length += BytesNeeded;
+
+  return EFI_SUCCESS;
 }
 
 /**
   Append the appointed Ia option to Buf, and move Buf to the end.
 
-  @param[in, out] Buf           The pointer to the position to append.
+  @param[in, out] Packet        A pointer to the packet, on success Packet->Length
+                                will be updated.
+  @param[in, out] PacketCursor  The pointer in the packet, on success PacketCursor
+                                will be moved to the end of the option.
   @param[in]      Ia            The pointer to the Ia.
   @param[in]      T1            The time of T1.
   @param[in]      T2            The time of T2.
   @param[in]      MessageType   Message type of DHCP6 package.
 
-  @return         Buf           The position to append the next Ia option.
+  @retval   EFI_INVALID_PARAMETER An argument provided to the function was invalid
+  @retval   EFI_BUFFER_TOO_SMALL  The buffer is too small to append the option.
+  @retval   EFI_SUCCESS           The option is appended successfully.
 
 **/
-UINT8 *
+EFI_STATUS
 Dhcp6AppendIaOption (
-  IN OUT UINT8         *Buf,
-  IN     EFI_DHCP6_IA  *Ia,
-  IN     UINT32        T1,
-  IN     UINT32        T2,
-  IN     UINT32        MessageType
+  IN OUT EFI_DHCP6_PACKET  *Packet,
+  IN OUT UINT8             **PacketCursor,
+  IN     EFI_DHCP6_IA      *Ia,
+  IN     UINT32            T1,
+  IN     UINT32            T2,
+  IN     UINT32            MessageType
   )
 {
-  UINT8   *AddrOpt;
-  UINT16  *Len;
-  UINTN   Index;
+  UINT8       *AddrOpt;
+  UINT16      *Len;
+  UINTN       Index;
+  UINT32      BytesNeeded;
+  UINT32      Length;
+  EFI_STATUS  Status;
 
   //
   //  The format of IA_NA and IA_TA option:
@@ -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;
 }
 
 /**
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114253): https://edk2.groups.io/g/devel/message/114253
Mute This Topic: https://groups.io/mt/103926731/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 11:39   ` Gerd Hoffmann
  2024-01-24  3:33 ` [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535

SECURITY PATCH - Unit Tests

TCBZ4535
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Test/NetworkPkgHostTest.dsc        |  99 ++++
 .../GoogleTest/Dhcp6DxeGoogleTest.inf         |  43 ++
 .../GoogleTest/Dhcp6DxeGoogleTest.cpp         |  20 +
 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
 NetworkPkg/NetworkPkg.ci.yaml                 | 118 ++---
 5 files changed, 695 insertions(+), 63 deletions(-)
 create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp

diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
new file mode 100644
index 000000000000..20bc90b1728d
--- /dev/null
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -0,0 +1,99 @@
+## @file
+# NetworkPkgHostTest DSC file used to build host-based unit tests.
+#
+# Copyright (c) Microsoft Corporation.<BR>
+# 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
+  #
+  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]
+  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
diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
new file mode 100644
index 000000000000..8e9119a37158
--- /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.<BR>
+# 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/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
new file mode 100644
index 000000000000..9aeced2f9156
--- /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 <gtest/gtest.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// Run the tests
+////////////////////////////////////////////////////////////////////////////////
+int
+main (
+  int   argc,
+  char  *argv[]
+  )
+{
+  testing::InitGoogleTest (&argc, argv);
+  return RUN_ALL_TESTS ();
+}
diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
new file mode 100644
index 000000000000..7ee40e4af480
--- /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 <gtest/gtest.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Library/BaseLib.h>
+  #include <Library/DebugLib.h>
+  #include <Library/BaseMemoryLib.h>
+  #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/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
index 07dc7abd6938..0060f7a2cb8f 100644
--- a/NetworkPkg/NetworkPkg.ci.yaml
+++ b/NetworkPkg/NetworkPkg.ci.yaml
@@ -7,73 +7,65 @@
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
 {
-    "LicenseCheck": {
-        "IgnoreFiles": []
-    },
+    "LicenseCheck": { "IgnoreFiles": [] },
     "EccCheck": {
-        ## Exception sample looks like below:
-        ## "ExceptionList": [
-        ##     "<ErrorID>", "<KeyWord>"
-        ## ]
-        "ExceptionList": [
-        ],
-        ## Both file path and directory path are accepted.
-        "IgnoreFiles": [
-        ]
-    },
-    "CompilerPlugin": {
-        "DscPath": "NetworkPkg.dsc"
-    },
-    "CharEncodingCheck": {
-        "IgnoreFiles": []
-    },
+            ## Exception sample looks like below:
+            ## "ExceptionList": [
+            ##     "<ErrorID>", "<KeyWord>"
+            ## ]
+            "ExceptionList": [],
+            ## Both file path and directory path are accepted.
+            "IgnoreFiles": [],
+        },
+    "CompilerPlugin": { "DscPath": "NetworkPkg.dsc" },
+    "HostUnitTestCompilerPlugin": { "DscPath": "Test/NetworkPkgHostTest.dsc" },
+    "CharEncodingCheck": { "IgnoreFiles": [] },
     "DependencyCheck": {
-        "AcceptableDependencies": [
-            "MdePkg/MdePkg.dec",
-            "MdeModulePkg/MdeModulePkg.dec",
-            "NetworkPkg/NetworkPkg.dec",
-            "CryptoPkg/CryptoPkg.dec"
-        ],
-        # For host based unit tests
-        "AcceptableDependencies-HOST_APPLICATION":[],
-        # For UEFI shell based apps
-        "AcceptableDependencies-UEFI_APPLICATION":[
-            "ShellPkg/ShellPkg.dec"
-        ],
-        "IgnoreInf": []
-    },
-    "DscCompleteCheck": {
-        "DscPath": "NetworkPkg.dsc",
-        "IgnoreInf": []
-    },
-    "GuidCheck": {
-        "IgnoreGuidName": [],
-        "IgnoreGuidValue": [],
-        "IgnoreFoldersAndFiles": []
-    },
-    "LibraryClassCheck": {
-        "IgnoreHeaderFile": []
-    },
+            "AcceptableDependencies":
+                [
+                    "MdePkg/MdePkg.dec",
+                    "MdeModulePkg/MdeModulePkg.dec",
+                    "NetworkPkg/NetworkPkg.dec",
+                    "CryptoPkg/CryptoPkg.dec",
+                ],
+            # For host based unit tests
+            "AcceptableDependencies-HOST_APPLICATION": [
+                "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+            ],
+            # For UEFI shell based apps
+            "AcceptableDependencies-UEFI_APPLICATION":
+                ["ShellPkg/ShellPkg.dec"],
+            "IgnoreInf": [],
+        },
+    "DscCompleteCheck": { "DscPath": "NetworkPkg.dsc", "IgnoreInf": [] },
+    "GuidCheck":
+        {
+            "IgnoreGuidName": [],
+            "IgnoreGuidValue": [],
+            "IgnoreFoldersAndFiles": [],
+        },
+    "LibraryClassCheck": { "IgnoreHeaderFile": [] },
 
     ## options defined ci/Plugin/SpellCheck
     "SpellCheck": {
-        "AuditOnly": True,           # Fails test but run in AuditOnly mode to collect log
-        "IgnoreFiles": [],           # use gitignore syntax to ignore errors in matching files
-        "ExtendWords": [],           # words to extend to the dictionary for this package
-        "IgnoreStandardPaths": [],   # Standard Plugin defined paths that should be ignore
-        "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
-    },
+            "AuditOnly": True, # Fails test but run in AuditOnly mode to collect log
+            "IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files
+            "ExtendWords": [], # words to extend to the dictionary for this package
+            "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
+            "AdditionalIncludePaths": [], # Additional paths to spell check (wildcards supported)
+        },
 
-    "Defines": {
-        "BLD_*_CONTINUOUS_INTEGRATION": "TRUE",
-        "BLD_*_NETWORK_ENABLE": "TRUE",
-        "BLD_*_NETWORK_SNP_ENABLE": "TRUE",
-        "BLD_*_NETWORK_VLAN_ENABLE": "TRUE",
-        "BLD_*_NETWORK_IP4_ENABLE": "TRUE",
-        "BLD_*_NETWORK_IP6_ENABLE": "TRUE",
-        "BLD_*_NETWORK_TLS_ENABLE": "TRUE",
-        "BLD_*_NETWORK_HTTP_ENABLE": "FALSE",
-        "BLD_*_NETWORK_HTTP_BOOT_ENABLE": "TRUE",
-        "BLD_*_NETWORK_ISCSI_ENABLE": "TRUE",
-    }
+    "Defines":
+        {
+            "BLD_*_CONTINUOUS_INTEGRATION": "TRUE",
+            "BLD_*_NETWORK_ENABLE": "TRUE",
+            "BLD_*_NETWORK_SNP_ENABLE": "TRUE",
+            "BLD_*_NETWORK_VLAN_ENABLE": "TRUE",
+            "BLD_*_NETWORK_IP4_ENABLE": "TRUE",
+            "BLD_*_NETWORK_IP6_ENABLE": "TRUE",
+            "BLD_*_NETWORK_TLS_ENABLE": "TRUE",
+            "BLD_*_NETWORK_HTTP_ENABLE": "FALSE",
+            "BLD_*_NETWORK_HTTP_BOOT_ENABLE": "TRUE",
+            "BLD_*_NETWORK_ISCSI_ENABLE": "TRUE",
+        },
 }
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114254): https://edk2.groups.io/g/devel/message/114254
Mute This Topic: https://groups.io/mt/103926732/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 11:45   ` Gerd Hoffmann
  2024-01-24  3:33 ` [edk2-devel] [PATCH 04/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534

SECURITY PATCH - Patch

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 <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 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 f2422c2f2827..220e7c68f11b 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 bf5aa7a769de..89d16484a568 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
+  // Seek the inner option
   //
-  // The inner options still start with 2 bytes option-code and 2 bytes option-len.
-  //
-  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.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114255): https://edk2.groups.io/g/devel/message/114255
Mute This Topic: https://groups.io/mt/103926733/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 04/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (2 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch Doug Flick via groups.io
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534

SECURITY PATCH - Unit Tests

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 <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Test/NetworkPkgHostTest.dsc        |   1 +
 .../GoogleTest/Dhcp6DxeGoogleTest.inf         |   1 +
 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h   |  58 +++
 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c                 |   2 +-
 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 365 +++++++++++++++++-
 5 files changed, 424 insertions(+), 3 deletions(-)
 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h

diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
index 20bc90b1728d..24dee654df2e 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -16,6 +16,7 @@ [Defines]
   SKUID_IDENTIFIER        = DEFAULT
 
 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
 [Packages]
   MdePkg/MdePkg.dec
   UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
index 8e9119a37158..12532ed30cb3 100644
--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
+++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
@@ -18,6 +18,7 @@ [Defines]
 [Sources]
   Dhcp6DxeGoogleTest.cpp
   Dhcp6IoGoogleTest.cpp
+  Dhcp6IoGoogleTest.h
   ../Dhcp6Io.c
   ../Dhcp6Utility.c
 
diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
new file mode 100644
index 000000000000..aed3b890827b
--- /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 <Uefi.h>
+
+/**
+  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/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
index 89d16484a568..3b8feb4a2032 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/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
index 7ee40e4af480..7db253a7b87f 100644
--- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
+++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
@@ -13,6 +13,7 @@ extern "C" {
   #include <Library/BaseMemoryLib.h>
   #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);
+}
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114256): https://edk2.groups.io/g/devel/message/114256
Mute This Topic: https://groups.io/mt/103926734/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (3 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 04/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 11:53   ` Gerd Hoffmann
  2024-01-24  3:33 ` [edk2-devel] [PATCH 06/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests Doug Flick via groups.io
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536

SECURITY PATCH - Patch

TCBZ4536
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Ip6Dxe/Ip6Option.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
index 199eea124dfe..8718d5d8756a 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.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114257): https://edk2.groups.io/g/devel/message/114257
Mute This Topic: https://groups.io/mt/103926735/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 06/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (4 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536

SECURITY PATCH - Unit Tests

TCBZ4536
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Test/NetworkPkgHostTest.dsc        |   1 +
 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf    |  42 ++++++
 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp    |  20 +++
 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++
 4 files changed, 192 insertions(+)
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp

diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
index 24dee654df2e..7fa7b0f9d5be 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -26,6 +26,7 @@ [Components]
   # 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]
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
new file mode 100644
index 000000000000..6e4de0745fb5
--- /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.<BR>
+# 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/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
new file mode 100644
index 000000000000..6ebfd5fdfb70
--- /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 <gtest/gtest.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// Run the tests
+////////////////////////////////////////////////////////////////////////////////
+int
+main (
+  int   argc,
+  char  *argv[]
+  )
+{
+  testing::InitGoogleTest (&argc, argv);
+  return RUN_ALL_TESTS ();
+}
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
new file mode 100644
index 000000000000..f2cd90e1a952
--- /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 <gtest/gtest.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Library/BaseLib.h>
+  #include <Library/DebugLib.h>
+  #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));
+}
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114258): https://edk2.groups.io/g/devel/message/114258
Mute This Topic: https://groups.io/mt/103926736/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (5 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 06/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 10:39   ` Pedro Falcato
  2024-01-24  3:33 ` [edk2-devel] [PATCH 08/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538

SECURITY PATCH - Patch

TCBZ4537
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')

TCBZ4538
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')

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Ip6Dxe/Ip6Option.h | 89 +++++++++++++++++++++++++++++++++++
 NetworkPkg/Ip6Dxe/Ip6Option.c | 76 +++++++++++++++++++++++++-----
 2 files changed, 154 insertions(+), 11 deletions(-)

diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
index bd8e223c8a67..5d786073ebcb 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
@@ -12,6 +12,95 @@
 
 #define IP6_FRAGMENT_OFFSET_MASK  (~0x3)
 
+//
+// 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.
+//
+#define IP6_SIZE_OF_OPT_TYPE                  (sizeof(UINT8))
+#define IP6_SIZE_OF_OPT_LEN                   (sizeof(UINT8))
+#define IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN  (IP6_SIZE_OF_OPT_TYPE + IP6_SIZE_OF_OPT_LEN)
+#define IP6_OFFSET_OF_OPT_LEN(a)  (a + IP6_SIZE_OF_OPT_TYPE)
+STATIC_ASSERT (
+  IP6_OFFSET_OF_OPT_LEN (0) == 1,
+  "The Length field should be 1 octet (8 bits) past the start of the option"
+  );
+
+#define IP6_NEXT_OPTION_OFFSET(offset, length)  (offset + IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN + length)
+STATIC_ASSERT (
+  IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
+  "The next option is minimally the combined size of the option tag and length"
+  );
+
+//
+// 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
+//
+#define IP6_SIZE_OF_EXT_NEXT_HDR  (sizeof(UINT8))
+#define IP6_SIZE_OF_HDR_EXT_LEN   (sizeof(UINT8))
+
+#define IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN  (IP6_SIZE_OF_EXT_NEXT_HDR + IP6_SIZE_OF_HDR_EXT_LEN)
+STATIC_ASSERT (
+  IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN == 2,
+  "The combined size of Next Header and Len is two 8 bit fields"
+  );
+
+//
+// The "+ 1" in this calculation is because of the "not including the first 8 octets"
+// part of the definition (meaning the value of 0 represents 64 bits)
+//
+#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) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN)
+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;
diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
index 8718d5d8756a..144f8d34dead 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_OFFSET_OF_OPT_LEN (Option + Offset));
+        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_OFFSET_OF_OPT_LEN (Option + Offset));
+            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) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
         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 + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN + 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;
 
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114259): https://edk2.groups.io/g/devel/message/114259
Mute This Topic: https://groups.io/mt/103926738/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 08/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (6 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538

SECURITY PATCH - Unit Tests

TCBZ4537
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')

TCBZ4538
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')

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf    |  10 +-
 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h   |  40 +++
 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 282 ++++++++++++++++++
 3 files changed, 328 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 6e4de0745fb5..ba29dbabadb9 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.<BR>
 # 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 @@ [Defines]
 #  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.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
new file mode 100644
index 000000000000..618a7e658e5a
--- /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 EFI_IP6_OPTION_GOOGLE_TEST_H_
+#define EFI_IP6_OPTION_GOOGLE_TEST_H_
+
+#include <Uefi.h>
+#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 // __EFI_IP6_OPTION_GOOGLE_TEST_H__
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
index f2cd90e1a952..69eef4b98ed2 100644
--- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
@@ -12,6 +12,7 @@ extern "C" {
   #include <Library/DebugLib.h>
   #include "../Ip6Impl.h"
   #include "../Ip6Option.h"
+  #include "Ip6OptionGoogleTest.h"
 }
 
 /////////////////////////////////////////////////////////////////////////
@@ -127,3 +128,284 @@ 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
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Ip6IsOptionValidTest Tests
+///////////////////////////////////////////////////////////////////////////////
+
+// 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 <unknown> 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 <unknown> 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 <unknown> 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));
+}
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114260): https://edk2.groups.io/g/devel/message/114260
Mute This Topic: https://groups.io/mt/103926739/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (7 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 08/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 12:09   ` Gerd Hoffmann
  2024-01-24  3:33 ` [edk2-devel] [PATCH 10/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539

SECURITY PATCH - Patch

TCBZ4539
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 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 425e0cf8061d..2b2d372889a3 100644
--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+  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.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114261): https://edk2.groups.io/g/devel/message/114261
Mute This Topic: https://groups.io/mt/103926740/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 10/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (8 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539

SECURITY PATCH - Unit Tests

TCBZ4539
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Test/NetworkPkgHostTest.dsc        |   1 +
 .../GoogleTest/UefiPxeBcDxeGoogleTest.inf     |  48 +++
 .../GoogleTest/PxeBcDhcp6GoogleTest.h         |  50 +++
 .../GoogleTest/PxeBcDhcp6GoogleTest.cpp       | 300 ++++++++++++++++++
 .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp     |  19 ++
 5 files changed, 418 insertions(+)
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp

diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
index 7fa7b0f9d5be..a0273c431025 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -27,6 +27,7 @@ [Components]
   #
   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/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
new file mode 100644
index 000000000000..301dcdf61109
--- /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.<BR>
+# 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
diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
new file mode 100644
index 000000000000..b17c314791c8
--- /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.<BR>
+  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 <Uefi.h>
+#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/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
new file mode 100644
index 000000000000..8260eeee50dc
--- /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 <gtest/gtest.h>
+
+extern "C" {
+  #include <Uefi.h>
+  #include <Library/BaseLib.h>
+  #include <Library/DebugLib.h>
+  #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/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
new file mode 100644
index 000000000000..cc4fdf525b62
--- /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 <gtest/gtest.h>
+
+////////////////////////////////////////////////////////////////////////////////
+// Run the tests
+////////////////////////////////////////////////////////////////////////////////
+int
+main (
+  int   argc,
+  char  *argv[]
+  )
+{
+  testing::InitGoogleTest (&argc, argv);
+  return RUN_ALL_TESTS ();
+}
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114262): https://edk2.groups.io/g/devel/message/114262
Mute This Topic: https://groups.io/mt/103926741/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (9 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 10/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 18:50   ` Michael D Kinney
  2024-01-24  3:33 ` [edk2-devel] [PATCH 12/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Michael D Kinney, Liming Gao, Zhiguang Liu

This adds support for GetTime Google Test Mock

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 .../GoogleTest/Library/MockUefiRuntimeServicesTableLib.h   | 7 +++++++
 .../MockUefiRuntimeServicesTableLib.cpp                    | 5 +++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h
index 241abc55c079..bcc902cb93c2 100644
--- a/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h
+++ b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h
@@ -37,6 +37,13 @@ struct MockUefiRuntimeServicesTableLib {
      IN UINTN     DataSize,
      IN VOID      *Data)
     );
+
+  MOCK_FUNCTION_DECLARATION (
+    EFI_STATUS,
+    gRT_GetTime,
+    (OUT  EFI_TIME                    *Time,
+     OUT  EFI_TIME_CAPABILITIES       *Capabilities OPTIONAL)
+    );
 };
 
 #endif
diff --git a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp
index 14296b0ccb88..8d2afd5dd63a 100644
--- a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp
+++ b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp
@@ -10,11 +10,12 @@ MOCK_INTERFACE_DEFINITION (MockUefiRuntimeServicesTableLib);
 
 MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib, gRT_GetVariable, 5, EFIAPI);
 MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib, gRT_SetVariable, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib, gRT_GetTime, 2, EFIAPI);
 
 static EFI_RUNTIME_SERVICES  localRt = {
-  { 0 },              // EFI_TABLE_HEADER
+  { 0 },            // EFI_TABLE_HEADER
 
-  NULL,             // EFI_GET_TIME
+  gRT_GetTime,      // EFI_GET_TIME
   NULL,             // EFI_SET_TIME
   NULL,             // EFI_GET_WAKEUP_TIME
   NULL,             // EFI_SET_WAKEUP_TIME
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114263): https://edk2.groups.io/g/devel/message/114263
Mute This Topic: https://groups.io/mt/103926742/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 12/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (10 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 13/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540

SECURITY PATCH - Patch

TCBZ4540
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++
 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 77 ++++++++++++++++++++++------
 2 files changed, 78 insertions(+), 16 deletions(-)

diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
index c86f6d391b80..6357d27faefd 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)
diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
index 2b2d372889a3..7fd1281c1184 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 (
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114264): https://edk2.groups.io/g/devel/message/114264
Mute This Topic: https://groups.io/mt/103926743/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 13/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (11 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 12/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24  3:33 ` [edk2-devel] [PATCH 14/14] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
  2024-01-24 10:17 ` [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Pedro Falcato
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel
  Cc: Doug Flick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

From: Doug Flick <dougflick@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540

SECURITY PATCH - Unit Tests

TCBZ4540
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

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 NetworkPkg/Test/NetworkPkgHostTest.dsc        |   5 +-
 .../GoogleTest/PxeBcDhcp6GoogleTest.h         |  18 ++
 .../GoogleTest/PxeBcDhcp6GoogleTest.cpp       | 278 +++++++++++++++++-
 3 files changed, 298 insertions(+), 3 deletions(-)

diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
index a0273c431025..fa301a7a52ab 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -27,7 +27,10 @@ [Components]
   #
   NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
   NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
-  NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+  NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
+    <LibraryClasses>
+      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.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
index b17c314791c8..0d825e44250a 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_
diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
index 8260eeee50dc..bd423ebadfce 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 <gtest/gtest.h>
+#include <Library/GoogleTestLib.h>
+#include <GoogleTest/Library/MockUefiLib.h>
+#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
 
 extern "C" {
   #include <Uefi.h>
@@ -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
+    );
+}
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114265): https://edk2.groups.io/g/devel/message/114265
Mute This Topic: https://groups.io/mt/103926744/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [edk2-devel] [PATCH 14/14] NetworkPkg: : Adds a SecurityFix.yaml file
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (12 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 13/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
@ 2024-01-24  3:33 ` Doug Flick via groups.io
  2024-01-24 10:17 ` [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Pedro Falcato
  14 siblings, 0 replies; 24+ messages in thread
From: Doug Flick via groups.io @ 2024-01-24  3:33 UTC (permalink / raw)
  To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

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 <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
---
 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 000000000000..7e900483fec5
--- /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.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114266): https://edk2.groups.io/g/devel/message/114266
Mute This Topic: https://groups.io/mt/103926745/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack
  2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
                   ` (13 preceding siblings ...)
  2024-01-24  3:33 ` [edk2-devel] [PATCH 14/14] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
@ 2024-01-24 10:17 ` Pedro Falcato
  14 siblings, 0 replies; 24+ messages in thread
From: Pedro Falcato @ 2024-01-24 10:17 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams,
	Michael D Kinney, Liming Gao, Zhiguang Liu

On Wed, Jan 24, 2024 at 5:20 AM Doug Flick via groups.io
<dougflick=microsoft.com@groups.io> wrote:
>
> The security patches contained in this series with the exception of
> "MdePkg/Test: Add gRT_GetTime Google Test Mock" and
> "NetworkPkg: : Adds a SecurityFix.yaml file" have been reviewed
> during GHSA-hc6x-cw6p-gj7h infosec review.
>
> This patch series contains the following security patches for the
> security vulnerabilities found by QuarksLab in the EDK II Network
> Stack:
>
> 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
>
> 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
>
> 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
>
> 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')
>
> 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')
>
> 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
>
> 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
>
> NetworkPkg:
> Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
> Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
>
> MdePkg:
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
>
> Doug Flick (8):
>   NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch
>   NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests
>   NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
>   NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
>   NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
>   NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
>   NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
>   NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests
>
> Douglas Flick [MSFT] (6):
>   NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
>   NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
>   NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
>   NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
>   MdePkg: Test: Add gRT_GetTime Google Test Mock
>   NetworkPkg: : Adds a SecurityFix.yaml file

Thanks for the patches. Please rewrite the commit messages for each
specific patch to contain relevant details on the problem and fix. The
commits as-is are somewhat useless unless one wants to track down the
CVEs. Thanks!

-- 
Pedro


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114271): https://edk2.groups.io/g/devel/message/114271
Mute This Topic: https://groups.io/mt/103926729/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
  2024-01-24  3:33 ` [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
@ 2024-01-24 10:39   ` Pedro Falcato
  2024-01-24 12:02     ` Gerd Hoffmann
  0 siblings, 1 reply; 24+ messages in thread
From: Pedro Falcato @ 2024-01-24 10:39 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Saloni Kasbekar, Zachary Clark-williams, Doug Flick [MSFT]

On Wed, Jan 24, 2024 at 5:20 AM Doug Flick via groups.io
<dougflick=microsoft.com@groups.io> wrote:
>
> From: Doug Flick <dougflick@microsoft.com>
>
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4537
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4538
>
> SECURITY PATCH - Patch
>
> TCBZ4537
> 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')
>
> TCBZ4538
> 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')
>
> Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
> Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
>
> Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> ---
>  NetworkPkg/Ip6Dxe/Ip6Option.h | 89 +++++++++++++++++++++++++++++++++++
>  NetworkPkg/Ip6Dxe/Ip6Option.c | 76 +++++++++++++++++++++++++-----
>  2 files changed, 154 insertions(+), 11 deletions(-)
>
> diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
> index bd8e223c8a67..5d786073ebcb 100644
> --- a/NetworkPkg/Ip6Dxe/Ip6Option.h
> +++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
> @@ -12,6 +12,95 @@
>
>  #define IP6_FRAGMENT_OFFSET_MASK  (~0x3)
>
> +//
> +// 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.
> +//

Why isn't this just a

struct Ipv6Option {
  UINT8 OptionType;
  UINT8 OptionLength;
  UINT8 OptionData[];
};

? You'd skip all of the weird obfuscated math below.

> +#define IP6_SIZE_OF_OPT_TYPE                  (sizeof(UINT8))
> +#define IP6_SIZE_OF_OPT_LEN                   (sizeof(UINT8))

sizeof(UINT8) can just be replaced by 1
> +#define IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN  (IP6_SIZE_OF_OPT_TYPE + IP6_SIZE_OF_OPT_LEN)
> +#define IP6_OFFSET_OF_OPT_LEN(a)  (a + IP6_SIZE_OF_OPT_TYPE)
> +STATIC_ASSERT (
> +  IP6_OFFSET_OF_OPT_LEN (0) == 1,
> +  "The Length field should be 1 octet (8 bits) past the start of the option"
> +  );
> +
> +#define IP6_NEXT_OPTION_OFFSET(offset, length)  (offset + IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN + length)
> +STATIC_ASSERT (
> +  IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
> +  "The next option is minimally the combined size of the option tag and length"
> +  );
> +
> +//
> +// 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
> +//

Same comment as above (why is this not a struct?)

> +#define IP6_SIZE_OF_EXT_NEXT_HDR  (sizeof(UINT8))
> +#define IP6_SIZE_OF_HDR_EXT_LEN   (sizeof(UINT8))

Same for sizeof(UINT8) here.

> +
> +#define IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN  (IP6_SIZE_OF_EXT_NEXT_HDR + IP6_SIZE_OF_HDR_EXT_LEN)
> +STATIC_ASSERT (
> +  IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN == 2,
> +  "The combined size of Next Header and Len is two 8 bit fields"
> +  );
> +
> +//
> +// The "+ 1" in this calculation is because of the "not including the first 8 octets"
> +// part of the definition (meaning the value of 0 represents 64 bits)
> +//
> +#define IP6_HDR_EXT_LEN(a)  (((UINT16)(UINT8)(a) + 1) * 8)

This expression is remarkably hard to understand correctly, operator
precedence is hard :( .

> +
> +// This is the maxmimum length permissible by a extension header

typo: maximum
> +// Length is UINT8 of 8 octets not including the first 8 octets
> +#define IP6_MAX_EXT_DATA_LENGTH  (IP6_HDR_EXT_LEN (MAX_UINT8) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN)
> +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;
> diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
> index 8718d5d8756a..144f8d34dead 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)) {

OptionLen is unsigned hence < 0 is not a valid check

-- 
Pedro


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114274): https://edk2.groups.io/g/devel/message/114274
Mute This Topic: https://groups.io/mt/103926738/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
  2024-01-24  3:33 ` [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
@ 2024-01-24 11:30   ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 11:30 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

On Tue, Jan 23, 2024 at 07:33:24PM -0800, Doug Flick via groups.io wrote:
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535
> 
> SECURITY PATCH - Patch

Not needed, the CVE number below implies that.

> TCBZ4535

Not needed, the link to tianocore bugzilla is above.

> 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

Good.  Given that this series of bugs got a fancy name I think it makes
sense to include that too ("pixiefail bug #1").

Please include a description of the bug and how it is fixed.

[ the same applies to the following patches ]

> -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.

The code changes look good to me.  The key changes should be highlighted
in the commit message.

thanks,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114275): https://edk2.groups.io/g/devel/message/114275
Mute This Topic: https://groups.io/mt/103926731/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
  2024-01-24  3:33 ` [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
@ 2024-01-24 11:39   ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 11:39 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

On Tue, Jan 23, 2024 at 07:33:25PM -0800, Doug Flick via groups.io wrote:
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535
> 
> SECURITY PATCH - Unit Tests
> 
> TCBZ4535
> 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

I don't think this is needed here, this patch doesn't fix CVE-2023-45230
after all.  A description of what the tests are checking would be more
useful.

> diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
> index 07dc7abd6938..0060f7a2cb8f 100644
> --- a/NetworkPkg/NetworkPkg.ci.yaml
> +++ b/NetworkPkg/NetworkPkg.ci.yaml
> @@ -7,73 +7,65 @@
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  ##
>  {
> -    "LicenseCheck": {
> -        "IgnoreFiles": []
> -    },
> +    "LicenseCheck": { "IgnoreFiles": [] },

I guess this patch hooks the unit tests into CI.  The whitespace changes
make changes file hard to read though.  Two options to deal with that:

  (1) avoid to reformat the file, or
  (2) split the patch into two, one with only the whitespace changes
      and one with the functional change.

thanks & take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114276): https://edk2.groups.io/g/devel/message/114276
Mute This Topic: https://groups.io/mt/103926732/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
  2024-01-24  3:33 ` [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
@ 2024-01-24 11:45   ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 11:45 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams

On Tue, Jan 23, 2024 at 07:33:26PM -0800, Doug Flick via groups.io wrote:
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
> 
> SECURITY PATCH - Patch
> 
> 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 <saloni.kasbekar@intel.com>
> Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Code changes look good to me, commit message should be improved simliar
ti patch #1.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114277): https://edk2.groups.io/g/devel/message/114277
Mute This Topic: https://groups.io/mt/103926733/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch
  2024-01-24  3:33 ` [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch Doug Flick via groups.io
@ 2024-01-24 11:53   ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 11:53 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Saloni Kasbekar, Zachary Clark-williams, Doug Flick [MSFT]

On Tue, Jan 23, 2024 at 07:33:28PM -0800, Doug Flick via groups.io wrote:
> From: Doug Flick <dougflick@microsoft.com>
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536
> 
> SECURITY PATCH - Patch
> 
> TCBZ4536
> 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

Same comment for the commit message as for patch #1.

> +  //
> +  // 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;
> +  }

Code change is good (and the commit message describing the change can be
as short as the patch itself ;)

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114278): https://edk2.groups.io/g/devel/message/114278
Mute This Topic: https://groups.io/mt/103926735/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
  2024-01-24 10:39   ` Pedro Falcato
@ 2024-01-24 12:02     ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 12:02 UTC (permalink / raw)
  To: devel, pedro.falcato
  Cc: dougflick, Saloni Kasbekar, Zachary Clark-williams,
	Doug Flick [MSFT]

  Hi,

> Why isn't this just a
> 
> struct Ipv6Option {
>   UINT8 OptionType;
>   UINT8 OptionLength;
>   UINT8 OptionData[];
> };

That makes sense indeed (for dhcpv6 we have that,
see EFI_DHCP6_PACKET_OPTION).

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114279): https://edk2.groups.io/g/devel/message/114279
Mute This Topic: https://groups.io/mt/103926738/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
  2024-01-24  3:33 ` [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
@ 2024-01-24 12:09   ` Gerd Hoffmann
  0 siblings, 0 replies; 24+ messages in thread
From: Gerd Hoffmann @ 2024-01-24 12:09 UTC (permalink / raw)
  To: devel, dougflick
  Cc: Saloni Kasbekar, Zachary Clark-williams, Doug Flick [MSFT]

On Tue, Jan 23, 2024 at 07:33:32PM -0800, Doug Flick via groups.io wrote:
> From: Doug Flick <dougflick@microsoft.com>
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
> 
> SECURITY PATCH - Patch
> 
> TCBZ4539
> 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
> 
> Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
> Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
> 
> Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>

Code change looks good to me, commit message should be improved (see
patch #1 comments).

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114280): https://edk2.groups.io/g/devel/message/114280
Mute This Topic: https://groups.io/mt/103926740/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock
  2024-01-24  3:33 ` [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
@ 2024-01-24 18:50   ` Michael D Kinney
  0 siblings, 0 replies; 24+ messages in thread
From: Michael D Kinney @ 2024-01-24 18:50 UTC (permalink / raw)
  To: Douglas Flick [MSFT], devel@edk2.groups.io
  Cc: Liming Gao, Liu, Zhiguang, Kinney, Michael D

Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>

> -----Original Message-----
> From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
> Sent: Tuesday, January 23, 2024 7:34 PM
> To: devel@edk2.groups.io
> Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
> Liu, Zhiguang <zhiguang.liu@intel.com>
> Subject: [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock
> 
> This adds support for GetTime Google Test Mock
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> 
> Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
> ---
>  .../GoogleTest/Library/MockUefiRuntimeServicesTableLib.h   | 7 +++++++
>  .../MockUefiRuntimeServicesTableLib.cpp                    | 5 +++--
>  2 files changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git
> a/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTab
> leLib.h
> b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTab
> leLib.h
> index 241abc55c079..bcc902cb93c2 100644
> ---
> a/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTab
> leLib.h
> +++
> b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTab
> leLib.h
> @@ -37,6 +37,13 @@ struct MockUefiRuntimeServicesTableLib {
>       IN UINTN     DataSize,
> 
>       IN VOID      *Data)
> 
>      );
> 
> +
> 
> +  MOCK_FUNCTION_DECLARATION (
> 
> +    EFI_STATUS,
> 
> +    gRT_GetTime,
> 
> +    (OUT  EFI_TIME                    *Time,
> 
> +     OUT  EFI_TIME_CAPABILITIES       *Capabilities OPTIONAL)
> 
> +    );
> 
>  };
> 
> 
> 
>  #endif
> 
> diff --git
> a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/Mo
> ckUefiRuntimeServicesTableLib.cpp
> b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/Mo
> ckUefiRuntimeServicesTableLib.cpp
> index 14296b0ccb88..8d2afd5dd63a 100644
> ---
> a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/Mo
> ckUefiRuntimeServicesTableLib.cpp
> +++
> b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/Mo
> ckUefiRuntimeServicesTableLib.cpp
> @@ -10,11 +10,12 @@ MOCK_INTERFACE_DEFINITION
> (MockUefiRuntimeServicesTableLib);
> 
> 
>  MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib,
> gRT_GetVariable, 5, EFIAPI);
> 
>  MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib,
> gRT_SetVariable, 5, EFIAPI);
> 
> +MOCK_FUNCTION_DEFINITION (MockUefiRuntimeServicesTableLib, gRT_GetTime,
> 2, EFIAPI);
> 
> 
> 
>  static EFI_RUNTIME_SERVICES  localRt = {
> 
> -  { 0 },              // EFI_TABLE_HEADER
> 
> +  { 0 },            // EFI_TABLE_HEADER
> 
> 
> 
> -  NULL,             // EFI_GET_TIME
> 
> +  gRT_GetTime,      // EFI_GET_TIME
> 
>    NULL,             // EFI_SET_TIME
> 
>    NULL,             // EFI_GET_WAKEUP_TIME
> 
>    NULL,             // EFI_SET_WAKEUP_TIME
> 
> --
> 2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114349): https://edk2.groups.io/g/devel/message/114349
Mute This Topic: https://groups.io/mt/103926742/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2024-01-24 18:50 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-24  3:33 [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 01/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
2024-01-24 11:30   ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 02/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
2024-01-24 11:39   ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 03/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
2024-01-24 11:45   ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 04/14] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 05/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Patch Doug Flick via groups.io
2024-01-24 11:53   ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 06/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 - Unit Tests Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 07/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
2024-01-24 10:39   ` Pedro Falcato
2024-01-24 12:02     ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 08/14] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 09/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
2024-01-24 12:09   ` Gerd Hoffmann
2024-01-24  3:33 ` [edk2-devel] [PATCH 10/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 11/14] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
2024-01-24 18:50   ` Michael D Kinney
2024-01-24  3:33 ` [edk2-devel] [PATCH 12/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 13/14] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
2024-01-24  3:33 ` [edk2-devel] [PATCH 14/14] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
2024-01-24 10:17 ` [edk2-devel] [PATCH 00/14] Security Patches for EDK II Network Stack Pedro Falcato

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox