ArmPkg/UncachedMemoryAllocationLib: set XP bit via CPU arch protocol

Commit e7b24ec978 ("ArmPkg/UncachedMemoryAllocationLib: map uncached
allocations non-executable") adds code that manipulates the GCD memory
space attributes of a newly allocated uncached region without checking
whether this region expose these attributes in its capabilities mask.

Given that the intent is to remove executable permissions from the region,
this is a fairly pointless exercise to begin with, regardless of whether
it is correct or not. The reason is that RO/XP memory attributes in the
GCD memory space map or the UEFI memory map are completely disconnected
from the actual mapping permissions used in the page tables.

So instead, invoke the CPU arch protocol directly, and add the non-exec
attributes in the page tables directly.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
This commit is contained in:
Ard Biesheuvel
2017-03-14 19:52:11 +00:00
parent 7e1bc8cdb3
commit 0985beff2c
2 changed files with 42 additions and 8 deletions

View File

@ -27,6 +27,10 @@
#include <Library/DxeServicesTableLib.h> #include <Library/DxeServicesTableLib.h>
#include <Library/CacheMaintenanceLib.h> #include <Library/CacheMaintenanceLib.h>
#include <Protocol/Cpu.h>
STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
VOID * VOID *
UncachedInternalAllocatePages ( UncachedInternalAllocatePages (
IN EFI_MEMORY_TYPE MemoryType, IN EFI_MEMORY_TYPE MemoryType,
@ -150,15 +154,25 @@ AllocatePagesFromList (
Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor); Status = gDS->GetMemorySpaceDescriptor (Memory, &Descriptor);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePages (Memory, Pages); goto FreePages;
return Status;
} }
Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages), Status = gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pages),
EFI_MEMORY_WC | EFI_MEMORY_XP); EFI_MEMORY_WC);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->FreePages (Memory, Pages); goto FreePages;
return Status; }
//
// EFI_CPU_ARCH_PROTOCOL::SetMemoryAttributes() will preserve the original
// memory type attribute if no memory type is passed. Permission attributes
// will be replaced, so EFI_MEMORY_RO will be removed if present (although
// it would be a bug if that were the case for an AllocatePages() allocation)
//
Status = mCpu->SetMemoryAttributes (mCpu, Memory, EFI_PAGES_TO_SIZE (Pages),
EFI_MEMORY_XP);
if (EFI_ERROR (Status)) {
goto FreePages;
} }
InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Pages)); InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Pages));
@ -166,8 +180,8 @@ AllocatePagesFromList (
NewNode = AllocatePool (sizeof (FREE_PAGE_NODE)); NewNode = AllocatePool (sizeof (FREE_PAGE_NODE));
if (NewNode == NULL) { if (NewNode == NULL) {
ASSERT (FALSE); ASSERT (FALSE);
gBS->FreePages (Memory, Pages); Status = EFI_OUT_OF_RESOURCES;
return EFI_OUT_OF_RESOURCES; goto FreePages;
} }
NewNode->Base = Memory; NewNode->Base = Memory;
@ -181,6 +195,10 @@ AllocatePagesFromList (
*Allocation = NewNode->Allocation; *Allocation = NewNode->Allocation;
return EFI_SUCCESS; return EFI_SUCCESS;
FreePages:
gBS->FreePages (Memory, Pages);
return Status;
} }
/** /**
@ -236,6 +254,16 @@ FreePagesFromList (
* This function is not responsible to free allocated buffer (eg: case of memory leak, * This function is not responsible to free allocated buffer (eg: case of memory leak,
* runtime allocation). * runtime allocation).
*/ */
EFI_STATUS
EFIAPI
UncachedMemoryAllocationLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
}
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
UncachedMemoryAllocationLibDestructor ( UncachedMemoryAllocationLibDestructor (

View File

@ -22,7 +22,7 @@
MODULE_TYPE = DXE_DRIVER MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0 VERSION_STRING = 1.0
LIBRARY_CLASS = UncachedMemoryAllocationLib LIBRARY_CLASS = UncachedMemoryAllocationLib
CONSTRUCTOR = UncachedMemoryAllocationLibConstructor
DESTRUCTOR = UncachedMemoryAllocationLibDestructor DESTRUCTOR = UncachedMemoryAllocationLibDestructor
[Sources.common] [Sources.common]
@ -42,3 +42,9 @@
[Pcd] [Pcd]
gArmTokenSpaceGuid.PcdArmFreeUncachedMemorySizeThreshold gArmTokenSpaceGuid.PcdArmFreeUncachedMemorySizeThreshold
[Protocols]
gEfiCpuArchProtocolGuid
[Depex]
gEfiCpuArchProtocolGuid