diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index c35f713488..07f40e92e2 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -996,90 +996,92 @@ MergeMemoryMapForProtectionPolicy ( 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; - - /* MU_CHANGE Start: Use Enhanced Memory Protections - DEBUG ((DEBUG_INFO, "MemoryProtectionCpuArchProtocolNotify:\n")); - Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); - if (EFI_ERROR (Status)) { - goto Done; - } +// MU_CHANGE Start: Remove Unused Function +// 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; + +// /* MU_CHANGE Start: Use Enhanced Memory Protections +// 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 (); - } - */ +// // +// // Apply the memory protection policy on non-BScode/RTcode regions. +// // +// if (PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) { +// InitializeDxeNxMemoryProtectionPolicy (); +// } +// */ - if (gCpu == NULL) { - goto Done; - } +// if (gCpu == NULL) { +// goto Done; +// } - InitializePageAttributesForMemoryProtectionPolicy (); +// InitializePageAttributesForMemoryProtectionPolicy (); - // - // Call notify function meant for Heap Guard. - // - HeapGuardCpuArchProtocolNotify (); +// // +// // Call notify function meant for Heap Guard. +// // +// HeapGuardCpuArchProtocolNotify (); - /* - if (mImageProtectionPolicy == 0) { - goto Done; - } +// /* +// if (mImageProtectionPolicy == 0) { +// goto Done; +// } - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiLoadedImageProtocolGuid, - NULL, - &NoHandles, - &HandleBuffer - ); - if (EFI_ERROR (Status) && (NoHandles == 0)) { - goto Done; - } +// Status = gBS->LocateHandleBuffer ( +// ByProtocol, +// &gEfiLoadedImageProtocolGuid, +// NULL, +// &NoHandles, +// &HandleBuffer +// ); +// if (EFI_ERROR (Status) && (NoHandles == 0)) { +// goto Done; +// } - for (Index = 0; Index < NoHandles; Index++) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiLoadedImageProtocolGuid, - (VOID **)&LoadedImage - ); - if (EFI_ERROR (Status)) { - continue; - } +// for (Index = 0; Index < NoHandles; Index++) { +// Status = gBS->HandleProtocol ( +// HandleBuffer[Index], +// &gEfiLoadedImageProtocolGuid, +// (VOID **)&LoadedImage +// ); +// if (EFI_ERROR (Status)) { +// continue; +// } - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID **)&LoadedImageDevicePath - ); - if (EFI_ERROR (Status)) { - LoadedImageDevicePath = NULL; - } +// Status = gBS->HandleProtocol ( +// HandleBuffer[Index], +// &gEfiLoadedImageDevicePathProtocolGuid, +// (VOID **)&LoadedImageDevicePath +// ); +// if (EFI_ERROR (Status)) { +// LoadedImageDevicePath = NULL; +// } - ProtectUefiImage (LoadedImage, LoadedImageDevicePath); - } +// ProtectUefiImage (LoadedImage, LoadedImageDevicePath); +// } - FreePool (HandleBuffer); - MU_CHANGE End: Use Enhanced Memory Protections */ +// FreePool (HandleBuffer); +// MU_CHANGE End: Use Enhanced Memory Protections */ -Done: - CoreCloseEvent (Event); -} +// Done: +// CoreCloseEvent (Event); +// } +// MU_CHANGE End: Remove Unused function /** ExitBootServices Callback function for memory protection. @@ -1189,8 +1191,7 @@ DisableNullDetectionEventFunction ( VOID EFIAPI EnableNullDetection ( - EFI_EVENT Event, - VOID *Context + VOID ) { EFI_STATUS Status; @@ -1210,7 +1211,7 @@ EnableNullDetection ( ); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); - goto Done; + return; } } @@ -1220,9 +1221,6 @@ EnableNullDetection ( Desc.Attributes | EFI_MEMORY_RP ); ASSERT_EFI_ERROR (Status); - -Done: - CoreCloseEvent (Event); } // MU_CHANGE END @@ -1236,137 +1234,135 @@ 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); MU_CHANGE - - - // - // 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 - - // Status = CoreCreateEvent ( - // EVT_NOTIFY_SIGNAL, - // TPL_CALLBACK, - // MemoryProtectionCpuArchProtocolNotify, - // NULL, - // &Event - // ); - // ASSERT_EFI_ERROR (Status); + // MU_CHANGE Start: Consolidate MU_CHANGEs + // 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); // // - // // Register for protocol notifactions on this event + // // 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 // // - // Status = CoreRegisterProtocolNotify ( - // &gEfiCpuArchProtocolGuid, - // Event, - // &Registration - // ); - // ASSERT_EFI_ERROR (Status); - // MU_CHANGE END - - // MU_CHANGE START: Change ordering of GCD sync and memory protection initialization - // Status = CoreCreateEvent ( - // EVT_NOTIFY_SIGNAL, - // TPL_CALLBACK - 1, // MU_CHANGE Update CpuArchProtocolNotify - // MemoryAttributeProtocolNotify, - // NULL, - // &MemoryAttributeProtocolEvent - // ); + // // 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 + + // // 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: Change ordering of GCD sync and memory protection initialization + // // Status = CoreCreateEvent ( + // // EVT_NOTIFY_SIGNAL, + // // TPL_CALLBACK - 1, // MU_CHANGE Update CpuArchProtocolNotify + // // 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 for protocol notification + // // Register a callback to disable NULL pointer detection at EndOfDxe // // - // 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); - - Status = CoreRegisterProtocolNotify ( - &gEfiCpuArchProtocolGuid, - EnableNullDetectionEvent, - &Registration - ); - ASSERT_EFI_ERROR (Status); - - 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 - ); - } - } + // // 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); + + // Status = CoreRegisterProtocolNotify ( + // &gEfiCpuArchProtocolGuid, + // EnableNullDetectionEvent, + // &Registration + // ); + // ASSERT_EFI_ERROR (Status); + + // 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 + // ); + // } + // } - ASSERT_EFI_ERROR (Status); - } + // ASSERT_EFI_ERROR (Status); // MU_CHANGE END @@ -1375,11 +1371,70 @@ CoreInitializeMemoryProtection ( // 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)); + // } + + // // MSCHANGE END + + // return; + + EFI_STATUS Status; + 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, + MemoryAttributeProtocolNotify, + NULL, + &Event + ); + ASSERT_EFI_ERROR (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); + + // Register protocol for auditing memory protection (used by DxePagingAuditTestApp) if (gDxeMps.HeapGuardPolicy.Data || gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromFv || gDxeMps.ImageProtectionPolicy.Fields.ProtectImageFromUnknown) { - EFI_HANDLE HgBmHandle = NULL; Status = CoreInstallMultipleProtocolInterfaces ( &HgBmHandle, &gMemoryProtectionDebugProtocolGuid, @@ -1389,9 +1444,8 @@ CoreInitializeMemoryProtection ( DEBUG ((DEBUG_INFO, "Installed gMemoryProtectionDebugProtocolGuid - %r\n", Status)); } - // MSCHANGE END - return; + // MU_CHANGE End: Consolidate MU_CHANGEs } /** diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c index f1e469b3cb..a44ee18f62 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.c @@ -161,6 +161,20 @@ SetUefiImageMemoryAttributes ( IN UINT64 Attributes ); +/** + 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 + ); + /** Disable NULL pointer detection. **/ @@ -170,6 +184,21 @@ DisableNullDetection ( VOID ); +/** + 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 +DisableNullDetectionEventFunction ( + EFI_EVENT Event, + VOID *Context + ); + extern LIST_ENTRY mGcdMemorySpaceMap; // --------------------------------------- @@ -2670,49 +2699,51 @@ InitializePageAttributesCallback ( IN VOID *Context ) { - InitializePageAttributesForMemoryProtectionPolicy (); + EFI_STATUS Status; + EFI_EVENT DisableNullDetectionEvent; - HeapGuardCpuArchProtocolNotify (); + // Initialize paging attributes + InitializePageAttributesForMemoryProtectionPolicy (); + // Indicates that the GCD sync process has been completed. This BOOLEAN + // must set this to TRUE so calls to ApplyMemoryProtectionPolicy() are not + // blocked. This BOOLEAN also allows guard pages to be set. mGcdSyncComplete = TRUE; - CoreCloseEvent (Event); -} + // Set all the guard pages + HeapGuardCpuArchProtocolNotify (); -/** - Registers a callback on gEdkiiGcdSyncCompleteProtocolGuid to initialize page attributes - in accordance with to the memory protection policy. + if (gDxeMps.NullPointerDetectionPolicy.Fields.UefiNullDetection) { + // Enable NULL pointer detection + EnableNullDetection (); - @retval EFI_SUCCESS Event successfully registered - @retval other Event was not registered - */ -EFI_STATUS -EFIAPI -RegisterPageAccessAttributesUpdateOnGcdSyncComplete ( - VOID - ) -{ - EFI_STATUS Status; - EFI_EVENT Event; - VOID *Registration; - - Status = CoreCreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - InitializePageAttributesCallback, - NULL, - &Event - ); + // Register for NULL pointer detection disabling if policy dictates + 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 + ); + } - if (EFI_ERROR (Status)) { - return Status; + 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 (); } - Status = CoreRegisterProtocolNotify ( - &gEdkiiGcdSyncCompleteProtocolGuid, - Event, - &Registration - ); - - return Status; + CoreCloseEvent (Event); } diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h index afbe6c5a16..966a4955a3 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtectionSupport.h @@ -136,11 +136,9 @@ InitializePageAttributesForMemoryProtectionPolicy ( /** 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 @@ -189,16 +187,14 @@ GetImageList ( ); /** - 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 + Event function called when gEdkiiGcdSyncCompleteProtocolGuid is + installed to initialize access attributes on tested and untested memory. **/ -EFI_STATUS +VOID EFIAPI -RegisterPageAccessAttributesUpdateOnGcdSyncComplete ( - VOID +InitializePageAttributesCallback ( + IN EFI_EVENT Event, + IN VOID *Context ); #endif