From nobody Thu Dec 26 12:05:08 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1505971245886216.95004030899213; Wed, 20 Sep 2017 22:20:45 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6F55E21E9461D; Wed, 20 Sep 2017 22:17:38 -0700 (PDT) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 40BAF20945B95 for ; Wed, 20 Sep 2017 22:17:37 -0700 (PDT) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Sep 2017 22:20:43 -0700 Received: from jwang36-mobl2.ccr.corp.intel.com ([10.239.192.31]) by fmsmga006.fm.intel.com with ESMTP; 20 Sep 2017 22:20:42 -0700 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.42,423,1500966000"; d="scan'208";a="154308606" From: Jian J Wang To: edk2-devel@lists.01.org Date: Thu, 21 Sep 2017 13:20:28 +0800 Message-Id: <20170921052032.13652-3-jian.j.wang@intel.com> X-Mailer: git-send-email 2.14.1.windows.1 In-Reply-To: <20170921052032.13652-1-jian.j.wang@intel.com> References: <20170921052032.13652-1-jian.j.wang@intel.com> Subject: [edk2] [PATCH v2 2/6] MdeModulePkg/DxeIpl: Implement NULL pointer detection X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eric Dong , Jordan Justen , Jiewen Yao , Ayellet Wolman , Michael Kinney , Laszlo Ersek , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" NULL pointer detection is done by making use of paging mechanism of CPU. During page table setup, if enabled, the first 4-K page (0-4095) will be marked as NOT PRESENT. Any code which unintentionally access memory between 0-4095 will trigger a Page Fault exception which warns users that there's potential illegal code in BIOS. This also means that legacy code which has to access memory between 0-4095 should be cautious to temporarily disable this feature before the access and re-enable it afterwards; or disalbe this feature at all. Cc: Star Zeng Cc: Eric Dong Cc: Laszlo Ersek Cc: Jiewen Yao Cc: Michael Kinney Cc: Jordan Justen Cc: Ayellet Wolman Suggested-by: Ayellet Wolman Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang --- MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 25 +++++++++ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 + MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 65 ++++++++++++++++++++= ++++ MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 11 +++- MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c | 2 + MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 31 ++++++++--- 6 files changed, 126 insertions(+), 9 deletions(-) diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeI= plPeim/DxeIpl.h index 72d2532f50..1654bcd2dc 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -240,4 +240,29 @@ Decompress ( OUT UINTN *OutputSize ); =20 +/** + Clear legacy memory located at the first 4K-page. + + This function traverses the whole HOB list to check if memory from 0 to= 4095 + exists and has not been allocated, and then clear it if so. + + @param HoStart The start of HobList passed to DxeCore. + +**/ +VOID +ClearLegacyMemory ( + IN VOID *HobStart + ); + +/** + Return configure status of NULL pointer detection feature + + @return TRUE NULL pointer detection feature is enabled + @return FALSE NULL pointer detection feature is disabled +**/ +BOOLEAN +IsNullDetectionEnabled ( + VOID + ); + #endif diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/Dx= eIplPeim/DxeIpl.inf index c54afe4aa6..9d0e76a293 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -115,6 +115,7 @@ [Pcd.IA32,Pcd.X64] gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ##= SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ##= CONSUMES =20 [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64] gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIM= ES_CONSUMES diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/Dxe= IplPeim/DxeLoad.c index 50b5440d15..0a71b1f3de 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -825,3 +825,68 @@ UpdateStackHob ( Hob.Raw =3D GET_NEXT_HOB (Hob); } } + +/** + Clear legacy memory located at the first 4K-page, if available. + + This function traverses the whole HOB list to check if memory from 0 to= 4095 + exists and has not been allocated, and then clear it if so. + + @param HoStart The start of HobList passed to DxeCore. + +**/ +VOID +ClearLegacyMemory ( + IN VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS RscHob; + EFI_PEI_HOB_POINTERS MemHob; + BOOLEAN DoClear; + + RscHob.Raw =3D HobStart; + MemHob.Raw =3D HobStart; + DoClear =3D FALSE; + + // + // Check if page 0 exists and free + // + while ((RscHob.Raw =3D GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + RscHob.Raw)) !=3D NULL) { + if (RscHob.ResourceDescriptor->ResourceType =3D=3D EFI_RESOURCE_SYSTEM= _MEMORY && + RscHob.ResourceDescriptor->PhysicalStart =3D=3D 0) { + DoClear =3D TRUE; + // + // Make sure memory at 0-4095 has not been allocated. + // + while ((MemHob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, + MemHob.Raw)) !=3D NULL) { + if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + < EFI_PAGE_SIZE) { + DoClear =3D FALSE; + break; + } + MemHob.Raw =3D GET_NEXT_HOB (MemHob); + } + break; + } + RscHob.Raw =3D GET_NEXT_HOB (RscHob); + } + + if (DoClear) { + DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n")); + SetMem (NULL, EFI_PAGE_SIZE, 0); + } + + return; +} + +BOOLEAN +IsNullDetectionEnabled ( + VOID + ) +{ + return (((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) !=3D 0) ? + TRUE : FALSE); +} + diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg= /Core/DxeIplPeim/Ia32/DxeLoadFunc.c index 1957326caf..503cf88382 100644 --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -123,7 +123,9 @@ Create4GPageTablesIa32Pae ( PageDirectoryPointerEntry->Bits.Present =3D 1; =20 for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < = 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += =3D SIZE_2MB) { - if ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress += SIZE_2MB) > StackBase)) { + if ((IsNullDetectionEnabled () && PhysicalAddress =3D=3D 0) + || ((PhysicalAddress < StackBase + StackSize) + && ((PhysicalAddress + SIZE_2MB) > StackBase))) { // // Need to split this 2M page that covers stack range. // @@ -240,6 +242,8 @@ HandOffToDxeCore ( EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi; BOOLEAN BuildPageTablesIa32Pae; =20 + ClearLegacyMemory (HobList.Raw); + Status =3D PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PA= GES (STACK_SIZE), &BaseOfStack); ASSERT_EFI_ERROR (Status); =20 @@ -379,7 +383,10 @@ HandOffToDxeCore ( TopOfStack =3D (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStac= k, CPU_STACK_ALIGNMENT); =20 PageTables =3D 0; - BuildPageTablesIa32Pae =3D (BOOLEAN) (PcdGetBool (PcdSetNxForStack) &&= IsIa32PaeSupport () && IsExecuteDisableBitAvailable ()); + BuildPageTablesIa32Pae =3D (BOOLEAN) (IsIa32PaeSupport () + && IsExecuteDisableBitAvailable () + && (PcdGetBool (PcdSetNxForStack) + || IsNullDetectionEnabled ())); if (BuildPageTablesIa32Pae) { PageTables =3D Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE); EnableExecuteDisableBit (); diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/= Core/DxeIplPeim/X64/DxeLoadFunc.c index 6488880eab..d93a9c5a2d 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c @@ -42,6 +42,8 @@ HandOffToDxeCore ( EFI_VECTOR_HANDOFF_INFO *VectorInfo; EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi; =20 + ClearLegacyMemory (HobList.Raw); + // // Get Vector Hand-off Info PPI and build Guided HOB // diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePk= g/Core/DxeIplPeim/X64/VirtualMemory.c index 48150be4e1..80c1821eca 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -90,8 +90,16 @@ Split2MPageTo4K ( // PageTableEntry->Uint64 =3D (UINT64) PhysicalAddress4K | AddressEncMask; PageTableEntry->Bits.ReadWrite =3D 1; - PageTableEntry->Bits.Present =3D 1; - if ((PhysicalAddress4K >=3D StackBase) && (PhysicalAddress4K < StackBa= se + StackSize)) { + + if (IsNullDetectionEnabled () && PhysicalAddress4K =3D=3D 0) { + PageTableEntry->Bits.Present =3D 0; + } else { + PageTableEntry->Bits.Present =3D 1; + } + + if (PcdGetBool (PcdSetNxForStack) + && (PhysicalAddress4K >=3D StackBase) + && (PhysicalAddress4K < StackBase + StackSize)) { // // Set Nx bit for stack. // @@ -137,9 +145,12 @@ Split1GPageTo2M ( =20 PhysicalAddress2M =3D PhysicalAddress; for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < 51= 2; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += =3D SIZE_2MB) { - if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M= + SIZE_2MB) > StackBase)) { + if ((IsNullDetectionEnabled () && PhysicalAddress2M =3D=3D 0) + || (PcdGetBool (PcdSetNxForStack) + && (PhysicalAddress2M < StackBase + StackSize) + && ((PhysicalAddress2M + SIZE_2MB) > StackBase))) { // - // Need to split this 2M page that covers stack range. + // Need to split this 2M page that covers NULL or stack range. // Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, S= tackBase, StackSize); } else { @@ -279,7 +290,10 @@ CreateIdentityMappingPageTables ( PageDirectory1GEntry =3D (VOID *) PageDirectoryPointerEntry; =20 for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries = < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += =3D SIZE_1GB) { - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + St= ackSize) && ((PageAddress + SIZE_1GB) > StackBase)) { + if ((IsNullDetectionEnabled () && PageAddress =3D=3D 0) + || (PcdGetBool (PcdSetNxForStack) + && (PageAddress < StackBase + StackSize) + && ((PageAddress + SIZE_1GB) > StackBase))) { Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, S= tackBase, StackSize); } else { // @@ -308,9 +322,12 @@ CreateIdentityMappingPageTables ( PageDirectoryPointerEntry->Bits.Present =3D 1; =20 for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntrie= s < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += =3D SIZE_2MB) { - if (PcdGetBool (PcdSetNxForStack) && (PageAddress < StackBase + = StackSize) && ((PageAddress + SIZE_2MB) > StackBase)) { + if ((IsNullDetectionEnabled () && PageAddress =3D=3D 0) + || (PcdGetBool (PcdSetNxForStack) + && (PageAddress < StackBase + StackSize) + && ((PageAddress + SIZE_2MB) > StackBase))) { // - // Need to split this 2M page that covers stack range. + // Need to split this 2M page that covers NULL or stack range. // Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, S= tackBase, StackSize); } else { --=20 2.14.1.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel