\r
Once the image is unloaded, the protection is removed automatically.\r
\r
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
#include <Guid/PropertiesTable.h>\r
\r
#include <Protocol/FirmwareVolume2.h>\r
-#include <Protocol/BlockIo.h>\r
#include <Protocol/SimpleFileSystem.h>\r
\r
#include "DxeMain.h"\r
+#include "Mem/HeapGuard.h"\r
\r
#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)\r
#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)\r
UINT64 Attributes;\r
LIST_ENTRY *Link;\r
EFI_GCD_MAP_ENTRY *Entry;\r
+ EFI_PEI_HOB_POINTERS Hob;\r
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
+ EFI_PHYSICAL_ADDRESS StackBase;\r
\r
//\r
// Get the EFI memory map.\r
} while (Status == EFI_BUFFER_TOO_SMALL);\r
ASSERT_EFI_ERROR (Status);\r
\r
- DEBUG((DEBUG_ERROR, "%a: applying strict permissions to active memory regions\n",\r
- __FUNCTION__));\r
+ StackBase = 0;\r
+ if (PcdGetBool (PcdCpuStackGuard)) {\r
+ //\r
+ // Get the base of stack from Hob.\r
+ //\r
+ Hob.Raw = GetHobList ();\r
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
+ MemoryHob = Hob.MemoryAllocation;\r
+ if (CompareGuid(&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: StackBase = 0x%016lx StackSize = 0x%016lx\n",\r
+ __FUNCTION__,\r
+ MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
+ MemoryHob->AllocDescriptor.MemoryLength\r
+ ));\r
+\r
+ StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+ //\r
+ // Ensure the base of the stack is page-size aligned.\r
+ //\r
+ ASSERT ((StackBase & EFI_PAGE_MASK) == 0);\r
+ break;\r
+ }\r
+ Hob.Raw = GET_NEXT_HOB (Hob);\r
+ }\r
+\r
+ //\r
+ // Ensure the base of stack can be found from Hob when stack guard is\r
+ // enabled.\r
+ //\r
+ ASSERT (StackBase != 0);\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: applying strict permissions to active memory regions\n",\r
+ __FUNCTION__\r
+ ));\r
\r
MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);\r
\r
MemoryMapEntry->PhysicalStart,\r
LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),\r
Attributes);\r
+\r
+ //\r
+ // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is\r
+ // enabled.\r
+ //\r
+ if (MemoryMapEntry->PhysicalStart == 0 &&\r
+ PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0) {\r
+\r
+ ASSERT (MemoryMapEntry->NumberOfPages > 0);\r
+ SetUefiImageMemoryAttributes (\r
+ 0,\r
+ EFI_PAGES_TO_SIZE (1),\r
+ EFI_MEMORY_RP | Attributes);\r
+ }\r
+\r
+ //\r
+ // Add EFI_MEMORY_RP attribute for the first page of the stack if stack\r
+ // guard is enabled.\r
+ //\r
+ if (StackBase != 0 &&\r
+ (StackBase >= MemoryMapEntry->PhysicalStart &&\r
+ StackBase < MemoryMapEntry->PhysicalStart +\r
+ LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT)) &&\r
+ PcdGetBool (PcdCpuStackGuard)) {\r
+\r
+ SetUefiImageMemoryAttributes (\r
+ StackBase,\r
+ EFI_PAGES_TO_SIZE (1),\r
+ EFI_MEMORY_RP | Attributes);\r
+ }\r
+\r
}\r
MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
}\r
// accessible, but have not been added to the UEFI memory map (yet).\r
//\r
if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) {\r
- DEBUG((DEBUG_ERROR,\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
"%a: applying strict permissions to inactive memory regions\n",\r
- __FUNCTION__));\r
+ __FUNCTION__\r
+ ));\r
\r
CoreAcquireGcdMemoryLock ();\r
\r
InitializeDxeNxMemoryProtectionPolicy ();\r
}\r
\r
+ //\r
+ // Call notify function meant for Heap Guard.\r
+ //\r
+ HeapGuardCpuArchProtocolNotify ();\r
+\r
if (mImageProtectionPolicy == 0) {\r
return;\r
}\r
}\r
}\r
\r
+/**\r
+ Disable NULL pointer detection after EndOfDxe. This is a workaround resort in\r
+ order to skip unfixable NULL pointer access issues detected in OptionROM or\r
+ boot loaders.\r
+\r
+ @param[in] Event The Event this notify function registered to.\r
+ @param[in] Context Pointer to the context data registered to the Event.\r
+**/\r
+VOID\r
+EFIAPI\r
+DisableNullDetectionAtTheEndOfDxe (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc;\r
+\r
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n"));\r
+ //\r
+ // Disable NULL pointer detection by enabling first 4K page\r
+ //\r
+ Status = CoreGetMemorySpaceDescriptor (0, &Desc);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) {\r
+ Status = CoreSetMemorySpaceCapabilities (\r
+ 0,\r
+ EFI_PAGE_SIZE,\r
+ Desc.Capabilities | EFI_MEMORY_RP\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ Status = CoreSetMemorySpaceAttributes (\r
+ 0,\r
+ EFI_PAGE_SIZE,\r
+ Desc.Attributes & ~EFI_MEMORY_RP\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ CoreCloseEvent (Event);\r
+ DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n"));\r
+\r
+ return;\r
+}\r
+\r
/**\r
Initialize Memory Protection support.\r
**/\r
{\r
EFI_STATUS Status;\r
EFI_EVENT Event;\r
+ EFI_EVENT EndOfDxeEvent;\r
VOID *Registration;\r
\r
mImageProtectionPolicy = PcdGet32(PcdImageProtectionPolicy);\r
);\r
ASSERT_EFI_ERROR(Status);\r
}\r
+\r
+ //\r
+ // Register a callback to disable NULL pointer detection at EndOfDxe\r
+ //\r
+ if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7))\r
+ == (BIT0|BIT7)) {\r
+ Status = CoreCreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ DisableNullDetectionAtTheEndOfDxe,\r
+ NULL,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
return ;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
+ //\r
+ // Don't overwrite Guard pages, which should be the first and/or last page,\r
+ // if any.\r
+ //\r
+ if (IsHeapGuardEnabled ()) {\r
+ if (IsGuardPage (Memory)) {\r
+ Memory += EFI_PAGE_SIZE;\r
+ Length -= EFI_PAGE_SIZE;\r
+ if (Length == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ if (IsGuardPage (Memory + Length - EFI_PAGE_SIZE)) {\r
+ Length -= EFI_PAGE_SIZE;\r
+ if (Length == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
//\r
// Update the executable permissions according to the DXE memory\r
// protection policy, but only if\r