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

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