NetworkPkg: Ip6Dxe: SECURITY PATCH CVE-2023-45232 Patch

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

Bug Details:
PixieFail Bug #4
CVE-2023-45232
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')

Infinite loop when parsing unknown options in the Destination Options
header

PixieFail Bug #5
CVE-2023-45233
CVSS 7.5 : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE-835 Loop with Unreachable Exit Condition ('Infinite Loop')

Infinite loop when parsing a PadN option in the Destination Options
header

Change Overview:

Most importantly this change corrects the following incorrect math
and cleans up the code.

>   // It is a PadN option
>   //
> - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
> + OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
> + Offset     = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);

> case Ip6OptionSkip:
> - Offset = (UINT8)(Offset + *(Option + Offset + 1));
>   OptDataLen = ((EFI_IP6_OPTION *)(Option + Offset))->Length;
>   Offset     = IP6_NEXT_OPTION_OFFSET (Offset, OptDataLen);

Additionally, this change also corrects incorrect math where the calling
function was calculating the HDR EXT optionLen as a uint8 instead of a
uint16

> - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
> + OptionLen = IP6_HDR_EXT_LEN (*Option) -
IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;

Additionally this check adds additional logic to santize the incoming
data

Cc: Saloni Kasbekar <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>
This commit is contained in:
Doug Flick
2024-01-26 05:54:50 +08:00
committed by mergify[bot]
parent 6f77463d72
commit 4df0229ef9
3 changed files with 171 additions and 11 deletions

View File

@@ -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;