mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/Core/Dxe: limit FwVol encapsulation section recursion
The DXE Core sets up a protocol notify function in its entry point, for instances of the Firmware Volume Block2 Protocol: DxeMain() [DxeMain/DxeMain.c] FwVolDriverInit() [FwVol/FwVol.c] Assume that a 3rd party UEFI driver or application installs an FVB instance, with crafted contents. The notification function runs: NotifyFwVolBlock() [FwVol/FwVol.c] installing an instance of the Firmware Volume 2 Protocol on the handle. (Alternatively, assume that a 3rd party application calls gDS->ProcessFirmwareVolume(), which may also produce a Firmware Volume 2 Protocol instance.) The EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() member performs "a depth-first, left-to-right search algorithm through all sections found in the specified file" (quoting the PI spec), as follows: FvReadFileSection() [FwVol/FwVolRead.c] GetSection() [SectionExtraction/CoreSectionExtraction.c] FindChildNode() [SectionExtraction/CoreSectionExtraction.c] FindChildNode() // recursive call FindChildNode() is called recursively for encapsulation sections. Currently this recursion is not limited. Introduce a new PCD (fixed-at-build, or patchable-in-module), and make FindChildNode() track the section nesting depth against that PCD. Cc: Dandan Bi <dandan.bi@intel.com> Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1743 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20201119105340.16225-3-lersek@redhat.com>
This commit is contained in:
parent
b9bdfc7285
commit
47343af304
|
@ -185,6 +185,7 @@
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth ## CONSUMES
|
||||||
|
|
||||||
# [Hob]
|
# [Hob]
|
||||||
# RESOURCE_DESCRIPTOR ## CONSUMES
|
# RESOURCE_DESCRIPTOR ## CONSUMES
|
||||||
|
|
|
@ -955,6 +955,9 @@ CreateChildNode (
|
||||||
This is an in/out parameter and it is 1-based,
|
This is an in/out parameter and it is 1-based,
|
||||||
to deal with recursions.
|
to deal with recursions.
|
||||||
@param SectionDefinitionGuid Guid of section definition
|
@param SectionDefinitionGuid Guid of section definition
|
||||||
|
@param Depth Nesting depth of encapsulation sections.
|
||||||
|
Callers different from FindChildNode() are
|
||||||
|
responsible for passing in a zero Depth.
|
||||||
@param FoundChild Output indicating the child node that is found.
|
@param FoundChild Output indicating the child node that is found.
|
||||||
@param FoundStream Output indicating which section stream the child
|
@param FoundStream Output indicating which section stream the child
|
||||||
was found in. If this stream was generated as a
|
was found in. If this stream was generated as a
|
||||||
|
@ -968,6 +971,9 @@ CreateChildNode (
|
||||||
@retval EFI_NOT_FOUND Requested child node does not exist.
|
@retval EFI_NOT_FOUND Requested child node does not exist.
|
||||||
@retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
|
@retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
|
||||||
does not exist
|
does not exist
|
||||||
|
@retval EFI_ABORTED Recursion aborted because Depth has been
|
||||||
|
greater than or equal to
|
||||||
|
PcdFwVolDxeMaxEncapsulationDepth.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -976,6 +982,7 @@ FindChildNode (
|
||||||
IN EFI_SECTION_TYPE SearchType,
|
IN EFI_SECTION_TYPE SearchType,
|
||||||
IN OUT UINTN *SectionInstance,
|
IN OUT UINTN *SectionInstance,
|
||||||
IN EFI_GUID *SectionDefinitionGuid,
|
IN EFI_GUID *SectionDefinitionGuid,
|
||||||
|
IN UINT32 Depth,
|
||||||
OUT CORE_SECTION_CHILD_NODE **FoundChild,
|
OUT CORE_SECTION_CHILD_NODE **FoundChild,
|
||||||
OUT CORE_SECTION_STREAM_NODE **FoundStream,
|
OUT CORE_SECTION_STREAM_NODE **FoundStream,
|
||||||
OUT UINT32 *AuthenticationStatus
|
OUT UINT32 *AuthenticationStatus
|
||||||
|
@ -990,6 +997,10 @@ FindChildNode (
|
||||||
|
|
||||||
ASSERT (*SectionInstance > 0);
|
ASSERT (*SectionInstance > 0);
|
||||||
|
|
||||||
|
if (Depth >= PcdGet32 (PcdFwVolDxeMaxEncapsulationDepth)) {
|
||||||
|
return EFI_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
CurrentChildNode = NULL;
|
CurrentChildNode = NULL;
|
||||||
ErrorStatus = EFI_NOT_FOUND;
|
ErrorStatus = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
@ -1053,6 +1064,7 @@ FindChildNode (
|
||||||
SearchType,
|
SearchType,
|
||||||
SectionInstance,
|
SectionInstance,
|
||||||
SectionDefinitionGuid,
|
SectionDefinitionGuid,
|
||||||
|
Depth + 1,
|
||||||
&RecursedChildNode,
|
&RecursedChildNode,
|
||||||
&RecursedFoundStream,
|
&RecursedFoundStream,
|
||||||
AuthenticationStatus
|
AuthenticationStatus
|
||||||
|
@ -1067,9 +1079,17 @@ FindChildNode (
|
||||||
*FoundStream = RecursedFoundStream;
|
*FoundStream = RecursedFoundStream;
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
if (Status == EFI_ABORTED) {
|
||||||
//
|
//
|
||||||
// If the status is not EFI_SUCCESS, just save the error code and
|
// If the recursive call was aborted due to nesting depth, stop
|
||||||
// continue to find the request child node in the rest stream.
|
// looking for the requested child node. The skipped subtree could
|
||||||
|
// throw off the instance counting.
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Save the error code and continue to find the requested child node in
|
||||||
|
// the rest of the stream.
|
||||||
//
|
//
|
||||||
ErrorStatus = Status;
|
ErrorStatus = Status;
|
||||||
}
|
}
|
||||||
|
@ -1272,11 +1292,20 @@ GetSection (
|
||||||
*SectionType,
|
*SectionType,
|
||||||
&Instance,
|
&Instance,
|
||||||
SectionDefinitionGuid,
|
SectionDefinitionGuid,
|
||||||
|
0, // encapsulation depth
|
||||||
&ChildNode,
|
&ChildNode,
|
||||||
&ChildStreamNode,
|
&ChildStreamNode,
|
||||||
&ExtractedAuthenticationStatus
|
&ExtractedAuthenticationStatus
|
||||||
);
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
|
if (Status == EFI_ABORTED) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: recursion aborted due to nesting depth\n",
|
||||||
|
__FUNCTION__));
|
||||||
|
//
|
||||||
|
// Map "aborted" to "not found".
|
||||||
|
//
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
goto GetSection_Done;
|
goto GetSection_Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1529,6 +1529,12 @@
|
||||||
# @Prompt Enable Capsule On Disk support.
|
# @Prompt Enable Capsule On Disk support.
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0000002d
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0000002d
|
||||||
|
|
||||||
|
## Maximum permitted encapsulation levels of sections in a firmware volume,
|
||||||
|
# in the DXE phase. Minimum value is 1. Sections nested more deeply are
|
||||||
|
# rejected.
|
||||||
|
# @Prompt Maximum permitted FwVol section nesting depth (exclusive).
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth|0x10|UINT32|0x00000030
|
||||||
|
|
||||||
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
|
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
|
||||||
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
|
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
|
||||||
# This PCD could be set to 0 then console output would be at max column and max row.
|
# This PCD could be set to 0 then console output would be at max column and max row.
|
||||||
|
|
|
@ -1160,6 +1160,12 @@
|
||||||
"Note:<BR>"
|
"Note:<BR>"
|
||||||
"If Both Capsule In Ram and Capsule On Disk are provisioned at the same time, the Capsule On Disk will be bypassed."
|
"If Both Capsule In Ram and Capsule On Disk are provisioned at the same time, the Capsule On Disk will be bypassed."
|
||||||
|
|
||||||
|
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDepth_PROMPT #language en-US "Maximum permitted FwVol section nesting depth (exclusive)."
|
||||||
|
|
||||||
|
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDepth_HELP #language en-US "Maximum permitted encapsulation levels of sections in a firmware volume,<BR>"
|
||||||
|
"in the DXE phase. Minimum value is 1. Sections nested more deeply are<BR>"
|
||||||
|
"rejected."
|
||||||
|
|
||||||
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT #language en-US "Enable Capsule In Ram support"
|
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT #language en-US "Enable Capsule In Ram support"
|
||||||
|
|
||||||
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP #language en-US "Capsule In Ram is to use memory to deliver the capsules that will be processed after system reset.<BR><BR>"
|
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP #language en-US "Capsule In Ram is to use memory to deliver the capsules that will be processed after system reset.<BR><BR>"
|
||||||
|
|
Loading…
Reference in New Issue