* [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:35 ` Saloni Kasbekar
2024-02-05 13:41 ` bryan-bt.tan via groups.io
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC Doug Flick via groups.io
` (15 subsequent siblings)
16 siblings, 2 replies; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 UTC (permalink / raw)
To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535
Bug Details:
PixieFail Bug #2
CVE-2023-45230
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds
of a Memory Buffer
Changes Overview:
> -UINT8 *
> +EFI_STATUS
> Dhcp6AppendOption (
> - IN OUT UINT8 *Buf,
> - IN UINT16 OptType,
> - IN UINT16 OptLen,
> - IN UINT8 *Data
> + IN OUT EFI_DHCP6_PACKET *Packet,
> + IN OUT UINT8 **PacketCursor,
> + IN UINT16 OptType,
> + IN UINT16 OptLen,
> + IN UINT8 *Data
> );
Dhcp6AppendOption() and variants can return errors now. All callsites
are adapted accordingly.
It gets passed in EFI_DHCP6_PACKET as additional parameter ...
> + //
> + // Verify the PacketCursor is within the packet
> + //
> + if ( (*PacketCursor < Packet->Dhcp6.Option)
> + || (*PacketCursor >= Packet->Dhcp6.Option +
(Packet->Size - sizeof (EFI_DHCP6_HEADER))))
> + {
> + return EFI_INVALID_PARAMETER;
> + }
... so it can look at Packet->Size when checking buffer space.
Also to allow Packet->Length updates.
Lots of checks added.
Cc: Saloni Kasbekar <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 (#114463): https://edk2.groups.io/g/devel/message/114463
Mute This Topic: https://groups.io/mt/103964976/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
@ 2024-02-01 19:35 ` Saloni Kasbekar
2024-02-05 13:41 ` bryan-bt.tan via groups.io
1 sibling, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:35 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535
Bug Details:
PixieFail Bug #2
CVE-2023-45230
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds of a Memory Buffer
Changes Overview:
> -UINT8 *
> +EFI_STATUS
> Dhcp6AppendOption (
> - IN OUT UINT8 *Buf,
> - IN UINT16 OptType,
> - IN UINT16 OptLen,
> - IN UINT8 *Data
> + IN OUT EFI_DHCP6_PACKET *Packet,
> + IN OUT UINT8 **PacketCursor,
> + IN UINT16 OptType,
> + IN UINT16 OptLen,
> + IN UINT8 *Data
> );
Dhcp6AppendOption() and variants can return errors now. All callsites are adapted accordingly.
It gets passed in EFI_DHCP6_PACKET as additional parameter ...
> + //
> + // Verify the PacketCursor is within the packet // if (
> + (*PacketCursor < Packet->Dhcp6.Option)
> + || (*PacketCursor >= Packet->Dhcp6.Option +
(Packet->Size - sizeof (EFI_DHCP6_HEADER))))
> + {
> + return EFI_INVALID_PARAMETER;
> + }
... so it can look at Packet->Size when checking buffer space.
Also to allow Packet->Length updates.
Lots of checks added.
Cc: Saloni Kasbekar <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 2diff --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 (#114954): https://edk2.groups.io/g/devel/message/114954
Mute This Topic: https://groups.io/mt/103964976/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
2024-02-01 19:35 ` Saloni Kasbekar
@ 2024-02-05 13:41 ` bryan-bt.tan via groups.io
1 sibling, 0 replies; 35+ messages in thread
From: bryan-bt.tan via groups.io @ 2024-02-05 13:41 UTC (permalink / raw)
To: Doug Flick, devel
[-- Attachment #1: Type: text/plain, Size: 4914 bytes --]
On Thu, Jan 25, 2024 at 11:06 PM, Doug Flick wrote:
>
> <snip>
> @@ -607,35 +616,95 @@ Dhcp6AppendOption (
> // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> //=0D
> =0D
> - ASSERT (OptLen !=3D 0);=0D
> + //=0D
> + // Verify the arguments are valid=0D
> + //=0D
> + if (Packet =3D=3D NULL) {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
> =0D
> - WriteUnaligned16 ((UINT16 *)Buf, OptType);=0D
> - Buf +=3D 2;=0D
> - WriteUnaligned16 ((UINT16 *)Buf, OptLen);=0D
> - Buf +=3D 2;=0D
> - CopyMem (Buf, Data, NTOHS (OptLen));=0D
> - Buf +=3D NTOHS (OptLen);=0D
> + if ((PacketCursor =3D=3D NULL) || (*PacketCursor =3D=3D NULL)) {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
> =0D
> - return Buf;=0D
> + if (Data =3D=3D NULL) {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
> +=0D
> + if (OptLen =3D=3D 0) {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
> +=0D
> + //=0D
> + // Verify the PacketCursor is within the packet=0D
> + //=0D
> + if ( (*PacketCursor < Packet->Dhcp6.Option)=0D
> + || (*PacketCursor >=3D Packet->Dhcp6.Option + (Packet->Size - sizeof =
> (EFI_DHCP6_HEADER))))=0D
> + {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
> +=0D
> + //=0D
> + // Calculate the bytes needed for the option=0D
> + //=0D
> + BytesNeeded =3D DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS (OptLen);=0D
>
> +=0D
> + //=0D
> + // Space remaining in the packet=0D
> + //=0D
> + Length =3D Packet->Size - Packet->Length;=0D
> + if (Length < BytesNeeded) {=0D
> + return EFI_BUFFER_TOO_SMALL;=0D
> + }=0D
> +=0D
> + //=0D
> + // Verify the PacketCursor is within the packet=0D
> + //=0D
> + if ( (*PacketCursor < Packet->Dhcp6.Option)=0D
> + || (*PacketCursor >=3D Packet->Dhcp6.Option + (Packet->Size - sizeof =
> (EFI_DHCP6_HEADER))))=0D
> + {=0D
> + return EFI_INVALID_PARAMETER;=0D
> + }=0D
This check is unnecessary; the same check is done above.
>
> <snip>
> @@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
> //=0D
> for (Index =3D 0; Index < Ia->IaAddressCount; Index++) {=0D
> AddrOpt =3D (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDR=
> ESS);=0D
> - Buf =3D Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)Addr=
> Opt, MessageType);=0D
> + Status =3D Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_=
> IA_ADDRESS *)AddrOpt, MessageType);=0D
> + if (EFI_ERROR (Status)) {=0D
> + return Status;=0D
> + }=0D
> }=0D
> =0D
> //=0D
> // Fill the value of Ia option length=0D
> //=0D
> - *Len =3D HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));=0D
> + *Len =3D HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));=0D
> =0D
> - return Buf;=0D
> + //=0D
> + // Update the packet length=0D
> + //=0D
> + Packet->Length +=3D BytesNeeded;=0D
Shouldn't we update Packet->Length before calling Dhcp6AppendIaAddrOption
as it needs to know how much space is left in the Packet?
>
> +=0D
> + return EFI_SUCCESS;=0D
> }=0D
> =0D
> /**=0D
> Append the appointed Elapsed time option to Buf, and move Buf to the end=
> .=0D
> =0D
> - @param[in, out] Buf The pointer to the position to append.=0D
> + @param[in, out] Packet A pointer to the packet, on success Packet=
> ->Length=0D
Nit: Missing "will be updated." like other function header comments.
>
> + @param[in, out] PacketCursor The pointer in the packet, on success Pack=
>
> etCursor=0D
> + will be moved to the end of the option.=0D
> @param[in] Instance The pointer to the Dhcp6 instance.=0D
> @param[out] Elapsed The pointer to the elapsed time value in=0D
> - the generated packet.=0D
> + the generated packet.=0D
> =0D
> - @return Buf The position to append the next Ia option.=
> =0D
> + @retval EFI_INVALID_PARAMETER An argument provided to the function was=
> invalid=0D
> + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the op=
> tion.=0D
> + @retval EFI_SUCCESS The option is appended successfully.=0D
> =0D
> **/=0D
> -UINT8 *=0D
> +EFI_STATUS=0D
> Dhcp6AppendETOption (=0D
> - IN OUT UINT8 *Buf,=0D
> - IN DHCP6_INSTANCE *Instance,=0D
> - OUT UINT16 **Elapsed=0D
> + IN OUT EFI_DHCP6_PACKET *Packet,=0D
> + IN OUT UINT8 **PacketCursor,=0D
> + IN DHCP6_INSTANCE *Instance,=0D
> + OUT UINT16 **Elapsed=0D
> )=0D
> {=0D
> + UINT32 BytesNeeded;=0D
> + UINT32 Length;=0D
> +=0D
> //=0D
> // The format of elapsed time option:=0D
> //=0D
Apologies for any poor formatting, this is my first time posting on this
mailing list and I'm using the web interface.
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115120): https://edk2.groups.io/g/devel/message/115120
Mute This Topic: https://groups.io/mt/103964976/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 5746 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* [edk2-devel] [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:36 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
` (14 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 UTC (permalink / raw)
To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams
Adds Host Based testing to the NetworkPkg
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 | 98 ++++++++++++++++++++++++++
NetworkPkg/NetworkPkg.ci.yaml | 7 +-
2 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
new file mode 100644
index 000000000000..1aeca5c5b353
--- /dev/null
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -0,0 +1,98 @@
+## @file
+# NetworkPkgHostTest DSC file used to build host-based unit tests.
+#
+# Copyright (c) Microsoft Corporation.<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
+ #
+
+# 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/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
index 07dc7abd6938..076424eb6065 100644
--- a/NetworkPkg/NetworkPkg.ci.yaml
+++ b/NetworkPkg/NetworkPkg.ci.yaml
@@ -24,6 +24,9 @@
"CompilerPlugin": {
"DscPath": "NetworkPkg.dsc"
},
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "Test/NetworkPkgHostTest.dsc"
+ },
"CharEncodingCheck": {
"IgnoreFiles": []
},
@@ -35,7 +38,9 @@
"CryptoPkg/CryptoPkg.dec"
],
# For host based unit tests
- "AcceptableDependencies-HOST_APPLICATION":[],
+ "AcceptableDependencies-HOST_APPLICATION":[
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+ ],
# For UEFI shell based apps
"AcceptableDependencies-UEFI_APPLICATION":[
"ShellPkg/ShellPkg.dec"
--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114464): https://edk2.groups.io/g/devel/message/114464
Mute This Topic: https://groups.io/mt/103964977/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC Doug Flick via groups.io
@ 2024-02-01 19:36 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:36 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC
Adds Host Based testing to the NetworkPkg
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 | 98 ++++++++++++++++++++++++++
NetworkPkg/NetworkPkg.ci.yaml | 7 +-
2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
new file mode 100644
index 000000000000..1aeca5c5b353
--- /dev/null
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -0,0 +1,98 @@
+## @file+# NetworkPkgHostTest DSC file used to build host-based unit tests.+#+# Copyright (c) Microsoft Corporation.<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+ #++# 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|0x4diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
index 07dc7abd6938..076424eb6065 100644
--- a/NetworkPkg/NetworkPkg.ci.yaml
+++ b/NetworkPkg/NetworkPkg.ci.yaml
@@ -24,6 +24,9 @@
"CompilerPlugin": { "DscPath": "NetworkPkg.dsc" },+ "HostUnitTestCompilerPlugin": {+ "DscPath": "Test/NetworkPkgHostTest.dsc"+ }, "CharEncodingCheck": { "IgnoreFiles": [] },@@ -35,7 +38,9 @@
"CryptoPkg/CryptoPkg.dec" ], # For host based unit tests- "AcceptableDependencies-HOST_APPLICATION":[],+ "AcceptableDependencies-HOST_APPLICATION":[+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec+ ], # For UEFI shell based apps "AcceptableDependencies-UEFI_APPLICATION":[ "ShellPkg/ShellPkg.dec"--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114955): https://edk2.groups.io/g/devel/message/114955
Mute This Topic: https://groups.io/mt/103964977/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 01/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch Doug Flick via groups.io
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 02/15] NetworkPkg: : Add Unit tests to CI and create Host Test DSC Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:40 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
` (13 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 UTC (permalink / raw)
To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535
Confirms that reported issue...
"Buffer overflow in the DHCPv6 client via a long Server ID option"
..has been corrected by the provided patch.
Tests the following functions to ensure they appropriately handle
untrusted data (either too long or too small) to prevent a buffer
overflow:
Dhcp6AppendOption
Dhcp6AppendETOption
Dhcp6AppendIaOption
Cc: Saloni Kasbekar <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 | 43 ++
.../GoogleTest/Dhcp6DxeGoogleTest.cpp | 20 +
.../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
4 files changed, 542 insertions(+)
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
index 1aeca5c5b353..20bc90b1728d 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -24,6 +24,7 @@ [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]
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);
+}
--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114465): https://edk2.groups.io/g/devel/message/114465
Mute This Topic: https://groups.io/mt/103964978/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
@ 2024-02-01 19:40 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:40 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4535
Confirms that reported issue...
"Buffer overflow in the DHCPv6 client via a long Server ID option"
..has been corrected by the provided patch.
Tests the following functions to ensure they appropriately handle untrusted data (either too long or too small) to prevent a buffer
overflow:
Dhcp6AppendOption
Dhcp6AppendETOption
Dhcp6AppendIaOption
Cc: Saloni Kasbekar <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 | 43 ++
.../GoogleTest/Dhcp6DxeGoogleTest.cpp | 20 +
.../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
4 files changed, 542 insertions(+)
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
index 1aeca5c5b353..20bc90b1728d 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -24,6 +24,7 @@ [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]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]+ gZeroGuiddiff --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);+}--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114957): https://edk2.groups.io/g/devel/message/114957
Mute This Topic: https://groups.io/mt/103964978/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (2 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 03/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:42 ` Saloni Kasbekar
2024-02-05 13:46 ` bryan-bt.tan via groups.io
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
` (12 subsequent siblings)
16 siblings, 2 replies; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 UTC (permalink / raw)
To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
Bug Details:
PixieFail Bug #1
CVE-2023-45229
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Change Overview:
Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking
the Inner Option from a DHCP6 Option.
>
> EFI_STATUS
> Dhcp6SeekInnerOptionSafe (
> IN UINT16 IaType,
> IN UINT8 *Option,
> IN UINT32 OptionLen,
> OUT UINT8 **IaInnerOpt,
> OUT UINT16 *IaInnerLen
> );
>
Lots of code cleanup to improve code readability.
Cc: Saloni Kasbekar <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 (#114466): https://edk2.groups.io/g/devel/message/114466
Mute This Topic: https://groups.io/mt/103964979/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
@ 2024-02-01 19:42 ` Saloni Kasbekar
2024-02-05 13:46 ` bryan-bt.tan via groups.io
1 sibling, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:42 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
Bug Details:
PixieFail Bug #1
CVE-2023-45229
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Change Overview:
Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking the Inner Option from a DHCP6 Option.
>
> EFI_STATUS
> Dhcp6SeekInnerOptionSafe (
> IN UINT16 IaType,
> IN UINT8 *Option,
> IN UINT32 OptionLen,
> OUT UINT8 **IaInnerOpt,
> OUT UINT16 *IaInnerLen
> );
>
Lots of code cleanup to improve code readability.
Cc: Saloni Kasbekar <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 (#114958): https://edk2.groups.io/g/devel/message/114958
Mute This Topic: https://groups.io/mt/103964979/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
2024-02-01 19:42 ` Saloni Kasbekar
@ 2024-02-05 13:46 ` bryan-bt.tan via groups.io
1 sibling, 0 replies; 35+ messages in thread
From: bryan-bt.tan via groups.io @ 2024-02-05 13:46 UTC (permalink / raw)
To: Doug Flick, devel
[-- Attachment #1: Type: text/plain, Size: 2527 bytes --]
On Thu, Jan 25, 2024 at 11:06 PM, Doug Flick wrote:
>
> <snip>
> @@ -641,7 +642,7 @@ Dhcp6UpdateIaInfo (
> Option =3D Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode)=
> ;=0D
> =0D
> if (Option !=3D NULL) {=0D
> - StsCode =3D NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));=0D
> + StsCode =3D NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN=
> (Option))));=0D
This should be DHCP6_OFFSET_OF_STATUS_CODE.
>
> <snip>
> @@ -715,52 +803,35 @@ Dhcp6SeekStsOption (
> }=0D
> =0D
> //=0D
> - // The format of the IA_NA option is:=0D
> + // Calculate the distance from Packet->Dhcp6.Option to the IA option.=0D
>
> //=0D
> - // 0 1 2 3=0D
> - // 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=0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> - // | OPTION_IA_NA | option-len |=
> =0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> - // | IAID (4 octets) |=
> =0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> - // | T1 |=
> =0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> - // | T2 |=
> =0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> - // | |=
> =0D
> - // . IA_NA-options .=
> =0D
> - // . .=
> =0D
> - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+=
> =0D
> + // Packet->Size and Packet->Length are both UINT32 type, and
> Packet->Siz=
> e is=0D
> + // the size of the whole packet, including the DHCP header, and
> Packet->=
> Length=0D
> + // is the length of the DHCP message body, excluding the DHCP header.=0D
>
> //=0D
> - // The format of the IA_TA option is:=0D
> + // (*Option - Packet->Dhcp6.Option) is the number of bytes from the
> star=
> t of=0D
> + // DHCP6 option area to the start of the IA option.=0D
Probably just my lack of understanding on DHCP, but earlier you do
`OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header);`
which seems to imply Packet->Length includes the DHCP header.
Am I missing something here?
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115121): https://edk2.groups.io/g/devel/message/115121
Mute This Topic: https://groups.io/mt/103964979/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
[-- Attachment #2: Type: text/html, Size: 3121 bytes --]
^ permalink raw reply [flat|nested] 35+ messages in thread
* [edk2-devel] [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (3 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 04/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:49 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch Doug Flick via groups.io
` (11 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 UTC (permalink / raw)
To: devel; +Cc: Douglas Flick [MSFT], Saloni Kasbekar, Zachary Clark-williams
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
These tests confirm that the report bug...
"Out-of-bounds read when processing IA_NA/IA_TA options in a
DHCPv6 Advertise message"
..has been patched.
The following functions are tested to confirm an out of bounds read is
patched and that the correct statuses are returned:
Dhcp6SeekInnerOptionSafe
Dhcp6SeekStsOption
TCBZ4534
CVE-2023-45229
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Cc: Saloni Kasbekar <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 (#114467): https://edk2.groups.io/g/devel/message/114467
Mute This Topic: https://groups.io/mt/103964980/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
@ 2024-02-01 19:49 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:49 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
These tests confirm that the report bug...
"Out-of-bounds read when processing IA_NA/IA_TA options in a
DHCPv6 Advertise message"
..has been patched.
The following functions are tested to confirm an out of bounds read is patched and that the correct statuses are returned:
Dhcp6SeekInnerOptionSafe
Dhcp6SeekStsOption
TCBZ4534
CVE-2023-45229
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Cc: Saloni Kasbekar <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.decdiff --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_Hdiff --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 optiondiff --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 (#114959): https://edk2.groups.io/g/devel/message/114959
Mute This Topic: https://groups.io/mt/103964980/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (4 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 05/15] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:52 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests Doug Flick via groups.io
` (10 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Bug Overview:
PixieFail Bug #3
CVE-2023-45231
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Out-of-bounds read when handling a ND Redirect message with truncated
options
Change Overview:
Adds a check to prevent truncated options from being parsed
+ //
+ // Cannot process truncated options.
+ // Cannot process options with a length of 0 as there is no Type
field.
+ //
+ if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
+ return FALSE;
+ }
Cc: Saloni Kasbekar <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 (#114468): https://edk2.groups.io/g/devel/message/114468
Mute This Topic: https://groups.io/mt/103964981/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch Doug Flick via groups.io
@ 2024-02-01 19:52 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:52 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536
Bug Overview:
PixieFail Bug #3
CVE-2023-45231
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
CWE-125 Out-of-bounds Read
Out-of-bounds read when handling a ND Redirect message with truncated options
Change Overview:
Adds a check to prevent truncated options from being parsed
+ //
+ // Cannot process truncated options.
+ // Cannot process options with a length of 0 as there is no Type
field.
+ //
+ if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
+ return FALSE;
+ }
Cc: Saloni Kasbekar <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 (#114961): https://edk2.groups.io/g/devel/message/114961
Mute This Topic: https://groups.io/mt/103964981/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 35+ messages in thread
* [edk2-devel] [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (5 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 06/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 19:59 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
` (9 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Validates that the patch for...
Out-of-bounds read when handling a ND Redirect message with truncated
options
.. has been fixed
Tests the following function to ensure that an out of bounds read does
not occur
Ip6OptionValidation
Cc: Saloni Kasbekar <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 (#114469): https://edk2.groups.io/g/devel/message/114469
Mute This Topic: https://groups.io/mt/103964982/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests Doug Flick via groups.io
@ 2024-02-01 19:59 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 19:59 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4536
Validates that the patch for...
Out-of-bounds read when handling a ND Redirect message with truncated options
.. has been fixed
Tests the following function to ensure that an out of bounds read does not occur Ip6OptionValidation
Cc: Saloni Kasbekar <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]+ gZeroGuiddiff --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 (#114960): https://edk2.groups.io/g/devel/message/114960
Mute This Topic: https://groups.io/mt/103964982/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (6 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 07/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45231 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 20:48 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
` (8 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Bug Details:
PixieFail Bug #4
CVE-2023-45232
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Infinite loop when parsing unknown options in the Destination Options
header
PixieFail Bug #5
CVE-2023-45233
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Infinite loop when parsing a PadN option in the Destination Options
header
Change Overview:
Most importantly this change corrects the following incorrect math
and cleans up the code.
> // It is a PadN option
> //
> - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
> + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
> + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
> case Ip6OptionSkip:
> - Offset = (UINT8)(Offset + *(Option + Offset + 1));
> OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
> Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
Additionally, this change also corrects incorrect math where the calling
function was calculating the HDR EXT optionLen as a uint8 instead of a
uint16
> - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
> + OptionLen = IP6_HDR_EXT_LEN (*Option) -
IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
Additionally this check adds additional logic to santize the incoming
data
Cc: Saloni Kasbekar <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/Ip6Nd.h | 35 ++++++++++++++++
NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++
NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++-----
3 files changed, 171 insertions(+), 11 deletions(-)
diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h
index 860934a167eb..bf64e9114e13 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
@@ -56,13 +56,48 @@ VOID
VOID *Context
);
+//
+// Per RFC8200 Section 4.2
+//
+// Two of the currently-defined extension headers -- the Hop-by-Hop
+// Options header and the Destination Options header -- carry a variable
+// number of type-length-value (TLV) encoded "options", of the following
+// format:
+//
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
+// | Option Type | Opt Data Len | Option Data
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
+//
+// Option Type 8-bit identifier of the type of option.
+//
+// Opt Data Len 8-bit unsigned integer. Length of the Option
+// Data field of this option, in octets.
+//
+// Option Data Variable-length field. Option-Type-specific
+// data.
+//
typedef struct _IP6_OPTION_HEADER {
+ ///
+ /// identifier of the type of option.
+ ///
UINT8 Type;
+ ///
+ /// Length of the Option Data field of this option, in octets.
+ ///
UINT8 Length;
+ ///
+ /// Option-Type-specific data.
+ ///
} IP6_OPTION_HEADER;
STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long.");
+#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length)
+STATIC_ASSERT (
+ IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
+ "The next option is minimally the combined size of the option tag and length"
+ );
+
typedef struct _IP6_ETHE_ADDR_OPTION {
UINT8 Type;
UINT8 Length;
diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
index bd8e223c8a67..fb07c28f5ad7 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
@@ -12,6 +12,77 @@
#define IP6_FRAGMENT_OFFSET_MASK (~0x3)
+//
+// For more information see RFC 8200, Section 4.3, 4.4, and 4.6
+//
+// This example format is from section 4.6
+// This does not apply to fragment headers
+//
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Next Header | Hdr Ext Len | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+// | |
+// . .
+// . Header-Specific Data .
+// . .
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// Next Header 8-bit selector. Identifies the type of
+// header immediately following the extension
+// header. Uses the same values as the IPv4
+// Protocol field [IANA-PN].
+//
+// Hdr Ext Len 8-bit unsigned integer. Length of the
+// Destination Options header in 8-octet units,
+// not including the first 8 octets.
+
+//
+// These defines apply to the following:
+// 1. Hop by Hop
+// 2. Routing
+// 3. Destination
+//
+typedef struct _IP6_EXT_HDR {
+ ///
+ /// The Next Header field identifies the type of header immediately
+ ///
+ UINT8 NextHeader;
+ ///
+ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options
+ ///
+ UINT8 HdrExtLen;
+ ///
+ /// Header-Specific Data
+ ///
+} IP6_EXT_HDR;
+
+STATIC_ASSERT (
+ sizeof (IP6_EXT_HDR) == 2,
+ "The combined size of Next Header and Len is two 8 bit fields"
+ );
+
+//
+// IPv6 extension headers contain an 8-bit length field which describes the size of
+// the header. However, the length field only includes the size of the extension
+// header options, not the size of the first 8 bytes of the header. Therefore, in
+// order to calculate the full size of the extension header, we add 1 (to account
+// for the first 8 bytes omitted by the length field reporting) and then multiply
+// by 8 (since the size is represented in 8-byte units).
+//
+// a is the length field of the extension header (UINT8)
+// The result may be up to 2046 octets (UINT16)
+//
+#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8)
+
+// This is the maxmimum length permissible by a extension header
+// Length is UINT8 of 8 octets not including the first 8 octets
+#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR))
+STATIC_ASSERT (
+ IP6_MAX_EXT_DATA_LENGTH == 2046,
+ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"
+ );
+
typedef struct _IP6_FRAGMENT_HEADER {
UINT8 NextHeader;
UINT8 Reserved;
diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
index 8718d5d8756a..fd97ce116f98 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
@@ -17,7 +17,8 @@
@param[in] IpSb The IP6 service data.
@param[in] Packet The to be validated packet.
@param[in] Option The first byte of the option.
- @param[in] OptionLen The length of the whole option.
+ @param[in] OptionLen The length of all options, expressed in byte length of octets.
+ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255.
@param[in] Pointer Identifies the octet offset within
the invoking packet where the error was detected.
@@ -31,12 +32,33 @@ Ip6IsOptionValid (
IN IP6_SERVICE *IpSb,
IN NET_BUF *Packet,
IN UINT8 *Option,
- IN UINT8 OptionLen,
+ IN UINT16 OptionLen,
IN UINT32 Pointer
)
{
- UINT8 Offset;
- UINT8 OptionType;
+ UINT16 Offset;
+ UINT8 OptionType;
+ UINT8 OptDataLen;
+
+ if (Option == NULL) {
+ ASSERT (Option != NULL);
+ return FALSE;
+ }
+
+ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) {
+ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);
+ return FALSE;
+ }
+
+ if (Packet == NULL) {
+ ASSERT (Packet != NULL);
+ return FALSE;
+ }
+
+ if (IpSb == NULL) {
+ ASSERT (IpSb != NULL);
+ return FALSE;
+ }
Offset = 0;
@@ -54,7 +76,8 @@ Ip6IsOptionValid (
//
// It is a PadN option
//
- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
break;
case Ip6OptionRouterAlert:
//
@@ -69,7 +92,8 @@ Ip6IsOptionValid (
//
switch (OptionType & Ip6OptionMask) {
case Ip6OptionSkip:
- Offset = (UINT8)(Offset + *(Option + Offset + 1));
+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;
+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
break;
case Ip6OptionDiscard:
return FALSE;
@@ -308,7 +332,7 @@ Ip6IsExtsValid (
UINT32 Pointer;
UINT32 Offset;
UINT8 *Option;
- UINT8 OptionLen;
+ UINT16 OptionLen;
BOOLEAN Flag;
UINT8 CountD;
UINT8 CountA;
@@ -385,6 +409,36 @@ Ip6IsExtsValid (
// Fall through
//
case IP6_DESTINATION:
+ //
+ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23
+ //
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | Next Header | Hdr Ext Len | |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
+ // | |
+ // . .
+ // . Options .
+ // . .
+ // | |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ //
+ //
+ // Next Header 8-bit selector. Identifies the type of header
+ // immediately following the Destination Options
+ // header. Uses the same values as the IPv4
+ // Protocol field [RFC-1700 et seq.].
+ //
+ // Hdr Ext Len 8-bit unsigned integer. Length of the
+ // Destination Options header in 8-octet units, not
+ // including the first 8 octets.
+ //
+ // Options Variable-length field, of length such that the
+ // complete Destination Options header is an
+ // integer multiple of 8 octets long. Contains one
+ // or more TLV-encoded options, as described in
+ // section 4.2.
+ //
+
if (*NextHeader == IP6_DESTINATION) {
CountD++;
}
@@ -398,7 +452,7 @@ Ip6IsExtsValid (
Offset++;
Option = ExtHdrs + Offset;
- OptionLen = (UINT8)((*Option + 1) * 8 - 2);
+ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR);
Option++;
Offset++;
@@ -430,7 +484,7 @@ Ip6IsExtsValid (
//
// Ignore the routing header and proceed to process the next header.
//
- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
+ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen);
if (UnFragmentLen != NULL) {
*UnFragmentLen = Offset;
@@ -441,7 +495,7 @@ Ip6IsExtsValid (
// to the packet's source address, pointing to the unrecognized routing
// type.
//
- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
+ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER);
if ((IpSb != NULL) && (Packet != NULL) &&
!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
{
@@ -527,7 +581,7 @@ Ip6IsExtsValid (
//
// RFC2402, Payload length is specified in 32-bit words, minus "2".
//
- OptionLen = (UINT8)((*Option + 2) * 4);
+ OptionLen = ((UINT16)(*Option + 2) * 4);
Offset = Offset + OptionLen;
break;
--
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114470): https://edk2.groups.io/g/devel/message/114470
Mute This Topic: https://groups.io/mt/103964983/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
@ 2024-02-01 20:48 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 20:48 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch
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
Bug Details:
PixieFail Bug #4
CVE-2023-45232
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Infinite loop when parsing unknown options in the Destination Options header
PixieFail Bug #5
CVE-2023-45233
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')
Infinite loop when parsing a PadN option in the Destination Options header
Change Overview:
Most importantly this change corrects the following incorrect math and cleans up the code.
> // It is a PadN option
> //
> - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
> + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
> + Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
> case Ip6OptionSkip:
> - Offset = (UINT8)(Offset + *(Option + Offset + 1));
> OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
> Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);
Additionally, this change also corrects incorrect math where the calling function was calculating the HDR EXT optionLen as a uint8 instead of a
uint16
> - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
> + OptionLen = IP6_HDR_EXT_LEN (*Option) -
IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
Additionally this check adds additional logic to santize the incoming data
Cc: Saloni Kasbekar <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/Ip6Nd.h | 35 ++++++++++++++++
NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++++++++++++++++++++++++++++++++ NetworkPkg/Ip6Dxe/Ip6Option.c | 76 ++++++++++++++++++++++++++++++-----
3 files changed, 171 insertions(+), 11 deletions(-)
diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h index 860934a167eb..bf64e9114e13 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
@@ -56,13 +56,48 @@ VOID
VOID *Context ); +//+// Per RFC8200 Section 4.2+//+// Two of the currently-defined extension headers -- the Hop-by-Hop+// Options header and the Destination Options header -- carry a variable+// number of type-length-value (TLV) encoded "options", of the following+// format:+//+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -+// | Option Type | Opt Data Len | Option Data+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -+//+// Option Type 8-bit identifier of the type of option.+//+// Opt Data Len 8-bit unsigned integer. Length of the Option+// Data field of this option, in octets.+//+// Option Data Variable-length field. Option-Type-specific+// data.+// typedef struct _IP6_OPTION_HEADER {+ ///+ /// identifier of the type of option.+ /// UINT8 Type;+ ///+ /// Length of the Option Data field of this option, in octets.+ /// UINT8 Length;+ ///+ /// Option-Type-specific data.+ /// } IP6_OPTION_HEADER; STATIC_ASSERT (sizeof (IP6_OPTION_HEADER) == 2, "IP6_OPTION_HEADER is expected to be exactly 2 bytes long."); +#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + sizeof(IP6_OPTION_HEADER) + length)+STATIC_ASSERT (+ IP6_NEXT_OPTION_OFFSET (0, 0) == 2,+ "The next option is minimally the combined size of the option tag and length"+ );+ typedef struct _IP6_ETHE_ADDR_OPTION { UINT8 Type; UINT8 Length;diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
index bd8e223c8a67..fb07c28f5ad7 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Option.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
@@ -12,6 +12,77 @@
#define IP6_FRAGMENT_OFFSET_MASK (~0x3) +//+// For more information see RFC 8200, Section 4.3, 4.4, and 4.6+//+// This example format is from section 4.6+// This does not apply to fragment headers+//+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++// | Next Header | Hdr Ext Len | |+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++// | |+// . .+// . Header-Specific Data .+// . .+// | |+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++//+// Next Header 8-bit selector. Identifies the type of+// header immediately following the extension+// header. Uses the same values as the IPv4+// Protocol field [IANA-PN].+//+// Hdr Ext Len 8-bit unsigned integer. Length of the+// Destination Options header in 8-octet units,+// not including the first 8 octets.++//+// These defines apply to the following:+// 1. Hop by Hop+// 2. Routing+// 3. Destination+//+typedef struct _IP6_EXT_HDR {+ ///+ /// The Next Header field identifies the type of header immediately+ ///+ UINT8 NextHeader;+ ///+ /// The Hdr Ext Len field specifies the length of the Hop-by-Hop Options+ ///+ UINT8 HdrExtLen;+ ///+ /// Header-Specific Data+ ///+} IP6_EXT_HDR;++STATIC_ASSERT (+ sizeof (IP6_EXT_HDR) == 2,+ "The combined size of Next Header and Len is two 8 bit fields"+ );++//+// IPv6 extension headers contain an 8-bit length field which describes the size of+// the header. However, the length field only includes the size of the extension+// header options, not the size of the first 8 bytes of the header. Therefore, in+// order to calculate the full size of the extension header, we add 1 (to account+// for the first 8 bytes omitted by the length field reporting) and then multiply+// by 8 (since the size is represented in 8-byte units).+//+// a is the length field of the extension header (UINT8)+// The result may be up to 2046 octets (UINT16)+//+#define IP6_HDR_EXT_LEN(a) (((UINT16)((UINT8)(a)) + 1) * 8)++// This is the maxmimum length permissible by a extension header+// Length is UINT8 of 8 octets not including the first 8 octets+#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - sizeof(IP6_EXT_HDR))+STATIC_ASSERT (+ IP6_MAX_EXT_DATA_LENGTH == 2046,+ "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"+ );+ typedef struct _IP6_FRAGMENT_HEADER { UINT8 NextHeader; UINT8 Reserved;diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
index 8718d5d8756a..fd97ce116f98 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Option.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
@@ -17,7 +17,8 @@
@param[in] IpSb The IP6 service data. @param[in] Packet The to be validated packet. @param[in] Option The first byte of the option.- @param[in] OptionLen The length of the whole option.+ @param[in] OptionLen The length of all options, expressed in byte length of octets.+ Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255. @param[in] Pointer Identifies the octet offset within the invoking packet where the error was detected. @@ -31,12 +32,33 @@ Ip6IsOptionValid (
IN IP6_SERVICE *IpSb, IN NET_BUF *Packet, IN UINT8 *Option,- IN UINT8 OptionLen,+ IN UINT16 OptionLen, IN UINT32 Pointer ) {- UINT8 Offset;- UINT8 OptionType;+ UINT16 Offset;+ UINT8 OptionType;+ UINT8 OptDataLen;++ if (Option == NULL) {+ ASSERT (Option != NULL);+ return FALSE;+ }++ if ((OptionLen <= 0) || (OptionLen > IP6_MAX_EXT_DATA_LENGTH)) {+ ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);+ return FALSE;+ }++ if (Packet == NULL) {+ ASSERT (Packet != NULL);+ return FALSE;+ }++ if (IpSb == NULL) {+ ASSERT (IpSb != NULL);+ return FALSE;+ } Offset = 0; @@ -54,7 +76,8 @@ Ip6IsOptionValid (
// // It is a PadN option //- Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); break; case Ip6OptionRouterAlert: //@@ -69,7 +92,8 @@ Ip6IsOptionValid (
// switch (OptionType & Ip6OptionMask) { case Ip6OptionSkip:- Offset = (UINT8)(Offset + *(Option + Offset + 1));+ OptDataLen = ((IP6_OPTION_HEADER *)(Option + Offset))->Length;+ Offset = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen); break; case Ip6OptionDiscard: return FALSE;@@ -308,7 +332,7 @@ Ip6IsExtsValid (
UINT32 Pointer; UINT32 Offset; UINT8 *Option;- UINT8 OptionLen;+ UINT16 OptionLen; BOOLEAN Flag; UINT8 CountD; UINT8 CountA;@@ -385,6 +409,36 @@ Ip6IsExtsValid (
// Fall through // case IP6_DESTINATION:+ //+ // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23+ //+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++ // | Next Header | Hdr Ext Len | |+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ // | |+ // . .+ // . Options .+ // . .+ // | |+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++ //+ //+ // Next Header 8-bit selector. Identifies the type of header+ // immediately following the Destination Options+ // header. Uses the same values as the IPv4+ // Protocol field [RFC-1700 et seq.].+ //+ // Hdr Ext Len 8-bit unsigned integer. Length of the+ // Destination Options header in 8-octet units, not+ // including the first 8 octets.+ //+ // Options Variable-length field, of length such that the+ // complete Destination Options header is an+ // integer multiple of 8 octets long. Contains one+ // or more TLV-encoded options, as described in+ // section 4.2.+ //+ if (*NextHeader == IP6_DESTINATION) { CountD++; }@@ -398,7 +452,7 @@ Ip6IsExtsValid (
Offset++; Option = ExtHdrs + Offset;- OptionLen = (UINT8)((*Option + 1) * 8 - 2);+ OptionLen = IP6_HDR_EXT_LEN (*Option) - sizeof (IP6_EXT_HDR); Option++; Offset++; @@ -430,7 +484,7 @@ Ip6IsExtsValid (
// // Ignore the routing header and proceed to process the next header. //- Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;+ Offset = Offset + IP6_HDR_EXT_LEN (RoutingHead->HeaderLen); if (UnFragmentLen != NULL) { *UnFragmentLen = Offset;@@ -441,7 +495,7 @@ Ip6IsExtsValid (
// to the packet's source address, pointing to the unrecognized routing // type. //- Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);+ Pointer = Offset + sizeof (IP6_EXT_HDR) + sizeof (EFI_IP6_HEADER); if ((IpSb != NULL) && (Packet != NULL) && !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {@@ -527,7 +581,7 @@ Ip6IsExtsValid (
// // RFC2402, Payload length is specified in 32-bit words, minus "2". //- OptionLen = (UINT8)((*Option + 2) * 4);+ OptionLen = ((UINT16)(*Option + 2) * 4); Offset = Offset + OptionLen; break; --
2.43.0
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114962): https://edk2.groups.io/g/devel/message/114962
Mute This Topic: https://groups.io/mt/103964983/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (7 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 08/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 21:16 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
` (7 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Unit tests to confirm that..
Infinite loop when parsing unknown options in the Destination Options
header
and
Infinite loop when parsing a PadN option in the Destination Options
header
... have been patched
This patch tests the following functions:
Ip6IsOptionValid
Cc: Saloni Kasbekar <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 | 278 ++++++++++++++++++
3 files changed, 324 insertions(+), 4 deletions(-)
create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
index 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..0509b6ae30d2
--- /dev/null
+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
@@ -0,0 +1,40 @@
+/** @file
+ Exposes the functions needed to test the Ip6Option module.
+
+ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_
+#define IP6_OPTION_HEADER_GOOGLE_TEST_H_
+
+#include <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 // __IP6_OPTION_HEADER_GOOGLE_TEST_H__
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
index f2cd90e1a952..29f8a4a96e4c 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,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
}
+
+////////////////////////////////////////////////////////////////////////
+// Ip6IsOptionValid Tests
+////////////////////////////////////////////////////////////////////////
+
+// Define a fixture for your tests if needed
+class Ip6IsOptionValidTest : public ::testing::Test {
+protected:
+ // Add any setup code if needed
+ virtual void
+ SetUp (
+ )
+ {
+ // Initialize any resources or variables
+ }
+
+ // Add any cleanup code if needed
+ virtual void
+ TearDown (
+ )
+ {
+ // Clean up any resources or variables
+ }
+};
+
+// Test Description
+// Verify that a NULL option is Invalid
+TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {
+ NET_BUF Packet = { 0 };
+ // we need to define enough of the packet to make the function work
+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
+ IP6_SERVICE *IpSb = NULL;
+
+ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
+ EFI_IP6_HEADER Ip6Header = { 0 };
+
+ Ip6Header.SourceAddress = SourceAddress;
+ Ip6Header.DestinationAddress = DestinationAddress;
+ Packet.Ip.Ip6 = &Ip6Header;
+
+ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
+}
+
+// Test Description
+// Verify that an unknown option with a length of 0 and type of <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 (#114471): https://edk2.groups.io/g/devel/message/114471
Mute This Topic: https://groups.io/mt/103964985/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
@ 2024-02-01 21:16 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 21:16 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests
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
Unit tests to confirm that..
Infinite loop when parsing unknown options in the Destination Options header
and
Infinite loop when parsing a PadN option in the Destination Options header
... have been patched
This patch tests the following functions:
Ip6IsOptionValid
Cc: Saloni Kasbekar <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 | 278 ++++++++++++++++++
3 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
index 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.decdiff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
new file mode 100644
index 000000000000..0509b6ae30d2
--- /dev/null
+++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
@@ -0,0 +1,40 @@
+/** @file+ Exposes the functions needed to test the Ip6Option module.++ Copyright (c) Microsoft Corporation+ SPDX-License-Identifier: BSD-2-Clause-Patent+**/++#ifndef IP6_OPTION_HEADER_GOOGLE_TEST_H_+#define IP6_OPTION_HEADER_GOOGLE_TEST_H_++#include <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 // __IP6_OPTION_HEADER_GOOGLE_TEST_H__diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
index f2cd90e1a952..29f8a4a96e4c 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,280 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen)); }++////////////////////////////////////////////////////////////////////////+// Ip6IsOptionValid Tests+////////////////////////////////////////////////////////////////////////++// Define a fixture for your tests if needed+class Ip6IsOptionValidTest : public ::testing::Test {+protected:+ // Add any setup code if needed+ virtual void+ SetUp (+ )+ {+ // Initialize any resources or variables+ }++ // Add any cleanup code if needed+ virtual void+ TearDown (+ )+ {+ // Clean up any resources or variables+ }+};++// Test Description+// Verify that a NULL option is Invalid+TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {+ NET_BUF Packet = { 0 };+ // we need to define enough of the packet to make the function work+ // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above+ IP6_SERVICE *IpSb = NULL;++ EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };+ EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };+ EFI_IP6_HEADER Ip6Header = { 0 };++ Ip6Header.SourceAddress = SourceAddress;+ Ip6Header.DestinationAddress = DestinationAddress;+ Packet.Ip.Ip6 = &Ip6Header;++ EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));+}++// Test Description+// Verify that an unknown option with a length of 0 and type of <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 (#114964): https://edk2.groups.io/g/devel/message/114964
Mute This Topic: https://groups.io/mt/103964985/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (8 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 09/15] NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 21:22 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
` (6 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Bug Details:
PixieFail Bug #6
CVE-2023-45234
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds of
a Memory Buffer
Buffer overflow when processing DNS Servers option in a DHCPv6
Advertise message
Change Overview:
Introduces a function to cache the Dns Server and perform sanitizing
on the incoming DnsServerLen to ensure that the length is valid
> + EFI_STATUS
> + PxeBcCacheDnsServerAddresses (
> + IN PXEBC_PRIVATE_DATA *Private,
> + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
> + )
Additional code cleanup
Cc: Saloni Kasbekar <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 (#114472): https://edk2.groups.io/g/devel/message/114472
Mute This Topic: https://groups.io/mt/103964986/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
@ 2024-02-01 21:22 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 21:22 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
Bug Details:
PixieFail Bug #6
CVE-2023-45234
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds of a Memory Buffer
Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message
Change Overview:
Introduces a function to cache the Dns Server and perform sanitizing on the incoming DnsServerLen to ensure that the length is valid
> + EFI_STATUS
> + PxeBcCacheDnsServerAddresses (
> + IN PXEBC_PRIVATE_DATA *Private,
> + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
> + )
Additional code cleanup
Cc: Saloni Kasbekar <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 (#114965): https://edk2.groups.io/g/devel/message/114965
Mute This Topic: https://groups.io/mt/103964986/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (9 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 10/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 21:32 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 12/15] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
` (5 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Unit tests to that the bug..
Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise
message
..has been patched
This contains tests for the following functions:
PxeBcHandleDhcp6Offer
PxeBcCacheDnsServerAddresses
Cc: Saloni Kasbekar <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 (#114473): https://edk2.groups.io/g/devel/message/114473
Mute This Topic: https://groups.io/mt/103964987/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
@ 2024-02-01 21:32 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 21:32 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4539
Unit tests to that the bug..
Buffer overflow when processing DNS Servers option in a DHCPv6 Advertise message
..has been patched
This contains tests for the following functions:
PxeBcHandleDhcp6Offer
PxeBcCacheDnsServerAddresses
Cc: Saloni Kasbekar <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]+ gZeroGuiddiff --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 (#114966): https://edk2.groups.io/g/devel/message/114966
Mute This Topic: https://groups.io/mt/103964987/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 12/15] MdePkg: Test: Add gRT_GetTime Google Test Mock
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (10 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 11/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45234 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-01-26 19:52 ` Michael D Kinney
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
` (4 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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 (#114474): https://edk2.groups.io/g/devel/message/114474
Mute This Topic: https://groups.io/mt/103964988/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 12/15] MdePkg: Test: Add gRT_GetTime Google Test Mock
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 12/15] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
@ 2024-01-26 19:52 ` Michael D Kinney
0 siblings, 0 replies; 35+ messages in thread
From: Michael D Kinney @ 2024-01-26 19:52 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: Thursday, January 25, 2024 1:55 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 v2 12/15] 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 (#114625): https://edk2.groups.io/g/devel/message/114625
Mute This Topic: https://groups.io/mt/103964988/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (11 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 12/15] MdePkg: Test: Add gRT_GetTime Google Test Mock Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 21:37 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
` (3 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Bug Details:
PixieFail Bug #7
CVE-2023-45235
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds of
a Memory Buffer
Buffer overflow when handling Server ID option from a DHCPv6 proxy
Advertise message
Change Overview:
Performs two checks
1. Checks that the length of the duid is accurate
> + //
> + // Check that the minimum and maximum requirements are met
> + //
> + if ((OpLen < PXEBC_MIN_SIZE_OF_DUID) ||
(OpLen > PXEBC_MAX_SIZE_OF_DUID)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto ON_ERROR;
> + }
2. Ensures that the amount of data written to the buffer is tracked and
never exceeds that
> + //
> + // Check that the option length is valid.
> + //
> + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN)
> DiscoverLenNeeded) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_ERROR;
> + }
Additional code clean up and fix for memory leak in case Option was NULL
Cc: Saloni Kasbekar <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 (#114475): https://edk2.groups.io/g/devel/message/114475
Mute This Topic: https://groups.io/mt/103964991/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
@ 2024-02-01 21:37 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 21:37 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540
Bug Details:
PixieFail Bug #7
CVE-2023-45235
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds of a Memory Buffer
Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message
Change Overview:
Performs two checks
1. Checks that the length of the duid is accurate
> + //
> + // Check that the minimum and maximum requirements are met // if
> + ((OpLen < PXEBC_MIN_SIZE_OF_DUID) ||
(OpLen > PXEBC_MAX_SIZE_OF_DUID)) {
> + Status = EFI_INVALID_PARAMETER;
> + goto ON_ERROR;
> + }
2. Ensures that the amount of data written to the buffer is tracked and never exceeds that
> + //
> + // Check that the option length is valid.
> + //
> + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN)
> DiscoverLenNeeded) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_ERROR;
> + }
Additional code clean up and fix for memory leak in case Option was NULL
Cc: Saloni Kasbekar <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 (#114967): https://edk2.groups.io/g/devel/message/114967
Mute This Topic: https://groups.io/mt/103964991/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (12 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 13/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Patch Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 22:03 ` Saloni Kasbekar
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
` (2 subsequent siblings)
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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
Unit tests to confirm that the bug..
Buffer overflow when handling Server ID option from a DHCPv6 proxy
Advertise message
..has been patched.
This patch contains unit tests for the following functions:
PxeBcRequestBootService
PxeBcDhcp6Discover
Cc: Saloni Kasbekar <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 (#114476): https://edk2.groups.io/g/devel/message/114476
Mute This Topic: https://groups.io/mt/103964992/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
@ 2024-02-01 22:03 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 22:03 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io
Cc: Doug Flick, Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Doug Flick <dougflick@microsoft.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>; Doug Flick [MSFT] <doug.edk2@gmail.com>
Subject: [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests
From: Doug Flick <dougflick@microsoft.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4540
Unit tests to confirm that the bug..
Buffer overflow when handling Server ID option from a DHCPv6 proxy Advertise message
..has been patched.
This patch contains unit tests for the following functions:
PxeBcRequestBootService
PxeBcDhcp6Discover
Cc: Saloni Kasbekar <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 (#114968): https://edk2.groups.io/g/devel/message/114968
Mute This Topic: https://groups.io/mt/103964992/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] 35+ messages in thread
* [edk2-devel] [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (13 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 14/15] NetworkPkg: UefiPxeBcDxe: SECURITY PATCH CVE-2023-45235 Unit Tests Doug Flick via groups.io
@ 2024-01-25 21:54 ` Doug Flick via groups.io
2024-02-01 22:18 ` Saloni Kasbekar
2024-01-31 5:22 ` [edk2-devel] 回复: [edk2-stable202402][PATCH v2 00/15] Security Patches for EDK II Network Stack gaoliming via groups.io
[not found] ` <17AF5718015C1866.16460@groups.io>
16 siblings, 1 reply; 35+ messages in thread
From: Doug Flick via groups.io @ 2024-01-25 21:54 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 (#114477): https://edk2.groups.io/g/devel/message/114477
Mute This Topic: https://groups.io/mt/103964993/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] 35+ messages in thread
* Re: [edk2-devel] [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
@ 2024-02-01 22:18 ` Saloni Kasbekar
0 siblings, 0 replies; 35+ messages in thread
From: Saloni Kasbekar @ 2024-02-01 22:18 UTC (permalink / raw)
To: Douglas Flick [MSFT], devel@edk2.groups.io; +Cc: Clark-williams, Zachary
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
-----Original Message-----
From: Douglas Flick [MSFT] <doug.edk2@gmail.com>
Sent: Thursday, January 25, 2024 1:55 PM
To: devel@edk2.groups.io
Cc: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Kasbekar, Saloni <saloni.kasbekar@intel.com>; Clark-williams, Zachary <zachary.clark-williams@intel.com>
Subject: [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file
This creates / adds a security file that tracks the security fixes found in this package and can be used to find the fixes that were applied.
Cc: Saloni Kasbekar <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 (#114969): https://edk2.groups.io/g/devel/message/114969
Mute This Topic: https://groups.io/mt/103964993/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 35+ messages in thread
* [edk2-devel] 回复: [edk2-stable202402][PATCH v2 00/15] Security Patches for EDK II Network Stack
2024-01-25 21:54 [edk2-devel] [PATCH v2 00/15] Security Patches for EDK II Network Stack Doug Flick via groups.io
` (14 preceding siblings ...)
2024-01-25 21:54 ` [edk2-devel] [PATCH v2 15/15] NetworkPkg: : Adds a SecurityFix.yaml file Doug Flick via groups.io
@ 2024-01-31 5:22 ` gaoliming via groups.io
[not found] ` <17AF5718015C1866.16460@groups.io>
16 siblings, 0 replies; 35+ messages in thread
From: gaoliming via groups.io @ 2024-01-31 5:22 UTC (permalink / raw)
To: 'Douglas Flick [MSFT]', devel, 'Saloni Kasbekar',
'Zachary Clark-williams'
Cc: 'Michael D Kinney', 'Zhiguang Liu',
'Laszlo Ersek', 'Leif Lindholm',
'Gerd Hoffmann'
Saloni and William:
Can you help review this patch set about Security Patches for EDK II
Network Stack? This patch set plans to catch edk2-stable202402 tag. And,
edk2-stable202402 will come soon.
edk2-stable202402 tag planning
Proposed Schedule
Date (00:00:00 UTC-8) Description
2023-11-24 Beginning of development
2024-02-05 Soft Feature Freeze
2024-02-09 Hard Feature Freeze
2024-02-23 Release
Thanks
Liming
> -----邮件原件-----
> 发件人: Douglas Flick [MSFT] <doug.edk2@gmail.com>
> 发送时间: 2024年1月26日 5:55
> 收件人: devel@edk2.groups.io
> 抄送: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Saloni Kasbekar
> <saloni.kasbekar@intel.com>; Zachary Clark-williams
> <zachary.clark-williams@intel.com>; Michael D Kinney
> <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
> Zhiguang Liu <zhiguang.liu@intel.com>
> 主题: [PATCH v2 00/15] Security Patches for EDK II Network Stack
>
> 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] (7):
> NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
> NetworkPkg: : Add Unit tests to CI and create Host Test DSC
> 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/Ip6Nd.h | 35 +
> NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++
> .../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 | 407 +++++++++
> NetworkPkg/NetworkPkg.ci.yaml | 7 +-
> NetworkPkg/SecurityFixes.yaml | 123 +++
> .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 574 ++++++++++++
> .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 +
> 26 files changed, 3650 insertions(+), 339 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 (#114858): https://edk2.groups.io/g/devel/message/114858
Mute This Topic: https://groups.io/mt/104070131/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 35+ messages in thread
[parent not found: <17AF5718015C1866.16460@groups.io>]
* 回复: [edk2-devel] 回复: [edk2-stable202402][PATCH v2 00/15] Security Patches for EDK II Network Stack
[not found] ` <17AF5718015C1866.16460@groups.io>
@ 2024-02-07 14:26 ` gaoliming via groups.io
0 siblings, 0 replies; 35+ messages in thread
From: gaoliming via groups.io @ 2024-02-07 14:26 UTC (permalink / raw)
To: devel, gaoliming, 'Douglas Flick [MSFT]',
'Saloni Kasbekar', 'Zachary Clark-williams'
Cc: 'Michael D Kinney', 'Zhiguang Liu',
'Laszlo Ersek', 'Leif Lindholm',
'Gerd Hoffmann'
Hi, all
This patch set has passed reviewed. I create PR
https://github.com/tianocore/edk2/pull/5352 to merge it for stable 202402
tag.
Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 gaoliming via
> groups.io
> 发送时间: 2024年1月31日 13:22
> 收件人: 'Douglas Flick [MSFT]' <doug.edk2@gmail.com>;
> devel@edk2.groups.io; 'Saloni Kasbekar' <saloni.kasbekar@intel.com>;
> 'Zachary Clark-williams' <zachary.clark-williams@intel.com>
> 抄送: 'Michael D Kinney' <michael.d.kinney@intel.com>; 'Zhiguang Liu'
> <zhiguang.liu@intel.com>; 'Laszlo Ersek' <lersek@redhat.com>; 'Leif
> Lindholm' <quic_llindhol@quicinc.com>; 'Gerd Hoffmann'
> <kraxel@redhat.com>
> 主题: [edk2-devel] 回复: [edk2-stable202402][PATCH v2 00/15] Security
> Patches for EDK II Network Stack
>
> Saloni and William:
> Can you help review this patch set about Security Patches for EDK II
> Network Stack? This patch set plans to catch edk2-stable202402 tag. And,
> edk2-stable202402 will come soon.
>
> edk2-stable202402 tag planning
> Proposed Schedule
> Date (00:00:00 UTC-8) Description
> 2023-11-24 Beginning of development
> 2024-02-05 Soft Feature Freeze
> 2024-02-09 Hard Feature Freeze
> 2024-02-23 Release
>
> Thanks
> Liming
> > -----邮件原件-----
> > 发件人: Douglas Flick [MSFT] <doug.edk2@gmail.com>
> > 发送时间: 2024年1月26日 5:55
> > 收件人: devel@edk2.groups.io
> > 抄送: Douglas Flick [MSFT] <doug.edk2@gmail.com>; Saloni Kasbekar
> > <saloni.kasbekar@intel.com>; Zachary Clark-williams
> > <zachary.clark-williams@intel.com>; Michael D Kinney
> > <michael.d.kinney@intel.com>; Liming Gao <gaoliming@byosoft.com.cn>;
> > Zhiguang Liu <zhiguang.liu@intel.com>
> > 主题: [PATCH v2 00/15] Security Patches for EDK II Network Stack
> >
> > 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] (7):
> > NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch
> > NetworkPkg: : Add Unit tests to CI and create Host Test DSC
> > 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/Ip6Nd.h | 35 +
> > NetworkPkg/Ip6Dxe/Ip6Option.h | 71 ++
> > .../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 | 407 +++++++++
> > NetworkPkg/NetworkPkg.ci.yaml | 7 +-
> > NetworkPkg/SecurityFixes.yaml | 123 +++
> > .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 574 ++++++++++++
> > .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 19 +
> > 26 files changed, 3650 insertions(+), 339 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 (#115236): https://edk2.groups.io/g/devel/message/115236
Mute This Topic: https://groups.io/mt/104218918/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 35+ messages in thread