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 9ADC682069 for ; Sun, 5 Feb 2017 17:07:23 -0800 (PST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga101.fm.intel.com with ESMTP; 05 Feb 2017 17:07:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,339,1477983600"; d="scan'208,217";a="55678540" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga004.jf.intel.com with ESMTP; 05 Feb 2017 17:07:22 -0800 Received: from fmsmsx111.amr.corp.intel.com (10.18.116.5) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.248.2; Sun, 5 Feb 2017 17:07:22 -0800 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx111.amr.corp.intel.com (10.18.116.5) with Microsoft SMTP Server (TLS) id 14.3.248.2; Sun, 5 Feb 2017 17:07:20 -0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.177]) by SHSMSX104.ccr.corp.intel.com ([10.239.4.70]) with mapi id 14.03.0248.002; Mon, 6 Feb 2017 09:07:18 +0800 From: "Tian, Feng" To: "Gao, Liming" , "Yao, Jiewen" , "edk2-devel@lists.01.org" CC: "Kinney, Michael D" , "Zeng, Star" , "Tian, Feng" Thread-Topic: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protection. Thread-Index: AQHSd6/lyy9tL1NKpkGfx2eTTj6ar6FWfLIAgAEMugCAADHMAIADf38w Date: Mon, 6 Feb 2017 01:07:18 +0000 Message-ID: <7F1BAD85ADEA444D97065A60D2E97EE5699AEE29@SHSMSX101.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> <4A89E2EF3DFEDB4C8BFDE51014F606A14D6D6428@shsmsx102.ccr.corp.intel.com> <74D8A39837DF1E4DA445A8C0B3885C503A8E8FFE@shsmsx102.ccr.corp.intel.com> <4A89E2EF3DFEDB4C8BFDE51014F606A14D6D674C@shsmsx102.ccr.corp.intel.com> In-Reply-To: <4A89E2EF3DFEDB4C8BFDE51014F606A14D6D674C@shsmsx102.ccr.corp.intel.com> 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 01:07:23 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Jiewen, So where will you add such limitation statements? In this commit log or oth= er places? Thanks Feng From: Gao, Liming Sent: Saturday, February 4, 2017 11:40 AM To: Yao, Jiewen ; edk2-devel@lists.01.org Cc: Kinney, Michael D ; Tian, Feng ; Zeng, Star Subject: RE: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protec= tion. Jiewen: I agree to keep the same policy to SMM and Runtime driver. Thanks Liming From: Yao, Jiewen Sent: Saturday, February 04, 2017 8:42 AM To: Gao, Liming >; edk2-d= evel@lists.01.org Cc: Kinney, Michael D >; Tian, Feng >; Z= eng, Star > Subject: RE: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protec= tion. It is pre-requisite that code section and data section should not be not me= rged. That is same criteria for SMM and Runtime driver. The problem is that I am not able to see the difference. I can only get LIN= K warning below: LINK : warning LNK4254: section '.data' (C0000040) merged into '.text' (600= 00020) with different attributes But final attribute in PE code section is same. Thank you Yao Jiewen From: Gao, Liming Sent: Friday, February 3, 2017 4:40 PM To: Yao, Jiewen >; edk2-d= evel@lists.01.org Cc: Kinney, Michael D >; Tian, Feng >; Z= eng, Star > Subject: RE: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image protec= tion. Jiewen: I have one comment. If VS linker option /MERGE:.data=3D.text is set, the = generated PE image will have one .text section. If this section is set to R= O, its data will be RO. Does this patch specially handle this case? Thanks Liming >-----Original Message----- >From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of >Jiewen Yao >Sent: Thursday, January 26, 2017 4:39 PM >To: edk2-devel@lists.01.org >Cc: Kinney, Michael D >; Tian, Feng >>; Zeng, Star > >Subject: [edk2] [PATCH 3/3] MdeModulePkg/DxeCore: Add UEFI image >protection. > >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 driver= , >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. >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/DxeMain.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_DATA_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 >protocol >+**/ >+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 >protocol >+**/ >+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/DxeMain.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 >HobStart 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 rea= d only >+ and the image data section is set to non-executable. >+ >+ 1) This policy is applied for all UEFI image including boot service dri= ver, >+ runtime driver or application. >+ 2) This policy is applied only if the UEFI image meets the page alignme= nt >+ requirement. >+ 3) This policy is applied only if the UEFI image is from firmware volum= e. >+ 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 BSD >License >+which accompanies this distribution. The full text of the license may be >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 IMPLIED. >+ >+**/ >+ >+#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_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | >EFI_MEMORY_WP) >+#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | >EFI_MEMORY_XP | EFI_MEMORY_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 fi= le 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 removabl= e >+ // >+ 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 i= s >fixed. >+ // >+ return IMAGE_FROM_FIXED_MEDIA; >+ } >+ >+ // >+ // File is not from an FV, Block I/O or Simple File System, so the only= options >+ // left are a PCI Option ROM and a Load File Protocol such as a PXE Boo= t >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_OFFSET_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 >protocol >+ >+ @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%016lx (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 *ImageRecordCodeSectionEndLin= k; >+ 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_SIGNA= TURE >+ ); >+ ImageRecordCodeSectionLink =3D ImageRecordCodeSectionLink- >>ForwardLink; >+ >+ 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 + >ImageRecordCodeSection->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_SIGNA= TURE >+ ); >+ 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 >protocol >+ @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, >LoadedImageDevicePath); >+ 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->ImageBase; >+ 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.Pe32->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 m= agic >value >+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) a= nd the >+ // Magic value in the OptionalHeader is >EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC >+ // then override the magic value to >EFI_IMAGE_NT_OPTIONAL_HDR64_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, >LoadedImage->ImageCodeType); >+ if (!IsAligned) { >+ DEBUG ((DEBUG_VERBOSE, "!!!!!!!! ProtectUefiImageCommon - Section >Alignment(0x%x) is incorrect !!!!!!!!\n", >+ SectionAlignment)); >+ PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) >ImageAddress); >+ if (PdbPointer !=3D NULL) { >+ DEBUG ((DEBUG_VERBOSE, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPoint= er)); >+ } >+ 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", >Section[Index].Misc.VirtualSize)); >+ DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", >Section[Index].VirtualAddress)); >+ DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", >Section[Index].SizeOfRawData)); >+ DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", >Section[Index].PointerToRawData)); >+ DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", >Section[Index].PointerToRelocations)); >+ DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", >Section[Index].PointerToLinenumbers)); >+ DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", >Section[Index].NumberOfRelocations)); >+ DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", >Section[Index].NumberOfLinenumbers)); >+ DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", >Section[Index].Characteristics)); >+ >+ // >+ // Step 2: record code section >+ // >+ ImageRecordCodeSection =3D AllocatePool >(sizeof(*ImageRecordCodeSection)); >+ 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[Index].SizeOfRawData, SectionAlignment); >+ >+ DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", >ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection- >>CodeSegmentSize)); >+ >+ InsertTailList (&ImageRecord->CodeSegmentList, >&ImageRecordCodeSection->Link); >+ ImageRecord->CodeSegmentCount++; >+ } >+ } >+ >+ if (ImageRecord->CodeSegmentCount =3D=3D 0) { >+ DEBUG ((DEBUG_ERROR, "!!!!!!!! ProtectUefiImageCommon - >CodeSegmentCount is 0 !!!!!!!!\n")); >+ PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) >ImageAddress); >+ if (PdbPointer !=3D NULL) { >+ DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer= )); >+ } >+ 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 >protocol >+**/ >+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 >protocol >+**/ >+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, EITHER 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