diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 45775438e8..c8cfe85865 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2699,7 +2699,8 @@ CoreInitializeMemoryAttributesTable ( **/ VOID EFIAPI -CoreInitializeMemoryProtection ( +// MU_CHANGE: Use Project Mu CoreInitializeMemoryProtection() +CoreInitializeMemoryProtectionMu ( VOID ); diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index 7a726ed69a..49a2c36274 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -479,7 +479,7 @@ DxeMain ( MemoryProfileInstallProtocol (); CoreInitializeMemoryAttributesTable (); - CoreInitializeMemoryProtection (); + CoreInitializeMemoryProtectionMu (); // MU_CHANGE: Use Project Mu CoreInitializeMemoryProtection() // // Get persisted vector hand-off info from GUIDeed HOB again due to HobStart may be updated, diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index 1aa1a2aec2..919bc10f41 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -39,7 +39,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include -#include // MU_CHANGE #include // MU_CHANGE #include "DxeMain.h" @@ -66,11 +65,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) -// UINT32 mImageProtectionPolicy; // MU_CHANGE +UINT32 mImageProtectionPolicy; extern LIST_ENTRY mGcdMemorySpaceMap; EFI_MEMORY_ATTRIBUTE_PROTOCOL *mMemoryAttribute = NULL; // MU_CHANGE +extern BOOLEAN mPageAttributesInitialized; // MU_CHANGE STATIC LIST_ENTRY mProtectedImageRecordList; // MS_CHANGE - START @@ -83,6 +83,7 @@ STATIC MEMORY_PROTECTION_DEBUG_PROTOCOL mMemoryProtectionDebug = BOOLEAN mGcdSyncComplete = FALSE; // MS_CHANGE - END +STATIC LIST_ENTRY mProtectedImageRecordList = INITIALIZE_LIST_HEAD_VARIABLE (mProtectedImageRecordList); // MU_CHANGE: Initialize at compile time /** Get the image type. @@ -986,21 +987,25 @@ MemoryProtectionExitBootServicesCallback ( } } -// MU_CHANGE [START]: Move disable NULL detection to separate routine so it can be called -// outside of the event context. - /** - Disable NULL pointer detection. + Disable NULL pointer detection after EndOfDxe. This is a workaround resort in + order to skip unfixable NULL pointer access issues detected in OptionROM or + boot loaders. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Event. **/ VOID -DisableNullDetection ( - VOID +EFIAPI +DisableNullDetectionAtTheEndOfDxe ( + EFI_EVENT Event, + VOID *Context ) { EFI_STATUS Status; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc; - DEBUG ((DEBUG_INFO, "%a - start\r\n", __FUNCTION__)); + DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): start\r\n")); // // Disable NULL pointer detection by enabling first 4K page // @@ -1023,249 +1028,91 @@ DisableNullDetection ( ); ASSERT_EFI_ERROR (Status); - DEBUG ((DEBUG_INFO, "%a - end\r\n", __FUNCTION__)); - - return; -} - -/** - Disable NULL pointer detection after EndOfDxe. This is a workaround resort in - order to skip unfixable NULL pointer access issues detected in OptionROM or - boot loaders. + // + // Page 0 might have be allocated to avoid misuses. Free it here anyway. + // + CoreFreePages (0, 1); - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registered to the Event. -**/ -VOID -EFIAPI -DisableNullDetectionEventFunction ( - EFI_EVENT Event, - VOID *Context - ) -{ - DisableNullDetection (); CoreCloseEvent (Event); - return; -} - -// MU_CHANGE [END] - -// MU_CHANGE START: Add function to enable null detection as it is now done in DXE instead of PEI - -/** - Enable NULL pointer detection by changing the attributes of page 0. The assumption is that PEI - has set page zero to allocated so this operation can be done safely. - - @retval EFI_SUCCESS Page zero successfully marked as read protected - @retval Other Page zero could not be marked as read protected - -**/ -VOID -EFIAPI -EnableNullDetection ( - EFI_EVENT Event, - VOID *Context - ) -{ - EFI_STATUS Status; - EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc; - - Status = CoreGetMemorySpaceDescriptor (0, &Desc); - - if (EFI_ERROR (Status)) { - return; - } - - if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) { - Status = CoreSetMemorySpaceCapabilities ( - 0, - EFI_PAGES_TO_SIZE (1), - Desc.Capabilities | EFI_MEMORY_RP - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto Done; - } - } - - Status = CoreSetMemorySpaceAttributes ( - 0, - EFI_PAGES_TO_SIZE (1), - Desc.Attributes | EFI_MEMORY_RP - ); - ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "DisableNullDetectionAtTheEndOfDxe(): end\r\n")); -Done: - CoreCloseEvent (Event); + return; } -// MU_CHANGE END +// MU_CHANGE START: Comment out unused functions /** Initialize Memory Protection support. **/ -VOID -EFIAPI -CoreInitializeMemoryProtection ( - VOID - ) -{ - EFI_STATUS Status; - // MU_CHANGE START: Update to use memory protection settings HOB, - // add support for RP on free memory. - EFI_EVENT DisableNullDetectionEvent; - EFI_EVENT EnableNullDetectionEvent; - EFI_EVENT MemoryAttributeProtocolEvent; - VOID *Registration; - - // mImageProtectionPolicy = gDxeMps.ImageProtectionPolicy; - // MU_CHANGE END - InitializeListHead (&mProtectedImageRecordList); - - // - // Sanity check the Image Protection Policy setting: // MU_CHANGE - // - code regions should have no EFI_MEMORY_XP attribute - // - EfiConventionalMemory and EfiBootServicesData should use the - // same attribute - // - // MU_CHANGE START: We allow code types to have NX and EfiBootServicesData to differ in attributes from - // EfiConventionalMemory - // ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0); - // ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0); - // ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0); - // ASSERT ( - // GetPermissionAttributeForMemoryType (EfiBootServicesData) == - // GetPermissionAttributeForMemoryType (EfiConventionalMemory) - // ); - // MU_CHANGE END - - // MU_CHANGE START: Change ordering of GCD sync and memory protection initialization - // Status = CoreCreateEvent ( - // EVT_NOTIFY_SIGNAL, - // TPL_CALLBACK, - // MemoryProtectionCpuArchProtocolNotify, - // NULL, - // &Event - // ); - // ASSERT_EFI_ERROR (Status); - - // // - // // Register for protocol notifactions on this event - // // - // Status = CoreRegisterProtocolNotify ( - // &gEfiCpuArchProtocolGuid, - // Event, - // &Registration - // ); - // ASSERT_EFI_ERROR (Status); - // MU_CHANGE END - - // MU_CHANGE START: Register an event to populate the memory attribute protocol - Status = CoreCreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - MemoryAttributeProtocolNotify, - NULL, - &MemoryAttributeProtocolEvent - ); - ASSERT_EFI_ERROR (Status); - - // - // Register for protocol notification - // - Status = CoreRegisterProtocolNotify ( - &gEfiMemoryAttributeProtocolGuid, - MemoryAttributeProtocolEvent, - &Registration - ); - ASSERT_EFI_ERROR (Status); - // MU_CHANGE END - - // MU_CHANGE START: Add event to apply page attribues according to the memory protection policy - // after the GCD has synced. - Status = RegisterPageAccessAttributesUpdateOnGcdSyncComplete (); - ASSERT_EFI_ERROR (Status); - // MU_CHANGE END - - // - // Register a callback to disable NULL pointer detection at EndOfDxe - // - // MU_CHANGE START Update to use memory protection settings HOB, added - // disable functionality at ReadyToBoot, create NULL - // detection enable event - // if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) - // == (BIT0|BIT7)) { - if (gDxeMps.NullPointerDetectionPolicy.Fields.UefiNullDetection) { - // PEI phase has been updated to always set page zero as allocated - // so it can be safely set as RP - Status = CoreCreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK - 1, - EnableNullDetection, - NULL, - &EnableNullDetectionEvent - ); - ASSERT_EFI_ERROR (Status); +// VOID +// EFIAPI +// CoreInitializeMemoryProtection ( +// VOID +// ) +// { +// EFI_STATUS Status; +// EFI_EVENT Event; +// EFI_EVENT EndOfDxeEvent; +// VOID *Registration; - Status = CoreRegisterProtocolNotify ( - &gEfiCpuArchProtocolGuid, - EnableNullDetectionEvent, - &Registration - ); - ASSERT_EFI_ERROR (Status); +// mImageProtectionPolicy = PcdGet32 (PcdImageProtectionPolicy); - if (!EFI_ERROR (Status)) { - // If both DisableEndOfDxe and DisableReadyToBoot are enabled, just - // create the event to disable at EndOfDxe because that event is sooner - if (gDxeMps.NullPointerDetectionPolicy.Fields.DisableEndOfDxe) { - Status = CoreCreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - DisableNullDetectionEventFunction, - NULL, - &gEfiEndOfDxeEventGroupGuid, - &DisableNullDetectionEvent - ); - } else if (gDxeMps.NullPointerDetectionPolicy.Fields.DisableReadyToBoot) { - Status = CoreCreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - DisableNullDetectionEventFunction, - NULL, - &gEfiEventReadyToBootGuid, - &DisableNullDetectionEvent - ); - } - } +// InitializeListHead (&mProtectedImageRecordList); - ASSERT_EFI_ERROR (Status); - } +// // +// // Sanity check the PcdDxeNxMemoryProtectionPolicy 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 ( +// GetPermissionAttributeForMemoryType (EfiBootServicesData) == +// GetPermissionAttributeForMemoryType (EfiConventionalMemory) +// ); + +// Status = CoreCreateEvent ( +// EVT_NOTIFY_SIGNAL, +// TPL_CALLBACK, +// MemoryProtectionCpuArchProtocolNotify, +// NULL, +// &Event +// ); +// ASSERT_EFI_ERROR (Status); - // MU_CHANGE END +// // +// // Register for protocol notifactions on this event +// // +// Status = CoreRegisterProtocolNotify ( +// &gEfiCpuArchProtocolGuid, +// Event, +// &Registration +// ); +// ASSERT_EFI_ERROR (Status); - // - // MSCHANGE START - // Install protocol for validating Heap Guard if Heap Guard is turned on - // Update to use memory protection settings HOB - // if (PcdGet8(PcdHeapGuardPropertyMask)) { - if (gDxeMps.HeapGuardPolicy.Data || - gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromFv || - gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromUnknown) - { - EFI_HANDLE HgBmHandle = NULL; - Status = CoreInstallMultipleProtocolInterfaces ( - &HgBmHandle, - &gMemoryProtectionDebugProtocolGuid, - &mMemoryProtectionDebug, - NULL - ); - DEBUG ((DEBUG_INFO, "Installed gMemoryProtectionDebugProtocolGuid - %r\n", Status)); - } +// // +// // Register a callback to disable NULL pointer detection at EndOfDxe +// // +// if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) +// == (BIT0|BIT7)) +// { +// Status = CoreCreateEventEx ( +// EVT_NOTIFY_SIGNAL, +// TPL_NOTIFY, +// DisableNullDetectionAtTheEndOfDxe, +// NULL, +// &gEfiEndOfDxeEventGroupGuid, +// &EndOfDxeEvent +// ); +// ASSERT_EFI_ERROR (Status); +// } - // MSCHANGE END +// return; +// } - return; -} +// MU_CHANGE END /** Returns whether we are currently executing in SMM mode. diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c index 634b886b0d..8a2b02a09a 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c @@ -29,7 +29,7 @@ BOOLEAN mEnhancedMemoryProtectionActive = TRUE; EFI_MEMORY_ATTRIBUTE_PROTOCOL *mMemoryAttributeProtocol = NULL; UINT8 *mBitmapGlobal = NULL; LIST_ENTRY **mArrayOfListEntryPointers = NULL; -extern BOOLEAN mGcdSyncComplete = FALSE; +BOOLEAN mGcdSyncComplete = FALSE; #define IS_BITMAP_INDEX_SET(Bitmap, Index) ((((UINT8*)Bitmap)[Index / 8] & (1 << (Index % 8))) != 0 ? TRUE : FALSE) #define SET_BITMAP_INDEX(Bitmap, Index) (((UINT8*)Bitmap)[Index / 8] |= (1 << (Index % 8))) @@ -161,14 +161,11 @@ SetUefiImageMemoryAttributes ( IN UINT64 Attributes ); -/** - Disable NULL pointer detection. -**/ -VOID -EFIAPI -DisableNullDetection ( - VOID - ); +STATIC MEMORY_PROTECTION_DEBUG_PROTOCOL mMemoryProtectionDebug = +{ + IsGuardPage, + GetImageList +}; /** Converts a number of pages to a size in bytes. @@ -2532,6 +2529,106 @@ GetDxeMemoryProtectionSettings ( return NULL; } +/** + Enable NULL pointer detection by changing the attributes of page 0. The assumption is that PEI + has set page zero to allocated so this operation can be done safely. + + @retval EFI_SUCCESS Page zero successfully marked as read protected + @retval Other Page zero could not be marked as read protected + +**/ +VOID +EFIAPI +EnableNullDetection ( + VOID + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc; + + Status = CoreGetMemorySpaceDescriptor (0, &Desc); + + if (EFI_ERROR (Status)) { + return; + } + + if ((Desc.Capabilities & EFI_MEMORY_RP) == 0) { + Status = CoreSetMemorySpaceCapabilities ( + 0, + EFI_PAGES_TO_SIZE (1), + Desc.Capabilities | EFI_MEMORY_RP + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + } + + Status = CoreSetMemorySpaceAttributes ( + 0, + EFI_PAGES_TO_SIZE (1), + Desc.Attributes | EFI_MEMORY_RP + ); + ASSERT_EFI_ERROR (Status); +} + +/** + Disable NULL pointer detection. +**/ +VOID +DisableNullDetection ( + VOID + ) +{ + EFI_STATUS Status; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Desc; + + DEBUG ((DEBUG_INFO, "%a - Enter\n", __func__)); + + Status = CoreGetMemorySpaceDescriptor (0, &Desc); + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a - Failed to get memory space descriptor for NULL address! Status = %r\n", + __func__, + Status + )); + return; + } + + Status = CoreSetMemorySpaceAttributes ( + 0, + EFI_PAGE_SIZE, + Desc.Attributes & ~EFI_MEMORY_RP + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "%a - Exit\n", __func__)); + + return; +} + +/** + Disable NULL pointer detection after EndOfDxe. This is a workaround resort in + order to skip unfixable NULL pointer access issues detected in OptionROM or + boot loaders. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Event. +**/ +VOID +EFIAPI +DisableNullDetectionCallback ( + EFI_EVENT Event, + VOID *Context + ) +{ + DisableNullDetection (); + CoreCloseEvent (Event); + return; +} + /** Uninstalls the Memory Attribute Protocol from all handles. **/ @@ -2650,49 +2747,118 @@ InitializePageAttributesCallback ( IN VOID *Context ) { + EFI_STATUS Status; + EFI_EVENT DisableNullDetectionEvent; + + // Initialize paging attributes InitializePageAttributesForMemoryProtectionPolicy (); + // Must set this to TRUE so calls to ApplyMemoryProtectionPolicy() are not + // blocked. This BOOLEAN also allows guard pages to be set and EFI_MEMORY_RP + // to be applied to memory being freed. + mGcdSyncComplete = TRUE; + + // Set all the guard pages HeapGuardCpuArchProtocolNotify (); - mPageAttributesInitialized = TRUE; + if (gDxeMps.NullPointerDetectionPolicy.Fields.UefiNullDetection) { + // Enable NULL pointer detection + EnableNullDetection (); + + // Register for NULL pointer detection disabling if policy dictates + if (gDxeMps.NullPointerDetectionPolicy.Fields.DisableEndOfDxe) { + Status = CoreCreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DisableNullDetectionCallback, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &DisableNullDetectionEvent + ); + } else if (gDxeMps.NullPointerDetectionPolicy.Fields.DisableReadyToBoot) { + Status = CoreCreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DisableNullDetectionCallback, + NULL, + &gEfiEventReadyToBootGuid, + &DisableNullDetectionEvent + ); + } + + ASSERT_EFI_ERROR (Status); + } else { + // The NULL page may be EFI_MEMORY_RP in the page tables inherited + // from PEI so clear the attribute now + DisableNullDetection (); + } CoreCloseEvent (Event); } /** - Registers a callback on gEdkiiGcdSyncCompleteProtocolGuid to initialize page attributes - in accordance with to the memory protection policy. - - @retval EFI_SUCCESS Event successfully registered - @retval other Event was not registered - */ -EFI_STATUS + Initialize Memory Protection support. +**/ +VOID EFIAPI -RegisterPageAccessAttributesUpdateOnGcdSyncComplete ( +CoreInitializeMemoryProtectionMu ( VOID ) { EFI_STATUS Status; - EFI_EVENT Event; VOID *Registration; + EFI_EVENT Event; + EFI_HANDLE HgBmHandle = NULL; + // Register an event to populate the memory attribute protocol Status = CoreCreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, - InitializePageAttributesCallback, + MemoryAttributeProtocolNotify, NULL, &Event ); + ASSERT_EFI_ERROR (Status); - if (EFI_ERROR (Status)) { - return Status; - } + // Register for protocol notification + Status = CoreRegisterProtocolNotify ( + &gEfiMemoryAttributeProtocolGuid, + Event, + &Registration + ); + ASSERT_EFI_ERROR (Status); + + // Register an event to initialize memory protection + Status = CoreCreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InitializePageAttributesCallback, + NULL, + &Event + ); + ASSERT_EFI_ERROR (Status); + // Register for protocol notification Status = CoreRegisterProtocolNotify ( &gEdkiiGcdSyncCompleteProtocolGuid, Event, &Registration ); + ASSERT_EFI_ERROR (Status); - return Status; + // Register protocol for auditing memory protection (used by DxePagingAuditTestApp) + if (gDxeMps.HeapGuardPolicy.Data || + gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromFv || + gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromUnknown) + { + Status = CoreInstallMultipleProtocolInterfaces ( + &HgBmHandle, + &gMemoryProtectionDebugProtocolGuid, + &mMemoryProtectionDebug, + NULL + ); + DEBUG ((DEBUG_INFO, "Installed gMemoryProtectionDebugProtocolGuid - %r\n", Status)); + } + + return; } diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h index 092384d5e5..e512e8f9cf 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h @@ -129,21 +129,6 @@ MemoryProtectionCpuArchProtocolNotifyMu ( IN VOID *Context ); -/** - A notification for the Memory Attribute 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 -MemoryAttributeProtocolNotify ( - IN EFI_EVENT Event, - IN VOID *Context - ); - /** Sets the NX compatibility global to FALSE so future checks to IsEnhancedMemoryProtectionActive() will return FALSE. @@ -183,17 +168,4 @@ GetImageList ( IN IMAGE_RANGE_PROTECTION_STATUS ProtectedOrNonProtected ); -/** - Registers a callback on gEdkiiGcdSyncCompleteProtocolGuid to initialize - page attributes in accordance with to the memory protection policy. - - @retval EFI_SUCCESS Event successfully registered - @retval other Event was not registered -**/ -EFI_STATUS -EFIAPI -RegisterPageAccessAttributesUpdateOnGcdSyncComplete ( - VOID - ); - #endif