From nobody Mon Feb 9 10:48:27 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+67706+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+67706+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1605783260; cv=none; d=zohomail.com; s=zohoarc; b=L8V9I8fX9g4N0jIdhvUz2s/6U8XaQhdBe4vNPGwFUgUfMy/fWM6NvuW0FHT6fAhemdKG98gMHI4rHrvkBp5HOHrdvaJx1qkmzRtIxK02hxMiaHYoq+jbRap+O0/11vWTrT6CKz/pdWtw//jsffVTsi5hXcv8BlTelDGQyz4wWUE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605783260; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=fGiUYZyhWH0hB04FcGL0UPMR9un5Ncto1Rd2fY1YKbY=; b=TetneimxDenc4lIVZ/RBSfbyherwXTrUXCH0flsYA4V/gsmdeNdHla0W2S0TP7Dp6NuV2+uECP6vkXINrjsdF1xSPhp9UioG/+v/vzoomx3O5sMHcRqgLbVGIKDQaaLn0SkxgQ24LRuRIg9I/2zbt6v1k8a+Gdf0fRHsSb2RIGA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+67706+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1605783260837427.9485596906851; Thu, 19 Nov 2020 02:54:20 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id gDpEYY1788612xzE4NfUUDkx; Thu, 19 Nov 2020 02:54:20 -0800 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.groups.io with SMTP id smtpd.web08.7637.1605783259836052515 for ; Thu, 19 Nov 2020 02:54:20 -0800 X-Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-216-27nROoU4MZ6SxrQmLWl4PQ-1; Thu, 19 Nov 2020 05:54:14 -0500 X-MC-Unique: 27nROoU4MZ6SxrQmLWl4PQ-1 X-Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 304F18EEA91; Thu, 19 Nov 2020 10:53:47 +0000 (UTC) X-Received: from lacos-laptop-7.usersys.redhat.com (ovpn-112-236.ams2.redhat.com [10.36.112.236]) by smtp.corp.redhat.com (Postfix) with ESMTP id A0BB31346F; Thu, 19 Nov 2020 10:53:45 +0000 (UTC) From: "Laszlo Ersek" To: edk2-devel-groups-io Cc: Dandan Bi , Hao A Wu , Jian J Wang , Liming Gao , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [edk2-devel] [PATCH v2 RESEND 2/2] MdeModulePkg/Core/Dxe: limit FwVol encapsulation section recursion Date: Thu, 19 Nov 2020 11:53:40 +0100 Message-Id: <20201119105340.16225-3-lersek@redhat.com> In-Reply-To: <20201119105340.16225-1-lersek@redhat.com> References: <20201119105340.16225-1-lersek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,lersek@redhat.com X-Gm-Message-State: pxQlSJLqkH6A7blUZ7mItQaPx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1605783260; bh=fGiUYZyhWH0hB04FcGL0UPMR9un5Ncto1Rd2fY1YKbY=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=wObr7FC+HY1CWqYZzajF721+PhBCwJf7jWcL4GUghVbXhx7oajjIi0Dpu2Xp5smY4qC W4efDwLr8bHkVqFdMzEFcVlFJpoCD5s7R0rJRgl3C/xJPKq/24424FF2yvzTAur3SDgp5 lkHYqNpnjCkA8S8pnjYixBM0O4KztAhFI98= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" 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 Cc: Hao A Wu Cc: Jian J Wang Cc: Liming Gao Cc: Philippe Mathieu-Daud=C3=A9 Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1743 Signed-off-by: Laszlo Ersek Reviewed-by: Liming Gao Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- MdeModulePkg/MdeModulePkg.dec | 6 ++++ MdeModulePkg/MdeModulePkg.uni | 6 ++++ MdeModulePkg/Core/Dxe/DxeMain.inf | 1 + MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c | 33 +++++= +++++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 00075528198d..9b52b3449443 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -1529,6 +1529,12 @@ [PcdsFixedAtBuild, PcdsPatchableInModule] # @Prompt Enable Capsule On Disk support. gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0= 000002d =20 + ## Maximum permitted encapsulation levels of sections in a firmware volu= me, + # 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|UIN= T32|0x00000030 + [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## This PCD defines the Console output row. The default value is 25 acco= rding to UEFI spec. # This PCD could be set to 0 then console output would be at max column= and max row. diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index 40884c57a460..1b347a75f684 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -1160,6 +1160,12 @@ = "Note:
" = "If Both Capsule In Ram and Capsule On Disk are provisione= d at the same time, the Capsule On Disk will be bypassed." =20 +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDept= h_PROMPT #language en-US "Maximum permitted FwVol section nesting depth (ex= clusive)." + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDept= h_HELP #language en-US "Maximum permitted encapsulation levels of section= s in a firmware volume,
" + = "in the DXE phase. Minimum value is 1. Sections ne= sted more deeply are
" + = "rejected." + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT = #language en-US "Enable Capsule In Ram support" =20 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP #l= anguage en-US "Capsule In Ram is to use memory to deliver the capsules th= at will be processed after system reset.

" diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeM= ain.inf index 1d4b11dc7318..e4bca895773d 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -185,6 +185,7 @@ [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth = ## CONSUMES =20 # [Hob] # RESOURCE_DESCRIPTOR ## CONSUMES diff --git a/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.= c b/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c index d7f7ef427422..908617d1ca5c 100644 --- a/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c +++ b/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c @@ -955,6 +955,9 @@ CreateChildNode ( This is an in/out parameter and it is 1-b= ased, 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 th= e child was found in. If this stream was generat= ed 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 prot= ocol does not exist + @retval EFI_ABORTED Recursion aborted because Depth has been + greater than or equal to + PcdFwVolDxeMaxEncapsulationDepth. =20 **/ 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 ( =20 ASSERT (*SectionInstance > 0); =20 + if (Depth >=3D PcdGet32 (PcdFwVolDxeMaxEncapsulationDepth)) { + return EFI_ABORTED; + } + CurrentChildNode =3D NULL; ErrorStatus =3D EFI_NOT_FOUND; =20 @@ -1053,6 +1064,7 @@ FindChildNode ( SearchType, SectionInstance, SectionDefinitionGuid, + Depth + 1, &RecursedChildNode, &RecursedFoundStream, AuthenticationStatus @@ -1067,9 +1079,17 @@ FindChildNode ( *FoundStream =3D RecursedFoundStream; return EFI_SUCCESS; } else { + if (Status =3D=3D EFI_ABORTED) { + // + // If the recursive call was aborted due to nesting depth, stop + // looking for the requested child node. The skipped subtree cou= ld + // throw off the instance counting. + // + return Status; + } // - // If the status is not EFI_SUCCESS, just save the error code and - // continue to find the request child node in the rest stream. + // Save the error code and continue to find the requested child no= de in + // the rest of the stream. // ErrorStatus =3D Status; } @@ -1272,11 +1292,20 @@ GetSection ( *SectionType, &Instance, SectionDefinitionGuid, + 0, // encapsulation depth &ChildNode, &ChildStreamNode, &ExtractedAuthenticationStatus ); if (EFI_ERROR (Status)) { + if (Status =3D=3D EFI_ABORTED) { + DEBUG ((DEBUG_ERROR, "%a: recursion aborted due to nesting depth\n= ", + __FUNCTION__)); + // + // Map "aborted" to "not found". + // + Status =3D EFI_NOT_FOUND; + } goto GetSection_Done; } =20 --=20 2.19.1.3.g30247aa5d201 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#67706): https://edk2.groups.io/g/devel/message/67706 Mute This Topic: https://groups.io/mt/78362189/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-