From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f171.google.com (mail-oi1-f171.google.com [209.85.167.171]) by mx.groups.io with SMTP id smtpd.web10.1857.1689119589501731897 for ; Tue, 11 Jul 2023 16:53:09 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@taylorbeebe.com header.s=google header.b=Aur+Mpzd; spf=pass (domain: taylorbeebe.com, ip: 209.85.167.171, mailfrom: t@taylorbeebe.com) Received: by mail-oi1-f171.google.com with SMTP id 5614622812f47-3a412653335so1422240b6e.1 for ; Tue, 11 Jul 2023 16:53:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=taylorbeebe.com; s=google; t=1689119588; x=1691711588; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YLFhvh7JSDgYFU2+k/RioAU0VBUWy6NpVaf93QuHFBo=; b=Aur+Mpzd/yHiTF6T8IAwbNmWdX6MZ25EIJIi1unM9URL7Ad+q9eVbOp75pruasvsoD Gu3Niu+L5IVX0Jp9z3erYQp4250EnDyE4KizSCK8/c4xrAkP3FgxNRrVNLo0W1CdHnNH BKLFeNgRlTPnta/cdnKj0NhkjUh9c87NGZRRsRxAFJS2RuItpXU+fV4rglHNFrzMQzwE blX9kr1zLi/C/L26tV4nUCK+onWNDFB2XXDdJOWQ69rK/zLatjaKmbusM32PyxUprmdQ RSG0Z/HsOl0B9rYENxqFu+yGfx3RlDX/d1tyDda0uNCF5ObJYnGx5qCuVk3oeekOV0Lt rB2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689119588; x=1691711588; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YLFhvh7JSDgYFU2+k/RioAU0VBUWy6NpVaf93QuHFBo=; b=XGXLjk1xo9rhAYohYfYMHYWvb8BhMy6lnEC64yZRuUKg4L3xLlgegtoCplClVGUo0/ gMGPqRU/MTBPeMNyUWUu0JcDMr/gZeoc4a+wlFmu0McQQq4a+9pd3AMpWeg9o+cEUmPm 1RFSOHaz1J+94TMfS3l01jFk/E7vOZdbFg7/CX9eUt93te961KQK6yU+7CJha04Mh6XW Ln8MZfNwG+ixJ1pmmiU52xYD7PisFvFQDB7e6mdj660yrQscdVkCEVh0BytQnC4r5ZVQ P1809UDYNPqud3qNTuEZkcQEd8d+URVDVTEl89Gt6YaXn/vR9oayjwDfHDWi1hnbHW2O VM5w== X-Gm-Message-State: ABy/qLaYVkHSI2lEoLvDmz4NrHyFlTfdQ1E/mwHjA1tvpCFwlzjM2Gay FmJuDR7E60mkG1KG+4zlCP2jf4Nf7L+do7vfpN+wwQ== X-Google-Smtp-Source: APBJJlGaQdm3ScdJ0AHRnPDezlUoOVhrr4PcIgzNDO/JZPZJiUZqOenE+ujI+8pCs9dvXYE5s56YIw== X-Received: by 2002:a54:4d95:0:b0:3a4:24ac:30dd with SMTP id y21-20020a544d95000000b003a424ac30ddmr510062oix.23.1689119588495; Tue, 11 Jul 2023 16:53:08 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([50.46.230.135]) by smtp.gmail.com with ESMTPSA id a13-20020a62e20d000000b00660d80087a8sm2232677pfi.187.2023.07.11.16.53.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Jul 2023 16:53:07 -0700 (PDT) From: "Taylor Beebe" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Dandan Bi Subject: [PATCH 08/14] MdeModulePkg: Update to use memory protection HOB Date: Tue, 11 Jul 2023 16:52:45 -0700 Message-ID: X-Mailer: git-send-email 2.41.0.windows.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Taylor Beebe Replace references to the memory protection PCDs with references to the memory protection HOB. The memory protection HOB will be ingested during handoff to check the memory proteciton settings when creating the page tables. This patch also adjusts the logic for the memory protection callback to apply protections one at a time (first NX, then stack protections, then NULL protection etc.) with a debug print before each application to help narrow down memory integrity related issues if they occur when applying protections. Signed-off-by: Taylor Beebe Cc: Jian J Wang Cc: Liming Gao Cc: Dandan Bi --- MdeModulePkg/Core/Dxe/DxeMain.h | 1 + MdeModulePkg/Core/Dxe/DxeMain.inf | 9 +- MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c | 8 +- MdeModulePkg/Core/Dxe/Mem/HeapGuard.c | 88 ++--- MdeModulePkg/Core/Dxe/Mem/HeapGuard.h | 24 +- MdeModulePkg/Core/Dxe/Mem/Page.c | 4 +- MdeModulePkg/Core/Dxe/Mem/Pool.c | 6 +- MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 338 ++++++++++-------- MdeModulePkg/Core/DxeIplPeim/DxeHandoff.c | 4 +- MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 15 + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 13 +- MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 26 ++ .../Core/DxeIplPeim/Ia32/DxeLoadFunc.c | 57 +-- .../Core/DxeIplPeim/X64/DxeLoadFunc.c | 20 +- .../Core/DxeIplPeim/X64/VirtualMemory.c | 87 ++--- .../Core/DxeIplPeim/X64/VirtualMemory.h | 23 +- MdeModulePkg/Core/PiSmmCore/HeapGuard.c | 60 +--- MdeModulePkg/Core/PiSmmCore/HeapGuard.h | 20 +- MdeModulePkg/Core/PiSmmCore/Page.c | 6 +- MdeModulePkg/Core/PiSmmCore/PiSmmCore.h | 1 + MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf | 4 +- MdeModulePkg/Core/PiSmmCore/Pool.c | 9 +- 22 files changed, 367 insertions(+), 456 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 43daa037be..9da87a33a9 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -84,6 +84,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include // // attributes for reserved memory before it is promoted to system memory diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 35d5bf0dee..3cbd1ae923 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -94,6 +94,7 @@ DebugAgentLib CpuExceptionHandlerLib PcdLib + DxeMemoryProtectionHobLib [Guids] gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event @@ -123,6 +124,7 @@ gEfiMemoryAttributesTableGuid ## SOMETIMES_PRODUCES ## SystemTable gEfiEndOfDxeEventGroupGuid ## SOMETIMES_CONSUMES ## Event gEfiHobMemoryAllocStackGuid ## SOMETIMES_CONSUMES ## SystemTable + gDxeMemoryProtectionSettingsGuid ## CONSUMES ## HOB [Ppis] gEfiVectorHandoffInfoPpiGuid ## UNDEFINED # HOB @@ -179,13 +181,6 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileMemoryType ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth ## CONSUMES # [Hob] diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index 0e0f9769b9..5bcef4f399 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -257,9 +257,13 @@ DxeMain ( ASSERT_EFI_ERROR (Status); // - // Setup Stack Guard + // Get the memory protection HOB entry and setup stack guard // - if (PcdGetBool (PcdCpuStackGuard)) { + GuidHob = GetFirstGuidHob (&gDxeMemoryProtectionSettingsGuid); + if ((GuidHob != NULL) && + DXE_MPS_IS_STRUCT_VALID (GET_GUID_HOB_DATA (GuidHob)) && + ((DXE_MEMORY_PROTECTION_SETTINGS *)GET_GUID_HOB_DATA (GuidHob))->CpuStackGuardEnabled) + { Status = InitializeSeparateExceptionStacks (NULL, NULL); ASSERT_EFI_ERROR (Status); } diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c index 9377f620c5..0b9008ad51 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c @@ -553,7 +553,7 @@ UnsetGuardPage ( // memory. // Attributes = 0; - if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & (1 << EfiConventionalMemory)) != 0) { + if (gDxeMps.ExecutionProtection.EnabledForType[EfiConventionalMemory]) { Attributes |= EFI_MEMORY_XP; } @@ -577,7 +577,7 @@ UnsetGuardPage ( @param[in] MemoryType Memory type to check. @param[in] AllocateType Allocation type to check. - @param[in] PageOrPool Indicate a page allocation or pool allocation. + @param[in] HeapGuardType Indicates the heap guard type. @return TRUE The given type of memory should be guarded. @@ -587,41 +587,32 @@ BOOLEAN IsMemoryTypeToGuard ( IN EFI_MEMORY_TYPE MemoryType, IN EFI_ALLOCATE_TYPE AllocateType, - IN UINT8 PageOrPool + IN HEAP_GUARD_TYPE HeapGuardType ) { - UINT64 TestBit; - UINT64 ConfigBit; - if (AllocateType == AllocateAddress) { return FALSE; } - if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) == 0) { - return FALSE; - } - - if (PageOrPool == GUARD_HEAP_TYPE_POOL) { - ConfigBit = PcdGet64 (PcdHeapGuardPoolType); - } else if (PageOrPool == GUARD_HEAP_TYPE_PAGE) { - ConfigBit = PcdGet64 (PcdHeapGuardPageType); - } else { - ConfigBit = (UINT64)-1; - } + UINT32 TestMemoryType; if ((UINT32)MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) { - TestBit = BIT63; + TestMemoryType = OS_RESERVED_MPS_MEMORY_TYPE; } else if ((UINT32)MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) { - TestBit = BIT62; - } else if (MemoryType < EfiMaxMemoryType) { - TestBit = LShiftU64 (1, MemoryType); - } else if (MemoryType == EfiMaxMemoryType) { - TestBit = (UINT64)-1; + TestMemoryType = OEM_RESERVED_MPS_MEMORY_TYPE; + } else if (MemoryType >= EfiMaxMemoryType) { + return TRUE; } else { - TestBit = 0; + TestMemoryType = MemoryType; + } + + if ((HeapGuardType == HeapGuardTypePool) && gDxeMps.HeapGuard.PoolGuardEnabled) { + return gDxeMps.PoolGuard.EnabledForType[TestMemoryType]; + } else if ((HeapGuardType == HeapGuardTypePage) && gDxeMps.HeapGuard.PageGuardEnabled) { + return gDxeMps.PageGuard.EnabledForType[TestMemoryType]; } - return ((ConfigBit & TestBit) != 0); + return FALSE; } /** @@ -641,7 +632,7 @@ IsPoolTypeToGuard ( return IsMemoryTypeToGuard ( MemoryType, AllocateAnyPages, - GUARD_HEAP_TYPE_POOL + HeapGuardTypePool ); } @@ -660,22 +651,7 @@ IsPageTypeToGuard ( IN EFI_ALLOCATE_TYPE AllocateType ) { - return IsMemoryTypeToGuard (MemoryType, AllocateType, GUARD_HEAP_TYPE_PAGE); -} - -/** - Check to see if the heap guard is enabled for page and/or pool allocation. - - @param[in] GuardType Specify the sub-type(s) of Heap Guard. - - @return TRUE/FALSE. -**/ -BOOLEAN -IsHeapGuardEnabled ( - UINT8 GuardType - ) -{ - return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages, GuardType); + return IsMemoryTypeToGuard (MemoryType, AllocateType, HeapGuardTypePage); } /** @@ -835,7 +811,7 @@ AdjustMemoryS ( // indicated to put the pool near the Tail Guard, we need extra bytes to // make sure alignment of the returned pool address. // - if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0) { + if (gDxeMps.HeapGuard.GuardAlignedToTail) { SizeRequested = ALIGN_VALUE (SizeRequested, 8); } @@ -1019,7 +995,7 @@ AdjustPoolHeadA ( IN UINTN Size ) { - if ((Memory == 0) || ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0)) { + if ((Memory == 0) || (!gDxeMps.HeapGuard.GuardAlignedToTail)) { // // Pool head is put near the head Guard // @@ -1045,7 +1021,7 @@ AdjustPoolHeadF ( IN EFI_PHYSICAL_ADDRESS Memory ) { - if ((Memory == 0) || ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0)) { + if ((Memory == 0) || (!gDxeMps.HeapGuard.GuardAlignedToTail)) { // // Pool head is put near the head Guard // @@ -1344,7 +1320,7 @@ GuardFreedPagesChecked ( IN UINTN Pages ) { - if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED)) { + if (gDxeMps.HeapGuard.FreedMemoryGuardEnabled) { GuardFreedPages (BaseAddress, Pages); } } @@ -1469,7 +1445,7 @@ MergeGuardPages ( UINT64 Bitmap; INTN Pages; - if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) || + if ((!gDxeMps.HeapGuard.FreedMemoryGuardEnabled) || (MemoryMapEntry->Type >= EfiMemoryMappedIO)) { return; @@ -1525,7 +1501,7 @@ PromoteGuardedFreePages ( UINT64 Bitmap; EFI_PHYSICAL_ADDRESS Start; - if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED)) { + if (!gDxeMps.HeapGuard.FreedMemoryGuardEnabled) { return FALSE; } @@ -1594,18 +1570,21 @@ HeapGuardCpuArchProtocolNotify ( { ASSERT (gCpu != NULL); - if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL) && - IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED)) + if ((gDxeMps.HeapGuard.PageGuardEnabled || + gDxeMps.HeapGuard.PoolGuardEnabled) && + gDxeMps.HeapGuard.FreedMemoryGuardEnabled) { DEBUG ((DEBUG_ERROR, "Heap guard and freed memory guard cannot be enabled at the same time.\n")); CpuDeadLoop (); } - if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL)) { + if (gDxeMps.HeapGuard.PageGuardEnabled || + gDxeMps.HeapGuard.PoolGuardEnabled) + { SetAllGuardPages (); } - if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED)) { + if (gDxeMps.HeapGuard.FreedMemoryGuardEnabled) { GuardAllFreedPages (); } } @@ -1660,7 +1639,10 @@ DumpGuardedMemoryBitmap ( CHAR8 *Ruler1; CHAR8 *Ruler2; - if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_ALL)) { + if (!gDxeMps.HeapGuard.FreedMemoryGuardEnabled && + !gDxeMps.HeapGuard.PageGuardEnabled && + !gDxeMps.HeapGuard.PoolGuardEnabled) + { return; } diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h index 9a32b4dd51..b90afae615 100644 --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h @@ -150,13 +150,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent } // -// Memory type to guard (matching the related PCD definition) +// Heap guard types // -#define GUARD_HEAP_TYPE_PAGE BIT0 -#define GUARD_HEAP_TYPE_POOL BIT1 -#define GUARD_HEAP_TYPE_FREED BIT4 -#define GUARD_HEAP_TYPE_ALL \ - (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_FREED) +typedef enum { + HeapGuardTypePage, + HeapGuardTypePool, + HeapGuardTypeMax +} HEAP_GUARD_TYPE; // // Debug message level @@ -386,18 +386,6 @@ AdjustPoolHeadF ( IN EFI_PHYSICAL_ADDRESS Memory ); -/** - Check to see if the heap guard is enabled for page and/or pool allocation. - - @param[in] GuardType Specify the sub-type(s) of Heap Guard. - - @return TRUE/FALSE. -**/ -BOOLEAN -IsHeapGuardEnabled ( - UINT8 GuardType - ); - /** Notify function used to set all Guard pages after CPU Arch Protocol installed. **/ diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index 41af50b3d5..848562ff21 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -181,7 +181,7 @@ CoreAddRange ( // used for other purposes. // if ((Type == EfiConventionalMemory) && (Start == 0) && (End >= EFI_PAGE_SIZE - 1)) { - if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) == 0) { + if (!gDxeMps.NullPointerDetection.Enabled) { SetMem ((VOID *)(UINTN)Start, EFI_PAGE_SIZE, 0); } } @@ -918,7 +918,7 @@ CoreConvertPagesEx ( // Add our new range in. Don't do this for freed pages if freed-memory // guard is enabled. // - if (!IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) || + if (!gDxeMps.HeapGuard.FreedMemoryGuardEnabled || !ChangingType || (MemType != EfiConventionalMemory)) { diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index b20cbfdedb..65f90f7922 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -385,8 +385,8 @@ CoreAllocatePoolI ( // HasPoolTail = !(NeedGuard && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); - PageAsPool = (IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) && !mOnGuarding); + gDxeMps.HeapGuard.GuardAlignedToTail); + PageAsPool = (gDxeMps.HeapGuard.FreedMemoryGuardEnabled && !mOnGuarding); // // Adjusting the Size to be of proper alignment so that @@ -717,7 +717,7 @@ CoreFreePoolI ( IsGuarded = IsPoolTypeToGuard (Head->Type) && IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); HasPoolTail = !(IsGuarded && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); + gDxeMps.HeapGuard.GuardAlignedToTail); PageAsPool = (Head->Signature == POOLPAGE_HEAD_SIGNATURE); if (HasPoolTail) { diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 7cc829b174..75aefa7514 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -9,7 +9,7 @@ 2) This policy is applied only if the UEFI image meets the page alignment requirement. 3) This policy is applied only if the Source UEFI image matches the - PcdImageProtectionPolicy definition. + Image Protection Policy definition. 4) This policy is not applied to the non-PE image region. The DxeCore calls CpuArchProtocol->SetMemoryAttributes() to protect @@ -60,7 +60,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) -UINT32 mImageProtectionPolicy; +STATIC BOOLEAN mIsExecutionProtectionActive = FALSE; + +STATIC BOOLEAN mIsPageOrPoolGuardActive = FALSE; extern LIST_ENTRY mGcdMemorySpaceMap; @@ -149,11 +151,13 @@ GetProtectionPolicyFromImageType ( IN UINT32 ImageType ) { - if ((ImageType & mImageProtectionPolicy) == 0) { - return DO_NOT_PROTECT; - } else { + if (((ImageType == IMAGE_UNKNOWN) && gDxeMps.ImageProtection.ProtectImageFromUnknown) || + ((ImageType == IMAGE_FROM_FV) && gDxeMps.ImageProtection.ProtectImageFromFv)) + { return PROTECT_IF_ALIGNED_ELSE_ALLOW; } + + return DO_NOT_PROTECT; } /** @@ -611,27 +615,25 @@ UnprotectUefiImage ( IMAGE_PROPERTIES_RECORD *ImageRecord; LIST_ENTRY *ImageRecordLink; - if (PcdGet32 (PcdImageProtectionPolicy) != 0) { - for (ImageRecordLink = mProtectedImageRecordList.ForwardLink; - ImageRecordLink != &mProtectedImageRecordList; - ImageRecordLink = ImageRecordLink->ForwardLink) - { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - - if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) { - SetUefiImageMemoryAttributes ( - ImageRecord->ImageBase, - ImageRecord->ImageSize, - 0 - ); - FreeImageRecord (ImageRecord); - return; - } + for (ImageRecordLink = mProtectedImageRecordList.ForwardLink; + ImageRecordLink != &mProtectedImageRecordList; + ImageRecordLink = ImageRecordLink->ForwardLink) + { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + + if (ImageRecord->ImageBase == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) { + SetUefiImageMemoryAttributes ( + ImageRecord->ImageBase, + ImageRecord->ImageSize, + 0 + ); + FreeImageRecord (ImageRecord); + return; } } } @@ -648,21 +650,24 @@ GetPermissionAttributeForMemoryType ( IN EFI_MEMORY_TYPE MemoryType ) { - UINT64 TestBit; + UINT32 TestMemoryType; if ((UINT32)MemoryType >= MEMORY_TYPE_OS_RESERVED_MIN) { - TestBit = BIT63; + TestMemoryType = OS_RESERVED_MPS_MEMORY_TYPE; } else if ((UINT32)MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) { - TestBit = BIT62; + TestMemoryType = OEM_RESERVED_MPS_MEMORY_TYPE; + } else if (MemoryType >= EfiMaxMemoryType) { + // If the memory type is not defined in the UEFI spec, return EFI_MEMORY_XP + return EFI_MEMORY_XP; } else { - TestBit = LShiftU64 (1, MemoryType); + TestMemoryType = MemoryType; } - if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & TestBit) != 0) { + if (gDxeMps.ExecutionProtection.EnabledForType[TestMemoryType]) { return EFI_MEMORY_XP; - } else { - return 0; } + + return 0; } /** @@ -771,8 +776,8 @@ MergeMemoryMapForProtectionPolicy ( } /** - Remove exec permissions from all regions whose type is identified by - PcdDxeNxMemoryProtectionPolicy. + Remove execution permissions from all regions whose memory type is identified by + the DXE Execution Protection Policy. **/ STATIC VOID @@ -780,20 +785,17 @@ InitializeDxeNxMemoryProtectionPolicy ( VOID ) { - UINTN MemoryMapSize; - UINTN MapKey; - UINTN DescriptorSize; - UINT32 DescriptorVersion; - EFI_MEMORY_DESCRIPTOR *MemoryMap; - EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; - EFI_STATUS Status; - UINT64 Attributes; - LIST_ENTRY *Link; - EFI_GCD_MAP_ENTRY *Entry; - EFI_PEI_HOB_POINTERS Hob; - EFI_HOB_MEMORY_ALLOCATION *MemoryHob; - EFI_PHYSICAL_ADDRESS StackBase; + UINTN MemoryMapSize; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + EFI_STATUS Status; + UINT64 Attributes; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; // // Get the EFI memory map. @@ -826,41 +828,6 @@ InitializeDxeNxMemoryProtectionPolicy ( ASSERT_EFI_ERROR (Status); - StackBase = 0; - if (PcdGetBool (PcdCpuStackGuard)) { - // - // Get the base of stack from Hob. - // - Hob.Raw = GetHobList (); - while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { - MemoryHob = Hob.MemoryAllocation; - if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) { - DEBUG (( - DEBUG_INFO, - "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n", - __func__, - MemoryHob->AllocDescriptor.MemoryBaseAddress, - MemoryHob->AllocDescriptor.MemoryLength - )); - - StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress; - // - // Ensure the base of the stack is page-size aligned. - // - ASSERT ((StackBase & EFI_PAGE_MASK) == 0); - break; - } - - Hob.Raw = GET_NEXT_HOB (Hob); - } - - // - // Ensure the base of stack can be found from Hob when stack guard is - // enabled. - // - ASSERT (StackBase != 0); - } - DEBUG (( DEBUG_INFO, "%a: applying strict permissions to active memory regions\n", @@ -879,38 +846,6 @@ InitializeDxeNxMemoryProtectionPolicy ( LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT), Attributes ); - - // - // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is - // enabled. - // - if ((MemoryMapEntry->PhysicalStart == 0) && - (PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0)) - { - ASSERT (MemoryMapEntry->NumberOfPages > 0); - SetUefiImageMemoryAttributes ( - 0, - EFI_PAGES_TO_SIZE (1), - EFI_MEMORY_RP | Attributes - ); - } - - // - // Add EFI_MEMORY_RP attribute for the first page of the stack if stack - // guard is enabled. - // - if ((StackBase != 0) && - ((StackBase >= MemoryMapEntry->PhysicalStart) && - (StackBase < MemoryMapEntry->PhysicalStart + - LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT))) && - PcdGetBool (PcdCpuStackGuard)) - { - SetUefiImageMemoryAttributes ( - StackBase, - EFI_PAGES_TO_SIZE (1), - EFI_MEMORY_RP | Attributes - ); - } } MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); @@ -968,18 +903,68 @@ InitializeDxeNxMemoryProtectionPolicy ( } /** - A notification for CPU_ARCH protocol. + Initialize stack guard and stack execution protection. +**/ +STATIC +VOID +InitializeDxeStackMemoryProtectionPolicy ( + VOID + ) +{ + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackLength; - @param[in] Event Event whose notification function is being invoked. - @param[in] Context Pointer to the notification function's context, - which is implementation-dependent. + StackBase = 0; + StackLength = 0; + + // Get the base of stack from the HOB. + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) { + MemoryHob = Hob.MemoryAllocation; + if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) { + StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress; + StackLength = MemoryHob->AllocDescriptor.MemoryLength; + + ASSERT ((StackBase & EFI_PAGE_MASK) == 0); + ASSERT ((StackLength & EFI_PAGE_MASK) == 0); + break; + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + ASSERT (StackBase != 0); + ASSERT (StackLength != 0); + if ((StackBase != 0) && (StackLength != 0)) { + // Set EFI_MEMORY_XP if stack execution protection is enabled. + if (gDxeMps.StackExecutionProtectionEnabled) { + SetUefiImageMemoryAttributes ( + StackBase, + StackLength, + EFI_MEMORY_XP + ); + } + // Set EFI_MEMORY_RP if stack guard is enabled. + if (gDxeMps.CpuStackGuardEnabled) { + SetUefiImageMemoryAttributes ( + StackBase, + EFI_PAGE_SIZE, + gDxeMps.StackExecutionProtectionEnabled ? (EFI_MEMORY_XP | EFI_MEMORY_RP) : EFI_MEMORY_RP + ); + } + } +} + +/** + Initialize the DXE image protection policy. **/ +STATIC VOID -EFIAPI -MemoryProtectionCpuArchProtocolNotify ( - IN EFI_EVENT Event, - IN VOID *Context +InitializeDxeImageMemoryProtectionPolicy ( + VOID ) { EFI_STATUS Status; @@ -989,28 +974,6 @@ MemoryProtectionCpuArchProtocolNotify ( EFI_HANDLE *HandleBuffer; UINTN Index; - DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n")); - Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); - if (EFI_ERROR (Status)) { - goto Done; - } - - // - // Apply the memory protection policy on non-BScode/RTcode regions. - // - if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) { - InitializeDxeNxMemoryProtectionPolicy (); - } - - // - // Call notify function meant for Heap Guard. - // - HeapGuardCpuArchProtocolNotify (); - - if (mImageProtectionPolicy == 0) { - goto Done; - } - Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiLoadedImageProtocolGuid, @@ -1019,7 +982,7 @@ MemoryProtectionCpuArchProtocolNotify ( &HandleBuffer ); if (EFI_ERROR (Status) && (NoHandles == 0)) { - goto Done; + return; } for (Index = 0; Index < NoHandles; Index++) { @@ -1045,6 +1008,65 @@ MemoryProtectionCpuArchProtocolNotify ( } FreePool (HandleBuffer); +} + +/** + 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; + + Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (DXE_MPS_IS_EXECUTION_PROTECTION_ENABLED (&gDxeMps)) { + DEBUG ((DEBUG_INFO, "Applying DXE Execution Protection Policy\n")); + mIsExecutionProtectionActive = TRUE; + InitializeDxeNxMemoryProtectionPolicy (); + } + + if (gDxeMps.NullPointerDetection.Enabled) { + DEBUG ((DEBUG_INFO, "Applying NULL Detection\n")); + SetUefiImageMemoryAttributes ( + (UINTN)NULL, + EFI_PAGE_SIZE, + gDxeMps.ExecutionProtection.EnabledForType[EfiBootServicesData] ? + (EFI_MEMORY_XP | EFI_MEMORY_RP) : EFI_MEMORY_RP + ); + } + + if (gDxeMps.CpuStackGuardEnabled || gDxeMps.StackExecutionProtectionEnabled) { + DEBUG ((DEBUG_INFO, "Applying DXE Stack Protection Policy\n")); + InitializeDxeStackMemoryProtectionPolicy (); + } + + if (gDxeMps.HeapGuard.PageGuardEnabled || + gDxeMps.HeapGuard.PoolGuardEnabled || + gDxeMps.HeapGuard.FreedMemoryGuardEnabled) + { + DEBUG ((DEBUG_INFO, "Applying DXE Heap Guard Protection Policy\n")); + mIsPageOrPoolGuardActive = gDxeMps.HeapGuard.PageGuardEnabled || + gDxeMps.HeapGuard.PoolGuardEnabled; + HeapGuardCpuArchProtocolNotify (); + } + + if (DXE_MPS_IS_IMAGE_PROTECTION_ENABLED (&gDxeMps)) { + DEBUG ((DEBUG_INFO, "Applying DXE Image Protection Policy\n")); + InitializeDxeImageMemoryProtectionPolicy (); + } Done: CoreCloseEvent (Event); @@ -1070,7 +1092,7 @@ MemoryProtectionExitBootServicesCallback ( // delay setting protections on RT code pages until after SetVirtualAddressMap(). // OS may set protection on RT based upon EFI_MEMORY_ATTRIBUTES_TABLE later. // - if (mImageProtectionPolicy != 0) { + if (DXE_MPS_IS_IMAGE_PROTECTION_ENABLED (&gDxeMps)) { for (Link = gRuntime->ImageHead.ForwardLink; Link != &gRuntime->ImageHead; Link = Link->ForwardLink) { RuntimeImage = BASE_CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link); SetUefiImageMemoryAttributes ((UINT64)(UINTN)RuntimeImage->ImageBase, ALIGN_VALUE (RuntimeImage->ImageSize, EFI_PAGE_SIZE), 0); @@ -1144,19 +1166,17 @@ CoreInitializeMemoryProtection ( EFI_EVENT EndOfDxeEvent; VOID *Registration; - mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy); - InitializeListHead (&mProtectedImageRecordList); // - // Sanity check the PcdDxeNxMemoryProtectionPolicy setting: + // Sanity check the DXE NX protection policy setting: // - code regions should have no EFI_MEMORY_XP attribute // - EfiConventionalMemory and EfiBootServicesData should use the // same attribute // - ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0); - ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0); - ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0); + ASSERT (!gDxeMps.ExecutionProtection.EnabledForType[EfiLoaderCode]); + ASSERT (!gDxeMps.ExecutionProtection.EnabledForType[EfiBootServicesCode]); + ASSERT (!gDxeMps.ExecutionProtection.EnabledForType[EfiRuntimeServicesCode]); ASSERT ( GetPermissionAttributeForMemoryType (EfiBootServicesData) == GetPermissionAttributeForMemoryType (EfiConventionalMemory) @@ -1184,8 +1204,8 @@ CoreInitializeMemoryProtection ( // // Register a callback to disable NULL pointer detection at EndOfDxe // - if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) - == (BIT0|BIT7)) + if (gDxeMps.NullPointerDetection.Enabled && + gDxeMps.NullPointerDetection.DisableEndOfDxe) { Status = CoreCreateEventEx ( EVT_NOTIFY_SIGNAL, @@ -1250,7 +1270,7 @@ ApplyMemoryProtectionPolicy ( UINT64 NewAttributes; // - // The policy configured in PcdDxeNxMemoryProtectionPolicy + // The policy configured in DXE Execution Protection Policy // does not apply to allocations performed in SMM mode. // if (IsInSmm ()) { @@ -1269,7 +1289,7 @@ ApplyMemoryProtectionPolicy ( // // Check if a DXE memory protection policy has been configured // - if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) == 0) { + if (!mIsExecutionProtectionActive) { return EFI_SUCCESS; } @@ -1277,7 +1297,7 @@ ApplyMemoryProtectionPolicy ( // Don't overwrite Guard pages, which should be the first and/or last page, // if any. // - if (IsHeapGuardEnabled (GUARD_HEAP_TYPE_PAGE|GUARD_HEAP_TYPE_POOL)) { + if (mIsPageOrPoolGuardActive) { if (IsGuardPage (Memory)) { Memory += EFI_PAGE_SIZE; Length -= EFI_PAGE_SIZE; diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeHandoff.c b/MdeModulePkg/Core/DxeIplPeim/DxeHandoff.c index 60400da352..676e2c1355 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeHandoff.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeHandoff.c @@ -33,13 +33,15 @@ HandOffToDxeCore ( EFI_STATUS Status; EDKII_MEMORY_ATTRIBUTE_PPI *MemoryPpi; + PopulateDxeMemoryProtectionSettings (&mDxeMps); + // // Allocate 128KB for the Stack // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); ASSERT (BaseOfStack != NULL); - if (PcdGetBool (PcdSetNxForStack)) { + if (mDxeMps.StackExecutionProtectionEnabled) { Status = PeiServicesLocatePpi ( &gEdkiiMemoryAttributePpiGuid, 0, diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h index 2f015befce..8e87a66908 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -46,11 +47,25 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define STACK_SIZE 0x20000 #define BSP_STORE_SIZE 0x4000 +extern DXE_MEMORY_PROTECTION_SETTINGS mDxeMps; + // // This PPI is installed to indicate the end of the PEI usage of memory // extern CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi; +/** + Populates mDxeMps global with the data present in the memory + protection HOB entry if it exists. + + @param[in] DxeMps Pointer to the DXE memory protection settings. +**/ +VOID +EFIAPI +PopulateDxeMemoryProtectionSettings ( + IN DXE_MEMORY_PROTECTION_SETTINGS *DxeMps + ); + /** This function installs the PPIs that require permanent memory. diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf index f1990eac77..ffc5cce31d 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -88,11 +88,12 @@ ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" ## SOMETIMES_PRODUCES ## HOB gEfiMemoryTypeInformationGuid + gDxeMemoryProtectionSettingsGuid ## CONSUMES [FeaturePcd.IA32] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES -[FeaturePcd.X64] +[FeaturePcd.IA32, FeaturePcd.X64] gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES [FeaturePcd] @@ -101,20 +102,10 @@ [Pcd.IA32,Pcd.X64] gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES -[Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64] - gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES - [Depex] gEfiPeiLoadFilePpiGuid AND gEfiPeiMasterBootModePpiGuid diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c index 2c19f1a507..ac3456ecd6 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -50,6 +50,8 @@ CONST EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList = { InstallIplPermanentMemoryPpis }; +DXE_MEMORY_PROTECTION_SETTINGS mDxeMps; + /** Entry point of DXE IPL PEIM. @@ -836,3 +838,27 @@ UpdateStackHob ( Hob.Raw = GET_NEXT_HOB (Hob); } } + +/** + Populates mDxeMps global with the data present in the memory + protection HOB entry if it exists. + + @param[in] DxeMps Pointer to the DXE memory protection settings. +**/ +VOID +EFIAPI +PopulateDxeMemoryProtectionSettings ( + IN DXE_MEMORY_PROTECTION_SETTINGS *DxeMps + ) +{ + VOID *Ptr; + + Ptr = GetFirstGuidHob (&gDxeMemoryProtectionSettingsGuid); + + // Cache the Memory Protection Settings HOB entry + if ((Ptr != NULL) && DXE_MPS_IS_STRUCT_VALID (GET_GUID_HOB_DATA (Ptr))) { + CopyMem (DxeMps, GET_GUID_HOB_DATA (Ptr), sizeof (DXE_MEMORY_PROTECTION_SETTINGS)); + } else { + ZeroMem (DxeMps, sizeof (DXE_MEMORY_PROTECTION_SETTINGS)); + } +} diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c index 4bc7b749b0..5395202b87 100644 --- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c @@ -135,9 +135,8 @@ Create4GPageTablesIa32Pae ( PageDirectoryPointerEntry->Bits.Present = 1; for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) { - if ( (IsNullDetectionEnabled () && (PhysicalAddress == 0)) - || ( (PhysicalAddress < StackBase + StackSize) - && ((PhysicalAddress + SIZE_2MB) > StackBase))) + if ((((mDxeMps.NullPointerDetection.Enabled) && (PhysicalAddress == (UINTN)NULL))) || + ((PhysicalAddress < StackBase + StackSize) && ((PhysicalAddress + SIZE_2MB) > StackBase))) { // // Need to split this 2M page that covers stack range. @@ -199,41 +198,6 @@ IsIa32PaeSupport ( return Ia32PaeSupport; } -/** - The function will check if page table should be setup or not. - - @retval TRUE Page table should be created. - @retval FALSE Page table should not be created. - -**/ -BOOLEAN -ToBuildPageTable ( - VOID - ) -{ - if (!IsIa32PaeSupport ()) { - return FALSE; - } - - if (IsNullDetectionEnabled ()) { - return TRUE; - } - - if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) { - return TRUE; - } - - if (PcdGetBool (PcdCpuStackGuard)) { - return TRUE; - } - - if (IsEnableNonExecNeeded ()) { - return TRUE; - } - - return FALSE; -} - /** Transfers control to DxeCore. @@ -265,12 +229,13 @@ HandOffToDxeCore ( EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi; BOOLEAN BuildPageTablesIa32Pae; - // - // Clear page 0 and mark it as allocated if NULL pointer detection is enabled. - // - if (IsNullDetectionEnabled ()) { - ClearFirst4KPage (HobList.Raw); - BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); + PopulateDxeMemoryProtectionSettings (&mDxeMps); + + if (mDxeMps.NullPointerDetection.Enabled) { + ASSERT (CanAllocateNullPage (HobList.Raw)); + // Clear NULL page and mark it as allocated for NULL detectiond. + SetMem (NULL, EFI_PAGE_SIZE, (UINTN)NULL); + BuildMemoryAllocationHob ((UINTN)NULL, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); } Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); @@ -420,12 +385,14 @@ HandOffToDxeCore ( TopOfStack = (EFI_PHYSICAL_ADDRESS)(UINTN)ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); PageTables = 0; - BuildPageTablesIa32Pae = ToBuildPageTable (); + BuildPageTablesIa32Pae = PcdGetBool (PcdDxeIplBuildPageTables); if (BuildPageTablesIa32Pae) { PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE); if (IsEnableNonExecNeeded ()) { EnableExecuteDisableBit (); } + } else { + ASSERT (!DXE_MPS_IS_MEMORY_PROTECTION_ACTIVE (&mDxeMps)); } // diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c index fa2050cf02..8565bc8171 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c @@ -36,12 +36,13 @@ HandOffToDxeCore ( VOID *GhcbBase; UINTN GhcbSize; - // - // Clear page 0 and mark it as allocated if NULL pointer detection is enabled. - // - if (IsNullDetectionEnabled ()) { - ClearFirst4KPage (HobList.Raw); - BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); + PopulateDxeMemoryProtectionSettings (&mDxeMps); + + if (mDxeMps.NullPointerDetection.Enabled) { + ASSERT (CanAllocateNullPage (HobList.Raw)); + // Clear NULL page and mark it as allocated for NULL detection + SetMem (NULL, EFI_PAGE_SIZE, (UINTN)NULL); + BuildMemoryAllocationHob ((UINTN)NULL, EFI_PAGES_TO_SIZE (1), EfiBootServicesData); } // @@ -99,13 +100,6 @@ HandOffToDxeCore ( (EFI_PHYSICAL_ADDRESS)(UINTN)GhcbBase, GhcbSize ); - } else { - // - // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE - // for the DxeIpl and the DxeCore are both X64. - // - ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE); - ASSERT (PcdGetBool (PcdCpuStackGuard) == FALSE); } // diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c index 980c2002d4..6de8ddb4f8 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -32,29 +32,34 @@ SPDX-License-Identifier: BSD-2-Clause-Patent PAGE_TABLE_POOL *mPageTablePool = NULL; /** - 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. + Returns TRUE if the NULL page has not been allocated. @param HobStart The start of HobList passed to DxeCore. + @retval TRUE NULL page is unallocated + @retval FALSE NULL page cannot be allocated + **/ -VOID -ClearFirst4KPage ( +BOOLEAN +CanAllocateNullPage ( IN VOID *HobStart ) { EFI_PEI_HOB_POINTERS RscHob; EFI_PEI_HOB_POINTERS MemHob; - BOOLEAN DoClear; + BOOLEAN CanAllocate; + + if (HobStart == NULL) { + ASSERT (HobStart != NULL); + return FALSE; + } - RscHob.Raw = HobStart; - MemHob.Raw = HobStart; - DoClear = FALSE; + RscHob.Raw = HobStart; + MemHob.Raw = HobStart; + CanAllocate = FALSE; // - // Check if page 0 exists and free + // Check if page 0 exists and is free // while ((RscHob.Raw = GetNextHob ( EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, @@ -62,9 +67,9 @@ ClearFirst4KPage ( )) != NULL) { if ((RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && - (RscHob.ResourceDescriptor->PhysicalStart == 0)) + (RscHob.ResourceDescriptor->PhysicalStart == (UINTN)NULL)) { - DoClear = TRUE; + CanAllocate = TRUE; // // Make sure memory at 0-4095 has not been allocated. // @@ -73,10 +78,10 @@ ClearFirst4KPage ( MemHob.Raw )) != NULL) { - if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress - < EFI_PAGE_SIZE) + if ((MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress >= (UINTN)NULL) && + (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress < (UINTN)NULL + EFI_PAGE_SIZE)) { - DoClear = FALSE; + CanAllocate = FALSE; break; } @@ -89,27 +94,7 @@ ClearFirst4KPage ( RscHob.Raw = GET_NEXT_HOB (RscHob); } - if (DoClear) { - DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n")); - SetMem (NULL, EFI_PAGE_SIZE, 0); - } - - return; -} - -/** - 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 - ) -{ - return ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0); + return CanAllocate; } /** @@ -155,17 +140,7 @@ IsEnableNonExecNeeded ( VOID ) { - if (!IsExecuteDisableBitAvailable ()) { - return FALSE; - } - - // - // XD flag (BIT63) in page table entry is only valid if IA32_EFER.NXE is set. - // Features controlled by Following PCDs need this feature to be enabled. - // - return (PcdGetBool (PcdSetNxForStack) || - PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0 || - PcdGet32 (PcdImageProtectionPolicy) != 0); + return IsExecuteDisableBitAvailable (); } /** @@ -210,17 +185,17 @@ ToSplitPageTable ( IN UINTN GhcbSize ) { - if (IsNullDetectionEnabled () && (Address == 0)) { + if (mDxeMps.NullPointerDetection.Enabled && (Address == (UINTN)NULL)) { return TRUE; } - if (PcdGetBool (PcdCpuStackGuard)) { + if (mDxeMps.CpuStackGuardEnabled) { if ((StackBase >= Address) && (StackBase < (Address + Size))) { return TRUE; } } - if (PcdGetBool (PcdSetNxForStack)) { + if (mDxeMps.StackExecutionProtectionEnabled) { if ((Address < StackBase + StackSize) && ((Address + Size) > StackBase)) { return TRUE; } @@ -402,17 +377,17 @@ Split2MPageTo4K ( PageTableEntry->Bits.ReadWrite = 1; - if ((IsNullDetectionEnabled () && (PhysicalAddress4K == 0)) || - (PcdGetBool (PcdCpuStackGuard) && (PhysicalAddress4K == StackBase))) + if ((mDxeMps.NullPointerDetection.Enabled && (PhysicalAddress4K == (UINTN)NULL)) || + (mDxeMps.CpuStackGuardEnabled && (PhysicalAddress4K == StackBase))) { PageTableEntry->Bits.Present = 0; } else { PageTableEntry->Bits.Present = 1; } - if ( PcdGetBool (PcdSetNxForStack) - && (PhysicalAddress4K >= StackBase) - && (PhysicalAddress4K < StackBase + StackSize)) + if (mDxeMps.StackExecutionProtectionEnabled && + (PhysicalAddress4K >= StackBase) && + (PhysicalAddress4K < StackBase + StackSize)) { // // Set Nx bit for stack. diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h index 616ebe42b0..c27bf68a04 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h @@ -265,28 +265,17 @@ AsmGetVectorTemplatInfo ( ); /** - Clear legacy memory located at the first 4K-page. + Returns TRUE if the NULL page has not been allocated. - 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 HobStart The start of HobList passed to DxeCore. - @param HobStart The start of HobList passed to DxeCore. + @retval TRUE NULL page is unallocated + @retval FALSE NULL page cannot be allocated **/ -VOID -ClearFirst4KPage ( - 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 +CanAllocateNullPage ( + IN VOID *HobStart ); /** diff --git a/MdeModulePkg/Core/PiSmmCore/HeapGuard.c b/MdeModulePkg/Core/PiSmmCore/HeapGuard.c index 25310122ca..ed174b68e4 100644 --- a/MdeModulePkg/Core/PiSmmCore/HeapGuard.c +++ b/MdeModulePkg/Core/PiSmmCore/HeapGuard.c @@ -8,6 +8,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "HeapGuard.h" +#include + // // Global to avoid infinite reentrance of memory allocation when updating // page table attributes, which may need allocating pages for new PDE/PTE. @@ -579,7 +581,7 @@ UnsetGuardPage ( @param[in] MemoryType Memory type to check. @param[in] AllocateType Allocation type to check. - @param[in] PageOrPool Indicate a page allocation or pool allocation. + @param[in] HeapGuardType Indicates the heap guard type. @return TRUE The given type of memory should be guarded. @@ -589,39 +591,22 @@ BOOLEAN IsMemoryTypeToGuard ( IN EFI_MEMORY_TYPE MemoryType, IN EFI_ALLOCATE_TYPE AllocateType, - IN UINT8 PageOrPool + IN HEAP_GUARD_TYPE HeapGuardType ) { - UINT64 TestBit; - UINT64 ConfigBit; - - if ( ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) == 0) - || mOnGuarding - || (AllocateType == AllocateAddress)) - { + if (mOnGuarding || (AllocateType == AllocateAddress)) { return FALSE; } - ConfigBit = 0; - if ((PageOrPool & GUARD_HEAP_TYPE_POOL) != 0) { - ConfigBit |= PcdGet64 (PcdHeapGuardPoolType); - } - - if ((PageOrPool & GUARD_HEAP_TYPE_PAGE) != 0) { - ConfigBit |= PcdGet64 (PcdHeapGuardPageType); + if ((HeapGuardType == HeapGuardTypePool) && gMmMps.HeapGuard.PoolGuardEnabled) { + return gMmMps.PoolGuard.EnabledForType[MemoryType]; } - if ((MemoryType == EfiRuntimeServicesData) || - (MemoryType == EfiRuntimeServicesCode)) - { - TestBit = LShiftU64 (1, MemoryType); - } else if (MemoryType == EfiMaxMemoryType) { - TestBit = (UINT64)-1; - } else { - TestBit = 0; + if ((HeapGuardType == HeapGuardTypePage) && gMmMps.HeapGuard.PageGuardEnabled) { + return gMmMps.PageGuard.EnabledForType[MemoryType]; } - return ((ConfigBit & TestBit) != 0); + return FALSE; } /** @@ -641,7 +626,7 @@ IsPoolTypeToGuard ( return IsMemoryTypeToGuard ( MemoryType, AllocateAnyPages, - GUARD_HEAP_TYPE_POOL + HeapGuardTypePool ); } @@ -660,24 +645,7 @@ IsPageTypeToGuard ( IN EFI_ALLOCATE_TYPE AllocateType ) { - return IsMemoryTypeToGuard (MemoryType, AllocateType, GUARD_HEAP_TYPE_PAGE); -} - -/** - Check to see if the heap guard is enabled for page and/or pool allocation. - - @return TRUE/FALSE. -**/ -BOOLEAN -IsHeapGuardEnabled ( - VOID - ) -{ - return IsMemoryTypeToGuard ( - EfiMaxMemoryType, - AllocateAnyPages, - GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE - ); + return IsMemoryTypeToGuard (MemoryType, AllocateType, HeapGuardTypePage); } /** @@ -951,7 +919,7 @@ AdjustPoolHeadA ( IN UINTN Size ) { - if ((Memory == 0) || ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0)) { + if ((Memory == 0) || (!gMmMps.HeapGuard.GuardAlignedToTail)) { // // Pool head is put near the head Guard // @@ -977,7 +945,7 @@ AdjustPoolHeadF ( IN EFI_PHYSICAL_ADDRESS Memory ) { - if ((Memory == 0) || ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0)) { + if ((Memory == 0) || (!gMmMps.HeapGuard.GuardAlignedToTail)) { // // Pool head is put near the head Guard // diff --git a/MdeModulePkg/Core/PiSmmCore/HeapGuard.h b/MdeModulePkg/Core/PiSmmCore/HeapGuard.h index 0a447ce2e8..0f3a860b1b 100644 --- a/MdeModulePkg/Core/PiSmmCore/HeapGuard.h +++ b/MdeModulePkg/Core/PiSmmCore/HeapGuard.h @@ -152,10 +152,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent } // -// Memory type to guard (matching the related PCD definition) +// Heap guard types // -#define GUARD_HEAP_TYPE_PAGE BIT2 -#define GUARD_HEAP_TYPE_POOL BIT3 +typedef enum { + HeapGuardTypePage, + HeapGuardTypePool, + HeapGuardTypeFreed, + HeapGuardTypeMax +} HEAP_GUARD_TYPE; // // Debug message level @@ -362,16 +366,6 @@ SmmInternalFreePagesExWithGuard ( IN BOOLEAN AddRegion ); -/** - Check to see if the heap guard is enabled for page and/or pool allocation. - - @return TRUE/FALSE. -**/ -BOOLEAN -IsHeapGuardEnabled ( - VOID - ); - /** Debug function used to verify if the Guard page is well set or not. diff --git a/MdeModulePkg/Core/PiSmmCore/Page.c b/MdeModulePkg/Core/PiSmmCore/Page.c index 255964c23a..e2db7ea114 100644 --- a/MdeModulePkg/Core/PiSmmCore/Page.c +++ b/MdeModulePkg/Core/PiSmmCore/Page.c @@ -943,8 +943,10 @@ SmmFreePages ( return EFI_NOT_FOUND; } - IsGuarded = IsHeapGuardEnabled () && IsMemoryGuarded (Memory); - Status = SmmInternalFreePages (Memory, NumberOfPages, IsGuarded); + IsGuarded = (gMmMps.HeapGuard.PageGuardEnabled || + gMmMps.HeapGuard.PoolGuardEnabled) && + IsMemoryGuarded (Memory); + Status = SmmInternalFreePages (Memory, NumberOfPages, IsGuarded); if (!EFI_ERROR (Status)) { SmmCoreUpdateProfile ( (EFI_PHYSICAL_ADDRESS)(UINTN)RETURN_ADDRESS (0), diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h index b8a490a8c3..c17afdd097 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "PiSmmCorePrivateData.h" #include "HeapGuard.h" diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf index 3df44b38f1..66fdccc1a9 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf @@ -61,6 +61,7 @@ HobLib SmmMemLib SafeIntLib + MmMemoryProtectionHobLib [Protocols] gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED # SmiHandlerRegister @@ -94,9 +95,6 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfileDriverPath ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdSmiHandlerProfilePropertyMask ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONSUMES [Guids] diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c b/MdeModulePkg/Core/PiSmmCore/Pool.c index e1ff40a8ea..7fb2305763 100644 --- a/MdeModulePkg/Core/PiSmmCore/Pool.c +++ b/MdeModulePkg/Core/PiSmmCore/Pool.c @@ -257,8 +257,7 @@ SmmInternalAllocatePool ( } NeedGuard = IsPoolTypeToGuard (PoolType); - HasPoolTail = !(NeedGuard && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); + HasPoolTail = !(NeedGuard && gMmMps.HeapGuard.GuardAlignedToTail); // // Adjust the size by the pool header & tail overhead @@ -389,10 +388,10 @@ SmmInternalFreePool ( return EFI_INVALID_PARAMETER; } - MemoryGuarded = IsHeapGuardEnabled () && + MemoryGuarded = (gMmMps.HeapGuard.PageGuardEnabled || + gMmMps.HeapGuard.PoolGuardEnabled) && IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)FreePoolHdr); - HasPoolTail = !(MemoryGuarded && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); + HasPoolTail = !(MemoryGuarded && gMmMps.HeapGuard.GuardAlignedToTail); if (HasPoolTail) { PoolTail = HEAD_TO_TAIL (&FreePoolHdr->Header); -- 2.41.0.windows.2