From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 03EF181F50 for ; Mon, 6 Feb 2017 06:51:28 -0800 (PST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP; 06 Feb 2017 06:51:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,342,1477983600"; d="scan'208,217";a="55851075" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga004.jf.intel.com with ESMTP; 06 Feb 2017 06:51:27 -0800 Received: from fmsmsx151.amr.corp.intel.com (10.18.125.4) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.248.2; Mon, 6 Feb 2017 06:51:27 -0800 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by FMSMSX151.amr.corp.intel.com (10.18.125.4) with Microsoft SMTP Server (TLS) id 14.3.248.2; Mon, 6 Feb 2017 06:51:26 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.88]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.132]) with mapi id 14.03.0248.002; Mon, 6 Feb 2017 22:51:24 +0800 From: "Yao, Jiewen" To: Ard Biesheuvel CC: "Kinney, Michael D" , "edk2-devel@lists.01.org" , "Tian, Feng" , "Zeng, Star" Thread-Topic: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protection. Thread-Index: AQHSd6/wrwK8jswf/k6AMNKUvS20dqFbltiAgACGePA= Date: Mon, 6 Feb 2017 14:51:23 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A8E9938@shsmsx102.ccr.corp.intel.com> References: <1485419955-26652-1-git-send-email-jiewen.yao@intel.com> <1485419955-26652-4-git-send-email-jiewen.yao@intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-Content-Filtered-By: Mailman/MimeDel 2.1.21 Subject: Re: [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protection. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Feb 2017 14:51:29 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Ard That is a good question. We (Intel) discussed this internally. We do not know if there is any need to make it configurable, so we start fr= om non-configurable, and see if there is any feedback from other one. Glad to hear your voice. We can define a policy like below: (I borrow some = definition from security pkg) [PcdsFixedAtBuild, PcdsPatchableInModule] ## Set Image protection policy. The policy is bitwise. # If a bit is set, the image will be protected by DxeCore if it is align= ed. # The code section becomes read-only, and the data section becomes non-= executable. # If a bit is clear, the image will not be protected.

# BIT0 - Image from unknown device.
# BIT1 - Image from firmware volume.
# BIT2 - Image from OptionRom.
# BIT3 - Image from removable media which includes CD-ROM, Flopp= y, USB and network.
# BIT4 - Image from fixed media device which includes hard disk.=
# @Prompt Set Image protection policy. # @ValidRange 0x80000002 | 0x00000000 - 0x0000001F gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000002|UINT32= |0x30001047 I will use 0x2 as default policy, to maximize the compatibility. And you ca= n set 0x1A or 0x1F for ARM. Is that OK? Thank you Yao Jiewen From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ard = Biesheuvel Sent: Monday, February 6, 2017 6:35 AM To: Yao, Jiewen Cc: Kinney, Michael D ; edk2-devel@lists.01.org= ; Tian, Feng ; Zeng, Star Subject: Re: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protec= tion. On 26 January 2017 at 08:39, Jiewen Yao > wrote: > If the UEFI image is page aligned, the image code section is set to read > only and the image data section is set to non-executable. > > 1) This policy is applied for all UEFI image including boot service drive= r, > runtime driver or application. > 2) This policy is applied only if the UEFI image meets the page alignment > requirement. > 3) This policy is applied only if the UEFI image is from firmware volume. > If the image is from OPROM, file system, or network, this policy is not > applied, even if the image meets the page alignment requirement. Is this policy configurable? I would like to start enforcing this on ARM even for file system images. > 4) This policy is not applied to the non-PE image region. > > The DxeCore calls CpuArchProtocol->SetMemoryAttributes() to protect > the image. If the CpuArch protocol is not installed yet, the DxeCore > enqueues the protection request. Once the CpuArch is installed, the > DxeCore dequeues the protection request and applies policy. > > Once the image is unloaded, the protection is removed automatically. > > Cc: Star Zeng > > Cc: Feng Tian > > Cc: Michael Kinney > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiewen Yao > > --- > MdeModulePkg/Core/Dxe/DxeMain.h | 53 ++ > MdeModulePkg/Core/Dxe/DxeMain.inf | 2 + > MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c | 1 + > MdeModulePkg/Core/Dxe/Image/Image.c | 5 + > MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 822 ++++++++++++++++++++ > MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c | 22 - > 6 files changed, 883 insertions(+), 22 deletions(-) > > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeM= ain.h > index ae35fbb..67b5a5a 100644 > --- a/MdeModulePkg/Core/Dxe/DxeMain.h > +++ b/MdeModulePkg/Core/Dxe/DxeMain.h > @@ -267,6 +267,26 @@ typedef struct { > #define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ > CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DA= TA_SIGNATURE) > > +#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I'= ,'P','R','C') > + > +typedef struct { > + UINT32 Signature; > + LIST_ENTRY Link; > + EFI_PHYSICAL_ADDRESS CodeSegmentBase; > + UINT64 CodeSegmentSize; > +} IMAGE_PROPERTIES_RECORD_CODE_SECTION; > + > +#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D') > + > +typedef struct { > + UINT32 Signature; > + LIST_ENTRY Link; > + EFI_PHYSICAL_ADDRESS ImageBase; > + UINT64 ImageSize; > + UINTN CodeSegmentCount; > + LIST_ENTRY CodeSegmentList; > +} IMAGE_PROPERTIES_RECORD; > + > // > // DXE Core Global Variables > // > @@ -2859,6 +2879,15 @@ CoreInitializeMemoryAttributesTable ( > ); > > /** > + Initialize Memory Protection support. > +**/ > +VOID > +EFIAPI > +CoreInitializeMemoryProtection ( > + VOID > + ); > + > +/** > Install MemoryAttributesTable on memory allocation. > > @param[in] MemoryType EFI memory type. > @@ -2888,4 +2917,28 @@ RemoveImageRecord ( > IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage > ); > > +/** > + Protect UEFI image. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > +**/ > +VOID > +ProtectUefiImage ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath > + ); > + > +/** > + Unprotect UEFI image. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > +**/ > +VOID > +UnprotectUefiImage ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath > + ); > + > #endif > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/Dx= eMain.inf > index 13a2381..e62bc42 100644 > --- a/MdeModulePkg/Core/Dxe/DxeMain.inf > +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf > @@ -42,6 +42,7 @@ > Misc/InstallConfigurationTable.c > Misc/PropertiesTable.c > Misc/MemoryAttributesTable.c > + Misc/MemoryProtection.c > Library/Library.c > Hand/DriverSupport.c > Hand/Notify.c > @@ -159,6 +160,7 @@ > gEfiHiiPackageListProtocolGuid ## SOMETIMES_PRODUCES > gEfiEbcProtocolGuid ## SOMETIMES_CONSUMES > gEfiSmmBase2ProtocolGuid ## SOMETIMES_CONSUMES > + gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES > > # Arch Protocols > gEfiBdsArchProtocolGuid ## CONSUMES > diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/= Dxe/DxeMain/DxeMain.c > index 21cd61a..7304f69 100644 > --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c > +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c > @@ -398,6 +398,7 @@ DxeMain ( > > CoreInitializePropertiesTable (); > CoreInitializeMemoryAttributesTable (); > + CoreInitializeMemoryProtection (); > > // > // Get persisted vector hand-off info from GUIDeed HOB again due to Ho= bStart may be updated, > diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/= Image/Image.c > index 4a8a16d..1c930ef 100644 > --- a/MdeModulePkg/Core/Dxe/Image/Image.c > +++ b/MdeModulePkg/Core/Dxe/Image/Image.c > @@ -203,6 +203,8 @@ CoreInitializeImageServices ( > ); > } > > + ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath); > + > return Status; > } > > @@ -862,6 +864,8 @@ CoreUnloadAndCloseImage ( > UnregisterMemoryProfileImage (Image); > } > > + UnprotectUefiImage (&Image->Info, Image->LoadedImageDevicePath); > + > if (Image->Ebc !=3D NULL) { > // > // If EBC protocol exists we must perform cleanups for this image. > @@ -1341,6 +1345,7 @@ CoreLoadImageCommon ( > goto Done; > } > } > + ProtectUefiImage (&Image->Info, Image->LoadedImageDevicePath); > > // > // Success. Return the image handle > diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg= /Core/Dxe/Misc/MemoryProtection.c > new file mode 100644 > index 0000000..fe412a0 > --- /dev/null > +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c > @@ -0,0 +1,822 @@ > +/** @file > + UEFI Memory Protection support. > + > + If the UEFI image is page aligned, the image code section is set to re= ad only > + and the image data section is set to non-executable. > + > + 1) This policy is applied for all UEFI image including boot service dr= iver, > + runtime driver or application. > + 2) This policy is applied only if the UEFI image meets the page alignm= ent > + requirement. > + 3) This policy is applied only if the UEFI image is from firmware volu= me. > + If the image is from OPROM, file system, or network, this policy is= not > + applied, even if the image meets the page alignment requirement. > + 4) This policy is not applied to the non-PE image region. > + > + The DxeCore calls CpuArchProtocol->SetMemoryAttributes() to protect > + the image. If the CpuArch protocol is not installed yet, the DxeCore > + enqueues the protection request. Once the CpuArch is installed, the > + DxeCore dequeues the protection request and applies policy. > + > + Once the image is unloaded, the protection is removed automatically. > + > +Copyright (c) 2016, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D License > +which accompanies this distribution. The full text of the license may b= e found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#include "DxeMain.h" > + > +#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMO= RY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP) > +#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMO= RY_RO) > + > +// > +// Image type definitions > +// > +#define IMAGE_UNKNOWN 0x00000001 > +#define IMAGE_FROM_FV 0x00000002 > +#define IMAGE_FROM_OPTION_ROM 0x00000004 > +#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000008 > +#define IMAGE_FROM_FIXED_MEDIA 0x00000010 > + > +// > +// Protection policy bit definition > +// > +#define DO_NOT_PROTECT 0x00000000 > +#define PROTECT_IF_ALIGNED_ELSE_ALLOW 0x00000001 > + > +UINT32 mDefaultProtectionPolicy[] =3D { > + DO_NOT_PROTECT, // IMAGE_UNKNOWN > + PROTECT_IF_ALIGNED_ELSE_ALLOW, // IMAGE_FROM_FV > + DO_NOT_PROTECT, // IMAGE_FROM_OPTION_ROM > + DO_NOT_PROTECT, // IMAGE_FROM_REMOVABLE_MEDIA > + DO_NOT_PROTECT, // IMAGE_FROM_FIXED_MEDIA > +}; > + > +/** > + Sort code section in image record, based upon CodeSegmentBase from low= to high. > + > + @param ImageRecord image record to be sorted > +**/ > +VOID > +SortImageRecordCodeSection ( > + IN IMAGE_PROPERTIES_RECORD *ImageRecord > + ); > + > +/** > + Check if code section in image record is valid. > + > + @param ImageRecord image record to be checked > + > + @retval TRUE image record is valid > + @retval FALSE image record is invalid > +**/ > +BOOLEAN > +IsImageRecordCodeSectionValid ( > + IN IMAGE_PROPERTIES_RECORD *ImageRecord > + ); > + > +/** > + Get the image type. > + > + @param[in] File This is a pointer to the device path of the f= ile that is > + being dispatched. > + > + @return UINT32 Image Type > +**/ > +UINT32 > +GetImageType ( > + IN CONST EFI_DEVICE_PATH_PROTOCOL *File > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE DeviceHandle; > + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; > + EFI_BLOCK_IO_PROTOCOL *BlockIo; > + > + if (File =3D=3D NULL) { > + return IMAGE_UNKNOWN; > + } > + > + // > + // First check to see if File is from a Firmware Volume > + // > + DeviceHandle =3D NULL; > + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) File; > + Status =3D gBS->LocateDevicePath ( > + &gEfiFirmwareVolume2ProtocolGuid, > + &TempDevicePath, > + &DeviceHandle > + ); > + if (!EFI_ERROR (Status)) { > + Status =3D gBS->OpenProtocol ( > + DeviceHandle, > + &gEfiFirmwareVolume2ProtocolGuid, > + NULL, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_TEST_PROTOCOL > + ); > + if (!EFI_ERROR (Status)) { > + return IMAGE_FROM_FV; > + } > + } > + > + // > + // Next check to see if File is from a Block I/O device > + // > + DeviceHandle =3D NULL; > + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) File; > + Status =3D gBS->LocateDevicePath ( > + &gEfiBlockIoProtocolGuid, > + &TempDevicePath, > + &DeviceHandle > + ); > + if (!EFI_ERROR (Status)) { > + BlockIo =3D NULL; > + Status =3D gBS->OpenProtocol ( > + DeviceHandle, > + &gEfiBlockIoProtocolGuid, > + (VOID **) &BlockIo, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (!EFI_ERROR (Status) && BlockIo !=3D NULL) { > + if (BlockIo->Media !=3D NULL) { > + if (BlockIo->Media->RemovableMedia) { > + // > + // Block I/O is present and specifies the media is removable > + // > + return IMAGE_FROM_REMOVABLE_MEDIA; > + } else { > + // > + // Block I/O is present and specifies the media is not removab= le > + // > + return IMAGE_FROM_FIXED_MEDIA; > + } > + } > + } > + } > + > + // > + // File is not in a Firmware Volume or on a Block I/O device, so check= to see if > + // the device path supports the Simple File System Protocol. > + // > + DeviceHandle =3D NULL; > + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) File; > + Status =3D gBS->LocateDevicePath ( > + &gEfiSimpleFileSystemProtocolGuid, > + &TempDevicePath, > + &DeviceHandle > + ); > + if (!EFI_ERROR (Status)) { > + // > + // Simple File System is present without Block I/O, so assume media = is fixed. > + // > + return IMAGE_FROM_FIXED_MEDIA; > + } > + > + // > + // File is not from an FV, Block I/O or Simple File System, so the onl= y options > + // left are a PCI Option ROM and a Load File Protocol such as a PXE Bo= ot from a NIC. > + // > + TempDevicePath =3D (EFI_DEVICE_PATH_PROTOCOL *) File; > + while (!IsDevicePathEndType (TempDevicePath)) { > + switch (DevicePathType (TempDevicePath)) { > + > + case MEDIA_DEVICE_PATH: > + if (DevicePathSubType (TempDevicePath) =3D=3D MEDIA_RELATIVE_OFFSE= T_RANGE_DP) { > + return IMAGE_FROM_OPTION_ROM; > + } > + break; > + > + case MESSAGING_DEVICE_PATH: > + if (DevicePathSubType(TempDevicePath) =3D=3D MSG_MAC_ADDR_DP) { > + return IMAGE_FROM_REMOVABLE_MEDIA; > + } > + break; > + > + default: > + break; > + } > + TempDevicePath =3D NextDevicePathNode (TempDevicePath); > + } > + return IMAGE_UNKNOWN; > +} > + > +/** > + Get UEFI image protection policy based upon image type. > + > + @param[in] ImageType The UEFI image type > + > + @return UEFI image protection policy > +**/ > +UINT32 > +GetProtectionPolicyFromImageType ( > + IN UINT32 ImageType > + ) > +{ > + UINTN Index; > + > + for (Index =3D 0; Index < ARRAY_SIZE(mDefaultProtectionPolicy); Index+= +) { > + if ((UINT32)(1 << Index) =3D=3D ImageType) { > + return mDefaultProtectionPolicy[Index]; > + } > + } > + return DO_NOT_PROTECT; > +} > + > +/** > + Get UEFI image protection policy based upon loaded image device path. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > + > + @return UEFI image protection policy > +**/ > +UINT32 > +GetUefiImageProtectionPolicy ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath > + ) > +{ > + BOOLEAN InSmm; > + UINT32 ImageType; > + UINT32 ProtectionPolicy; > + > + // > + // Check SMM > + // > + InSmm =3D FALSE; > + if (gSmmBase2 !=3D NULL) { > + gSmmBase2->InSmm (gSmmBase2, &InSmm); > + } > + if (InSmm) { > + return FALSE; > + } > + > + // > + // Check DevicePath > + // > + if (LoadedImage =3D=3D gDxeCoreLoadedImage) { > + ImageType =3D IMAGE_FROM_FV; > + } else { > + ImageType =3D GetImageType (LoadedImageDevicePath); > + } > + ProtectionPolicy =3D GetProtectionPolicyFromImageType (ImageType); > + return ProtectionPolicy; > +} > + > + > +/** > + Set UEFI image memory attributes. > + > + @param[in] BaseAddress Specified start address > + @param[in] Length Specified length > + @param[in] Attributes Specified attributes > +**/ > +VOID > +SetUefiImageMemoryAttributes ( > + IN UINT64 BaseAddress, > + IN UINT64 Length, > + IN UINT64 Attributes > + ) > +{ > + EFI_STATUS Status; > + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; > + UINT64 FinalAttributes; > + > + Status =3D CoreGetMemorySpaceDescriptor(BaseAddress, &Descriptor); > + ASSERT_EFI_ERROR(Status); > + > + FinalAttributes =3D (Descriptor.Attributes & CACHE_ATTRIBUTE_MASK) | (= Attributes & MEMORY_ATTRIBUTE_MASK); > + > + DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016l= x (0x%016lx)\n", BaseAddress, Length, FinalAttributes)); > + > + ASSERT(gCpu !=3D NULL); > + gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes)= ; > +} > + > +/** > + Set UEFI image protection attributes. > + > + @param[in] ImageRecord A UEFI image record > + @param[in] Protect TRUE: Protect the UEFI image. > + FALSE: Unprotect the UEFI image. > +**/ > +VOID > +SetUefiImageProtectionAttributes ( > + IN IMAGE_PROPERTIES_RECORD *ImageRecord, > + IN BOOLEAN Protect > + ) > +{ > + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; > + LIST_ENTRY *ImageRecordCodeSectionLink; > + LIST_ENTRY *ImageRecordCodeSectionEndLi= nk; > + LIST_ENTRY *ImageRecordCodeSectionList; > + UINT64 CurrentBase; > + UINT64 ImageEnd; > + UINT64 Attribute; > + > + ImageRecordCodeSectionList =3D &ImageRecord->CodeSegmentList; > + > + CurrentBase =3D ImageRecord->ImageBase; > + ImageEnd =3D ImageRecord->ImageBase + ImageRecord->ImageSize; > + > + ImageRecordCodeSectionLink =3D ImageRecordCodeSectionList->ForwardLink= ; > + ImageRecordCodeSectionEndLink =3D ImageRecordCodeSectionList; > + while (ImageRecordCodeSectionLink !=3D ImageRecordCodeSectionEndLink) = { > + ImageRecordCodeSection =3D CR ( > + ImageRecordCodeSectionLink, > + IMAGE_PROPERTIES_RECORD_CODE_SECTION, > + Link, > + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGN= ATURE > + ); > + ImageRecordCodeSectionLink =3D ImageRecordCodeSectionLink->ForwardLi= nk; > + > + ASSERT (CurrentBase <=3D ImageRecordCodeSection->CodeSegmentBase); > + if (CurrentBase < ImageRecordCodeSection->CodeSegmentBase) { > + // > + // DATA > + // > + if (Protect) { > + Attribute =3D EFI_MEMORY_XP; > + } else { > + Attribute =3D 0; > + } > + SetUefiImageMemoryAttributes ( > + CurrentBase, > + ImageRecordCodeSection->CodeSegmentBase - CurrentBase, > + Attribute > + ); > + } > + // > + // CODE > + // > + if (Protect) { > + Attribute =3D EFI_MEMORY_RO; > + } else { > + Attribute =3D 0; > + } > + SetUefiImageMemoryAttributes ( > + ImageRecordCodeSection->CodeSegmentBase, > + ImageRecordCodeSection->CodeSegmentSize, > + Attribute > + ); > + CurrentBase =3D ImageRecordCodeSection->CodeSegmentBase + ImageRecor= dCodeSection->CodeSegmentSize; > + } > + // > + // Last DATA > + // > + ASSERT (CurrentBase <=3D ImageEnd); > + if (CurrentBase < ImageEnd) { > + // > + // DATA > + // > + if (Protect) { > + Attribute =3D EFI_MEMORY_XP; > + } else { > + Attribute =3D 0; > + } > + SetUefiImageMemoryAttributes ( > + CurrentBase, > + ImageEnd - CurrentBase, > + Attribute > + ); > + } > + return ; > +} > + > +/** > + Return if the PE image section is aligned. > + > + @param[in] SectionAlignment PE/COFF section alignment > + @param[in] MemoryType PE/COFF image memory type > + > + @retval TRUE The PE image section is aligned. > + @retval FALSE The PE image section is not aligned. > +**/ > +BOOLEAN > +IsMemoryProtectionSectionAligned ( > + IN UINT32 SectionAlignment, > + IN EFI_MEMORY_TYPE MemoryType > + ) > +{ > + UINT32 PageAlignment; > + > + switch (MemoryType) { > + case EfiRuntimeServicesCode: > + case EfiACPIMemoryNVS: > + PageAlignment =3D EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; > + break; > + case EfiRuntimeServicesData: > + case EfiACPIReclaimMemory: > + ASSERT (FALSE); > + PageAlignment =3D EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; > + break; > + case EfiBootServicesCode: > + case EfiLoaderCode: > + case EfiReservedMemoryType: > + PageAlignment =3D EFI_PAGE_SIZE; > + break; > + default: > + ASSERT (FALSE); > + PageAlignment =3D EFI_PAGE_SIZE; > + break; > + } > + > + if ((SectionAlignment & (PageAlignment - 1)) !=3D 0) { > + return FALSE; > + } else { > + return TRUE; > + } > +} > + > +/** > + Free Image record. > + > + @param[in] ImageRecord A UEFI image record > +**/ > +VOID > +FreeImageRecord ( > + IN IMAGE_PROPERTIES_RECORD *ImageRecord > + ) > +{ > + LIST_ENTRY *CodeSegmentListHead; > + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; > + > + CodeSegmentListHead =3D &ImageRecord->CodeSegmentList; > + while (!IsListEmpty (CodeSegmentListHead)) { > + ImageRecordCodeSection =3D CR ( > + CodeSegmentListHead->ForwardLink, > + IMAGE_PROPERTIES_RECORD_CODE_SECTION, > + Link, > + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGN= ATURE > + ); > + RemoveEntryList (&ImageRecordCodeSection->Link); > + FreePool (ImageRecordCodeSection); > + } > + > + if (ImageRecord->Link.ForwardLink !=3D NULL) { > + RemoveEntryList (&ImageRecord->Link); > + } > + FreePool (ImageRecord); > +} > + > +/** > + Protect or unprotect UEFI image common function. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > + @param[in] Protect TRUE: Protect the UEFI image. > + FALSE: Unprotect the UEFI image. > +**/ > +VOID > +ProtectUefiImageCommon ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath, > + IN BOOLEAN Protect > + ) > +{ > + VOID *ImageAddress; > + EFI_IMAGE_DOS_HEADER *DosHdr; > + UINT32 PeCoffHeaderOffset; > + UINT32 SectionAlignment; > + EFI_IMAGE_SECTION_HEADER *Section; > + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; > + UINT8 *Name; > + UINTN Index; > + IMAGE_PROPERTIES_RECORD *ImageRecord; > + CHAR8 *PdbPointer; > + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; > + UINT16 Magic; > + BOOLEAN IsAligned; > + UINT32 ProtectionPolicy; > + > + DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage)); > + DEBUG ((DEBUG_INFO, " - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS= )(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize)); > + > + if (gCpu =3D=3D NULL) { > + return ; > + } > + > + ProtectionPolicy =3D GetUefiImageProtectionPolicy (LoadedImage, Loaded= ImageDevicePath); > + switch (ProtectionPolicy) { > + case DO_NOT_PROTECT: > + return ; > + case PROTECT_IF_ALIGNED_ELSE_ALLOW: > + break; > + default: > + ASSERT(FALSE); > + return ; > + } > + > + ImageRecord =3D AllocateZeroPool (sizeof(*ImageRecord)); > + if (ImageRecord =3D=3D NULL) { > + return ; > + } > + ImageRecord->Signature =3D IMAGE_PROPERTIES_RECORD_SIGNATURE; > + > + // > + // Step 1: record whole region > + // > + ImageRecord->ImageBase =3D (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->I= mageBase; > + ImageRecord->ImageSize =3D LoadedImage->ImageSize; > + > + ImageAddress =3D LoadedImage->ImageBase; > + > + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress= ); > + if (PdbPointer !=3D NULL) { > + DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer)); > + } > + > + // > + // Check PE/COFF image > + // > + DosHdr =3D (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; > + PeCoffHeaderOffset =3D 0; > + if (DosHdr->e_magic =3D=3D EFI_IMAGE_DOS_SIGNATURE) { > + PeCoffHeaderOffset =3D DosHdr->e_lfanew; > + } > + > + Hdr.Pe32 =3D (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress= + PeCoffHeaderOffset); > + if (Hdr.Pe32->Signature !=3D EFI_IMAGE_NT_SIGNATURE) { > + DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.P= e32->Signature)); > + // It might be image in SMM. > + goto Finish; > + } > + > + // > + // Get SectionAlignment > + // > + if (Hdr.Pe32->FileHeader.Machine =3D=3D IMAGE_FILE_MACHINE_IA64 && Hdr= .Pe32->OptionalHeader.Magic =3D=3D EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { > + // > + // NOTE: Some versions of Linux ELILO for Itanium have an incorrect = magic value > + // in the PE/COFF Header. If the MachineType is Itanium(IA64) = and the > + // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_= HDR32_MAGIC > + // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR6= 4_MAGIC > + // > + Magic =3D EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; > + } else { > + // > + // Get the magic value from the PE/COFF Optional Header > + // > + Magic =3D Hdr.Pe32->OptionalHeader.Magic; > + } > + if (Magic =3D=3D EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { > + SectionAlignment =3D Hdr.Pe32->OptionalHeader.SectionAlignment; > + } else { > + SectionAlignment =3D Hdr.Pe32Plus->OptionalHeader.SectionAlignment; > + } > + > + IsAligned =3D IsMemoryProtectionSectionAligned (SectionAlignment, Load= edImage->ImageCodeType); > + if (!IsAligned) { > + DEBUG ((DEBUG_VERBOSE, "!!!!!!!! ProtectUefiImageCommon - Section A= lignment(0x%x) is incorrect !!!!!!!!\n", > + SectionAlignment)); > + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddre= ss); > + if (PdbPointer !=3D NULL) { > + DEBUG ((DEBUG_VERBOSE, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPoin= ter)); > + } > + goto Finish; > + } > + > + Section =3D (EFI_IMAGE_SECTION_HEADER *) ( > + (UINT8 *) (UINTN) ImageAddress + > + PeCoffHeaderOffset + > + sizeof(UINT32) + > + sizeof(EFI_IMAGE_FILE_HEADER) + > + Hdr.Pe32->FileHeader.SizeOfOptionalHeader > + ); > + ImageRecord->CodeSegmentCount =3D 0; > + InitializeListHead (&ImageRecord->CodeSegmentList); > + for (Index =3D 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index= ++) { > + Name =3D Section[Index].Name; > + DEBUG (( > + DEBUG_VERBOSE, > + " Section - '%c%c%c%c%c%c%c%c'\n", > + Name[0], > + Name[1], > + Name[2], > + Name[3], > + Name[4], > + Name[5], > + Name[6], > + Name[7] > + )); > + > + if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) !=3D 0= ) { > + DEBUG ((DEBUG_VERBOSE, " VirtualSize - 0x%08x\n", Sectio= n[Index].Misc.VirtualSize)); > + DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", Sectio= n[Index].VirtualAddress)); > + DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", Sectio= n[Index].SizeOfRawData)); > + DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", Sectio= n[Index].PointerToRawData)); > + DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", Sectio= n[Index].PointerToRelocations)); > + DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Sectio= n[Index].PointerToLinenumbers)); > + DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", Sectio= n[Index].NumberOfRelocations)); > + DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Sectio= n[Index].NumberOfLinenumbers)); > + DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", Sectio= n[Index].Characteristics)); > + > + // > + // Step 2: record code section > + // > + ImageRecordCodeSection =3D AllocatePool (sizeof(*ImageRecordCodeSe= ction)); > + if (ImageRecordCodeSection =3D=3D NULL) { > + return ; > + } > + ImageRecordCodeSection->Signature =3D IMAGE_PROPERTIES_RECORD_CODE= _SECTION_SIGNATURE; > + > + ImageRecordCodeSection->CodeSegmentBase =3D (UINTN)ImageAddress + = Section[Index].VirtualAddress; > + ImageRecordCodeSection->CodeSegmentSize =3D ALIGN_VALUE(Section[In= dex].SizeOfRawData, SectionAlignment); > + > + DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRe= cordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize))= ; > + > + InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSec= tion->Link); > + ImageRecord->CodeSegmentCount++; > + } > + } > + > + if (ImageRecord->CodeSegmentCount =3D=3D 0) { > + DEBUG ((DEBUG_ERROR, "!!!!!!!! ProtectUefiImageCommon - CodeSegment= Count is 0 !!!!!!!!\n")); > + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddre= ss); > + if (PdbPointer !=3D NULL) { > + DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointe= r)); > + } > + goto Finish; > + } > + > + // > + // Final > + // > + SortImageRecordCodeSection (ImageRecord); > + // > + // Check overlap all section in ImageBase/Size > + // > + if (!IsImageRecordCodeSectionValid (ImageRecord)) { > + DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n")); > + goto Finish; > + } > + > + // > + // CPU ARCH present. Update memory attribute directly. > + // > + SetUefiImageProtectionAttributes (ImageRecord, Protect); > + > + // > + // Clean up > + // > + FreeImageRecord (ImageRecord); > + > +Finish: > + return ; > +} > + > +/** > + Protect UEFI image. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > +**/ > +VOID > +ProtectUefiImage ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath > + ) > +{ > + ProtectUefiImageCommon (LoadedImage, LoadedImageDevicePath, TRUE); > +} > + > +/** > + Unprotect UEFI image. > + > + @param[in] LoadedImage The loaded image protocol > + @param[in] LoadedImageDevicePath The loaded image device path prot= ocol > +**/ > +VOID > +UnprotectUefiImage ( > + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, > + IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath > + ) > +{ > + ProtectUefiImageCommon (LoadedImage, LoadedImageDevicePath, FALSE); > +} > + > +/** > + A notification for CPU_ARCH protocol. > + > + @param[in] Event Event whose notification function is= being invoked. > + @param[in] Context Pointer to the notification function= 's context, > + which is implementation-dependent. > + > +**/ > +VOID > +EFIAPI > +MemoryProtectionCpuArchProtocolNotify ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_STATUS Status; > + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; > + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; > + UINTN NoHandles; > + EFI_HANDLE *HandleBuffer; > + UINTN Index; > + > + DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n")); > + Status =3D CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID *= *)&gCpu); > + if (EFI_ERROR (Status)) { > + return; > + } > + > + Status =3D gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiLoadedImageProtocolGuid, > + NULL, > + &NoHandles, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status) && (NoHandles =3D=3D 0)) { > + return ; > + } > + > + for (Index =3D 0; Index < NoHandles; Index++) { > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiLoadedImageProtocolGuid, > + (VOID **)&LoadedImage > + ); > + if (EFI_ERROR(Status)) { > + continue; > + } > + Status =3D gBS->HandleProtocol ( > + HandleBuffer[Index], > + &gEfiLoadedImageDevicePathProtocolGuid, > + (VOID **)&LoadedImageDevicePath > + ); > + if (EFI_ERROR(Status)) { > + LoadedImageDevicePath =3D NULL; > + } > + > + ProtectUefiImage (LoadedImage, LoadedImageDevicePath); > + } > + > + CoreCloseEvent (Event); > + return; > +} > + > +/** > + Initialize Memory Protection support. > +**/ > +VOID > +EFIAPI > +CoreInitializeMemoryProtection ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_EVENT Event; > + VOID *Registration; > + > + Status =3D CoreCreateEvent ( > + EVT_NOTIFY_SIGNAL, > + TPL_CALLBACK, > + MemoryProtectionCpuArchProtocolNotify, > + NULL, > + &Event > + ); > + ASSERT_EFI_ERROR(Status); > + > + // > + // Register for protocol notifactions on this event > + // > + Status =3D CoreRegisterProtocolNotify ( > + &gEfiCpuArchProtocolGuid, > + Event, > + &Registration > + ); > + ASSERT_EFI_ERROR(Status); > + return ; > +} > diff --git a/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c b/MdeModulePkg/= Core/Dxe/Misc/PropertiesTable.c > index 7ecad89..a18c02d 100644 > --- a/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c > +++ b/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c > @@ -36,26 +36,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EIT= HER EXPRESS OR IMPLIED. > #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ > ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) > > -#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I'= ,'P','R','C') > - > -typedef struct { > - UINT32 Signature; > - LIST_ENTRY Link; > - EFI_PHYSICAL_ADDRESS CodeSegmentBase; > - UINT64 CodeSegmentSize; > -} IMAGE_PROPERTIES_RECORD_CODE_SECTION; > - > -#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D') > - > -typedef struct { > - UINT32 Signature; > - LIST_ENTRY Link; > - EFI_PHYSICAL_ADDRESS ImageBase; > - UINT64 ImageSize; > - UINTN CodeSegmentCount; > - LIST_ENTRY CodeSegmentList; > -} IMAGE_PROPERTIES_RECORD; > - > #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P= ','D') > > typedef struct { > @@ -864,7 +844,6 @@ SwapImageRecordCodeSection ( > > @param ImageRecord image record to be sorted > **/ > -STATIC > VOID > SortImageRecordCodeSection ( > IN IMAGE_PROPERTIES_RECORD *ImageRecord > @@ -915,7 +894,6 @@ SortImageRecordCodeSection ( > @retval TRUE image record is valid > @retval FALSE image record is invalid > **/ > -STATIC > BOOLEAN > IsImageRecordCodeSectionValid ( > IN IMAGE_PROPERTIES_RECORD *ImageRecord > -- > 2.7.4.windows.1 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel