NetworkPkg/Ip6Dxe: Validate source data record length

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

Ip6ConfigReadConfigData() reads configuration data from a UEFI variable
and copies the data to another buffer. This change checks that the
length
of the data record being copied does not exceed the size of the source
UEFI variable data buffer.

If the size is exceeded, this change follows existing logic to treat the
variable as corrupted and deletes the variable so it will be set again.

Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
This commit is contained in:
Michael Kubacki 2020-04-07 22:46:37 -07:00 committed by mergify[bot]
parent df4f154da9
commit 1c76101134

View File

@ -2,6 +2,7 @@
The implementation of EFI IPv6 Configuration Protocol. The implementation of EFI IPv6 Configuration Protocol.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -390,24 +391,9 @@ Ip6ConfigReadConfigData (
); );
if (EFI_ERROR (Status) || (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize)) != 0) { if (EFI_ERROR (Status) || (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize)) != 0) {
// //
// GetVariable still error or the variable is corrupted. // GetVariable error or the variable is corrupted.
// Fall back to the default value.
// //
FreePool (Variable); goto Error;
//
// Remove the problematic variable and return EFI_NOT_FOUND, a new
// variable will be set again.
//
gRT->SetVariable (
VarName,
&gEfiIp6ConfigProtocolGuid,
IP6_CONFIG_VARIABLE_ATTRIBUTE,
0,
NULL
);
return EFI_NOT_FOUND;
} }
// //
@ -432,7 +418,12 @@ Ip6ConfigReadConfigData (
if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) { if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
// //
// This data item has variable length data. // This data item has variable length data.
// Check that the length is contained within the variable before allocating.
// //
if (DataRecord.DataSize > VarSize - DataRecord.Offset) {
goto Error;
}
DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize); DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize);
if (DataItem->Data.Ptr == NULL) { if (DataItem->Data.Ptr == NULL) {
// //
@ -454,6 +445,28 @@ Ip6ConfigReadConfigData (
} }
return Status; return Status;
Error:
//
// Fall back to the default value.
//
if (Variable != NULL) {
FreePool (Variable);
}
//
// Remove the problematic variable and return EFI_NOT_FOUND, a new
// variable will be set again.
//
gRT->SetVariable (
VarName,
&gEfiIp6ConfigProtocolGuid,
IP6_CONFIG_VARIABLE_ATTRIBUTE,
0,
NULL
);
return EFI_NOT_FOUND;
} }
/** /**