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.PcdHeapGuardPropertyMask ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth ## CONSUMES
|
||||
|
||||
# [Hob]
|
||||
# RESOURCE_DESCRIPTOR ## CONSUMES
|
||||
|
|
|
@ -955,6 +955,9 @@ CreateChildNode (
|
|||
This is an in/out parameter and it is 1-based,
|
||||
to deal with recursions.
|
||||
@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 FoundStream Output indicating which section stream the child
|
||||
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_PROTOCOL_ERROR a required GUIDED section extraction protocol
|
||||
does not exist
|
||||
@retval EFI_ABORTED Recursion aborted because Depth has been
|
||||
greater than or equal to
|
||||
PcdFwVolDxeMaxEncapsulationDepth.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
|
@ -976,6 +982,7 @@ FindChildNode (
|
|||
IN EFI_SECTION_TYPE SearchType,
|
||||
IN OUT UINTN *SectionInstance,
|
||||
IN EFI_GUID *SectionDefinitionGuid,
|
||||
IN UINT32 Depth,
|
||||
OUT CORE_SECTION_CHILD_NODE **FoundChild,
|
||||
OUT CORE_SECTION_STREAM_NODE **FoundStream,
|
||||
OUT UINT32 *AuthenticationStatus
|
||||
|
@ -990,6 +997,10 @@ FindChildNode (
|
|||
|
||||
ASSERT (*SectionInstance > 0);
|
||||
|
||||
if (Depth >= PcdGet32 (PcdFwVolDxeMaxEncapsulationDepth)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
CurrentChildNode = NULL;
|
||||
ErrorStatus = EFI_NOT_FOUND;
|
||||
|
||||
|
@ -1053,6 +1064,7 @@ FindChildNode (
|
|||
SearchType,
|
||||
SectionInstance,
|
||||
SectionDefinitionGuid,
|
||||
Depth + 1,
|
||||
&RecursedChildNode,
|
||||
&RecursedFoundStream,
|
||||
AuthenticationStatus
|
||||
|
@ -1067,9 +1079,17 @@ FindChildNode (
|
|||
*FoundStream = RecursedFoundStream;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
if (Status == EFI_ABORTED) {
|
||||
//
|
||||
// If the status is not EFI_SUCCESS, just save the error code and
|
||||
// continue to find the request child node in the rest stream.
|
||||
// If the recursive call was aborted due to nesting depth, stop
|
||||
// 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;
|
||||
}
|
||||
|
@ -1272,11 +1292,20 @@ GetSection (
|
|||
*SectionType,
|
||||
&Instance,
|
||||
SectionDefinitionGuid,
|
||||
0, // encapsulation depth
|
||||
&ChildNode,
|
||||
&ChildStreamNode,
|
||||
&ExtractedAuthenticationStatus
|
||||
);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1529,6 +1529,12 @@
|
|||
# @Prompt Enable Capsule On Disk support.
|
||||
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]
|
||||
## 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.
|
||||
|
|
|
@ -1160,6 +1160,12 @@
|
|||
"Note:<BR>"
|
||||
"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_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