You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
622 lines
24 KiB
622 lines
24 KiB
6 months ago
|
From a115d0a66c3e73c60b74ec6d09e3759da89e919b Mon Sep 17 00:00:00 2001
|
||
|
From: Jon Maloy <jmaloy@redhat.com>
|
||
|
Date: Fri, 9 Feb 2024 17:57:07 -0500
|
||
|
Subject: [PATCH 17/17] NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229
|
||
|
Patch
|
||
|
|
||
|
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||
|
RH-MergeRequest: 50: CVE-2023-45230 and CVE-2023-45229
|
||
|
RH-Jira: RHEL-21840 RHEL-21842
|
||
|
RH-Acked-by: Oliver Steffen <osteffen@redhat.com>
|
||
|
RH-Commit: [4/4] 3daf69000f78416ee1f1bad0b6ceb01ed28a84a5 (jmaloy/jons_fork)
|
||
|
|
||
|
JIRA: https://issues.redhat.com/browse/RHEL-21840
|
||
|
CVE: CVE-2023-45229
|
||
|
Upstream: Merged
|
||
|
|
||
|
commit 1dbb10cc52dc8ef49bb700daa1cefc76b26d52e0
|
||
|
Author: Doug Flick via groups.io <dougflick=microsoft.com@groups.io>
|
||
|
Date: Fri Jan 26 05:54:46 2024 +0800
|
||
|
|
||
|
NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45229 Patch
|
||
|
|
||
|
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4534
|
||
|
|
||
|
Bug Details:
|
||
|
PixieFail Bug #1
|
||
|
CVE-2023-45229
|
||
|
CVSS 6.5 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
|
||
|
CWE-125 Out-of-bounds Read
|
||
|
|
||
|
Change Overview:
|
||
|
|
||
|
Introduce Dhcp6SeekInnerOptionSafe which performs checks before seeking
|
||
|
the Inner Option from a DHCP6 Option.
|
||
|
|
||
|
>
|
||
|
> EFI_STATUS
|
||
|
> Dhcp6SeekInnerOptionSafe (
|
||
|
> IN UINT16 IaType,
|
||
|
> IN UINT8 *Option,
|
||
|
> IN UINT32 OptionLen,
|
||
|
> OUT UINT8 **IaInnerOpt,
|
||
|
> OUT UINT16 *IaInnerLen
|
||
|
> );
|
||
|
>
|
||
|
|
||
|
Lots of code cleanup to improve code readability.
|
||
|
|
||
|
Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
|
||
|
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>
|
||
|
|
||
|
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
|
||
|
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
|
||
|
|
||
|
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||
|
---
|
||
|
NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 138 ++++++++++++++++++---
|
||
|
NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 205 +++++++++++++++++++++-----------
|
||
|
2 files changed, 257 insertions(+), 86 deletions(-)
|
||
|
|
||
|
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||
|
index ec0ed5d8f5..e759ab9a62 100644
|
||
|
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||
|
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
|
||
|
@@ -47,6 +47,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
|
||
|
//
|
||
|
@@ -61,12 +75,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)
|
||
|
|
||
|
@@ -75,34 +87,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 2976684aba..d680febbf1 100644
|
||
|
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
|
||
|
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
|
||
|
@@ -611,8 +611,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
|
||
|
@@ -621,13 +621,14 @@ Dhcp6UpdateIaInfo (
|
||
|
if (T1 > T2 && T2 > 0) {
|
||
|
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);
|
||
|
+
|
||
|
+ IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT (Option);
|
||
|
+ IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN (Option)))) - DHCP6_SIZE_OF_IAID);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
@@ -653,7 +654,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;
|
||
|
}
|
||
|
@@ -675,6 +676,87 @@ Dhcp6UpdateIaInfo (
|
||
|
|
||
|
|
||
|
|
||
|
+/**
|
||
|
+ 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.
|
||
|
@@ -695,9 +777,15 @@ Dhcp6SeekStsOption (
|
||
|
OUT UINT8 **Option
|
||
|
)
|
||
|
{
|
||
|
- UINT8 *IaInnerOpt;
|
||
|
- UINT16 IaInnerLen;
|
||
|
- UINT16 StsCode;
|
||
|
+ 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
|
||
|
@@ -705,12 +793,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;
|
||
|
}
|
||
|
@@ -721,7 +809,7 @@ Dhcp6SeekStsOption (
|
||
|
//
|
||
|
*Option = Dhcp6SeekIaOption (
|
||
|
Packet->Dhcp6.Option,
|
||
|
- Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
+ OptionLen,
|
||
|
&Instance->Config->IaDescriptor
|
||
|
);
|
||
|
if (*Option == NULL) {
|
||
|
@@ -729,52 +817,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;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
@@ -798,7 +869,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;
|
||
|
}
|
||
|
@@ -1123,7 +1194,7 @@ Dhcp6SendRequestMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption (
|
||
|
Instance->AdSelect->Dhcp6.Option,
|
||
|
- Instance->AdSelect->Length - 4,
|
||
|
+ Instance->AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
if (Option == NULL) {
|
||
|
@@ -1309,7 +1380,7 @@ Dhcp6SendDeclineMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption (
|
||
|
LastReply->Dhcp6.Option,
|
||
|
- LastReply->Length - 4,
|
||
|
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
if (Option == NULL) {
|
||
|
@@ -1469,7 +1540,7 @@ Dhcp6SendReleaseMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption (
|
||
|
LastReply->Dhcp6.Option,
|
||
|
- LastReply->Length - 4,
|
||
|
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
if (Option == NULL) {
|
||
|
@@ -1695,7 +1766,7 @@ Dhcp6SendRenewRebindMsg (
|
||
|
|
||
|
Option = Dhcp6SeekOption (
|
||
|
LastReply->Dhcp6.Option,
|
||
|
- LastReply->Length - 4,
|
||
|
+ LastReply->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
if (Option == NULL) {
|
||
|
@@ -2235,7 +2306,7 @@ Dhcp6HandleReplyMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption (
|
||
|
Packet->Dhcp6.Option,
|
||
|
- Packet->Length - 4,
|
||
|
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptRapidCommit
|
||
|
);
|
||
|
|
||
|
@@ -2383,7 +2454,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:
|
||
|
//
|
||
|
@@ -2514,7 +2585,7 @@ Dhcp6SelectAdvertiseMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption(
|
||
|
AdSelect->Dhcp6.Option,
|
||
|
- AdSelect->Length - 4,
|
||
|
+ AdSelect->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerUnicast
|
||
|
);
|
||
|
|
||
|
@@ -2526,7 +2597,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));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
@@ -2580,7 +2651,7 @@ Dhcp6HandleAdvertiseMsg (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption(
|
||
|
Packet->Dhcp6.Option,
|
||
|
- Packet->Length - 4,
|
||
|
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptRapidCommit
|
||
|
);
|
||
|
|
||
|
@@ -2676,7 +2747,7 @@ Dhcp6HandleAdvertiseMsg (
|
||
|
CopyMem (Instance->AdSelect, Packet, Packet->Size);
|
||
|
|
||
|
if (Option != NULL) {
|
||
|
- Instance->AdPref = *(Option + 4);
|
||
|
+ Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA (Option));
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
@@ -2747,11 +2818,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;
|
||
|
}
|
||
|
|
||
|
@@ -2760,7 +2831,7 @@ Dhcp6HandleStateful (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption(
|
||
|
Packet->Dhcp6.Option,
|
||
|
- Packet->Length - 4,
|
||
|
+ Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
|
||
|
@@ -2865,7 +2936,7 @@ Dhcp6HandleStateless (
|
||
|
//
|
||
|
Option = Dhcp6SeekOption (
|
||
|
Packet->Dhcp6.Option,
|
||
|
- Packet->Length - 4,
|
||
|
+ Packet->Length - sizeof (EFI_DHCP6_HEADER),
|
||
|
Dhcp6OptServerId
|
||
|
);
|
||
|
|
||
|
--
|
||
|
2.41.0
|
||
|
|