Ring3: Split Page Table template construction and initialization,

removed ChangeUefiImageRing(), added GetUefiImageRecord().
This commit is contained in:
Mikhail Krichanov 2024-11-27 13:51:07 +03:00
parent cd3da4b9ff
commit 285c6b0de9
6 changed files with 173 additions and 97 deletions

View File

@ -289,8 +289,6 @@ extern VOID *gCoreSysCallStackTop;
extern VOID *gRing3CallStackBase;
extern VOID *gRing3CallStackTop;
extern VOID *gRing3EntryPoint;
extern VOID *gUserPageTableTemplate;
extern UINTN gUserPageTableTemplateSize;
extern UINTN gUserPageTable;
extern UINTN gCorePageTable;
@ -2650,18 +2648,9 @@ UnprotectUefiImage (
IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
);
/**
Change UEFI image owner: Supervisor / Privileged or User / Unprivileged.
@param[in] LoadedImage The loaded image protocol
@param[in] LoadedImageDevicePath The loaded image device path protocol
@param[in] IsUser Whether UEFI image record is User Image.
**/
VOID
ChangeUefiImageRing (
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath,
IN BOOLEAN IsUser
UEFI_IMAGE_RECORD *
GetUefiImageRecord (
IN LOADED_IMAGE_PRIVATE_DATA *Image
);
/**
@ -2728,6 +2717,18 @@ SetUefiImageMemoryAttributes (
IN UINT64 Attributes
);
/**
Set UEFI image protection attributes.
@param[in] ImageRecord A UEFI image record
@param[in] IsUser Whether UEFI image record is User Image.
**/
VOID
SetUefiImageProtectionAttributes (
IN UEFI_IMAGE_RECORD *ImageRecord,
IN BOOLEAN IsUser
);
EFI_STATUS
EFIAPI
CoreBootServices (
@ -2782,10 +2783,10 @@ FreeProtocolsList (
VOID
);
VOID
UINTN
EFIAPI
MakeUserPageTableTemplate (
VOID
InitializeUserPageTable (
IN LOADED_IMAGE_PRIVATE_DATA *Image
);
#endif

View File

@ -246,7 +246,7 @@ DxeMain (
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
gRing3Data = NULL;
//
// Setup Stack Guard
//
@ -328,8 +328,6 @@ DxeMain (
ProtectUefiImage (&mCurrentImage->Info, UefiImageOriginFv, &ImageContext, mCurrentImage->IsUserImage);
MakeUserPageTableTemplate ();
//
// Call constructor for all libraries
//

View File

@ -1108,7 +1108,6 @@ CoreLoadImageCommon (
UEFI_IMAGE_LOADER_IMAGE_CONTEXT ImageContext;
UINT8 ImageOrigin;
EFI_FV_FILE_ATTRIBUTES FileAttributes;
VOID *UserPageTable;
SecurityStatus = EFI_SUCCESS;
@ -1349,14 +1348,6 @@ CoreLoadImageCommon (
Image->Info.ParentHandle = ParentImageHandle;
Image->IsUserImage = (FileAttributes & EFI_FV_FILE_ATTRIB_USER) != 0;
if ((gRing3Data != NULL) && Image->IsUserImage) {
UserPageTable = AllocatePages (EFI_SIZE_TO_PAGES (gUserPageTableTemplateSize));
CopyMem (UserPageTable, gUserPageTableTemplate, gUserPageTableTemplateSize);
Image->UserPageTable = (UINTN)UserPageTable;
gUserPageTable = Image->UserPageTable;
}
if (NumberOfPages != NULL) {
Image->NumberOfPages = *NumberOfPages;
} else {
@ -1453,6 +1444,11 @@ CoreLoadImageCommon (
Status = EFI_SUCCESS;
ProtectUefiImage (&Image->Info, ImageOrigin, &ImageContext, Image->IsUserImage);
if ((gRing3Data != NULL) && Image->IsUserImage) {
Image->UserPageTable = InitializeUserPageTable (Image);
gUserPageTable = Image->UserPageTable;
}
RegisterMemoryProfileImage (
Image->LoadedImageDevicePath,
(UefiImageGetSubsystem (&ImageContext) == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER),

View File

@ -82,10 +82,6 @@ SetUefiImageMemoryAttributes (
ASSERT (gCpu != NULL);
gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes);
if ((Attributes & EFI_MEMORY_USER) != 0) {
gCpu->SetUserMemoryAttributes (gCpu, gUserPageTable, BaseAddress, Length, FinalAttributes);
}
}
/**
@ -291,22 +287,13 @@ UnprotectUefiImage (
}
}
/**
Change UEFI image owner: Supervisor / Privileged or User / Unprivileged.
@param[in] LoadedImage The loaded image protocol
@param[in] LoadedImageDevicePath The loaded image device path protocol
@param[in] IsUser Whether UEFI image record is User Image.
**/
VOID
ChangeUefiImageRing (
IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath,
IN BOOLEAN IsUser
UEFI_IMAGE_RECORD *
GetUefiImageRecord (
IN LOADED_IMAGE_PRIVATE_DATA *Image
)
{
UEFI_IMAGE_RECORD *ImageRecord;
LIST_ENTRY *ImageRecordLink;
UEFI_IMAGE_RECORD *ImageRecord;
LIST_ENTRY *ImageRecordLink;
for (ImageRecordLink = mProtectedImageRecordList.ForwardLink;
ImageRecordLink != &mProtectedImageRecordList;
@ -319,14 +306,12 @@ ChangeUefiImageRing (
UEFI_IMAGE_RECORD_SIGNATURE
);
if (ImageRecord->StartAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase) {
ASSERT (gCpu != NULL);
SetUefiImageProtectionAttributes (ImageRecord, IsUser);
return;
if (ImageRecord->StartAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)Image->Info.ImageBase) {
return ImageRecord;
}
}
return NULL;
}
/**

View File

@ -18,6 +18,17 @@ RING3_DATA *gRing3Data;
VOID *gRing3Interfaces;
UINTN gUartBaseAddress;
UEFI_IMAGE_RECORD *mDxeRing3;
VOID *mUserPageTableTemplate;
UINTN mUserPageTableTemplateSize;
VOID
EFIAPI
MakeUserPageTableTemplate (
OUT VOID **UserPageTableTemplate,
OUT UINTN *UserPageTableTemplateSize
);
VOID
EFIAPI
InitializeMsr (
@ -102,11 +113,14 @@ InitializeRing3 (
//
// Initialize DxeRing3 with Supervisor privileges.
//
ChangeUefiImageRing (&Image->Info, Image->LoadedImageDevicePath, FALSE);
mDxeRing3 = GetUefiImageRecord (Image);
ASSERT (mDxeRing3 != NULL);
SetUefiImageProtectionAttributes (mDxeRing3, FALSE);
Status = Image->EntryPoint (ImageHandle, (EFI_SYSTEM_TABLE *)gRing3Data);
ChangeUefiImageRing (&Image->Info, Image->LoadedImageDevicePath, TRUE);
SetUefiImageProtectionAttributes (mDxeRing3, TRUE);
gRing3EntryPoint = gRing3Data->EntryPoint;
@ -153,9 +167,6 @@ InitializeRing3 (
gCoreSysCallStackTop = TopOfStack;
SetUefiImageMemoryAttributes ((UINTN)gCoreSysCallStackBase, SizeOfStack, EFI_MEMORY_XP);
//
// gCpu->SetUserMemoryAttributes (gCpu, gUserPageTable, (UINTN)gCoreSysCallStackBase, SizeOfStack, EFI_MEMORY_XP);
//
DEBUG ((DEBUG_ERROR, "Core: gCoreSysCallStackTop = %p\n", gCoreSysCallStackTop));
//
@ -180,5 +191,124 @@ InitializeRing3 (
gRing3Data->SystemTable.NumberOfTableEntries
);
MakeUserPageTableTemplate (&mUserPageTableTemplate, &mUserPageTableTemplateSize);
return Status;
}
UINTN
EFIAPI
InitializeUserPageTable (
IN LOADED_IMAGE_PRIVATE_DATA *Image
)
{
UINTN UserPageTable;
UEFI_IMAGE_RECORD_SEGMENT *ImageRecordSegment;
UINTN SectionAddress;
UINT32 Index;
UEFI_IMAGE_RECORD *UserImageRecord;
UserPageTable = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (mUserPageTableTemplateSize));
CopyMem ((VOID *)UserPageTable, mUserPageTableTemplate, mUserPageTableTemplateSize);
//
// Map gRing3Data, gRing3Interfaces, gRing3CallStackBase, DxeRing3
//
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
(UINTN)gRing3Data,
ALIGN_VALUE (sizeof (RING3_DATA), EFI_PAGE_SIZE),
EFI_MEMORY_XP | EFI_MEMORY_USER
);
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
(UINTN)gRing3Interfaces,
EFI_PAGES_TO_SIZE (RING3_INTERFACES_PAGES),
EFI_MEMORY_XP | EFI_MEMORY_USER
);
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
(UINTN)gRing3CallStackBase,
EFI_SIZE_TO_PAGES (USER_STACK_SIZE) * EFI_PAGE_SIZE,
EFI_MEMORY_XP | EFI_MEMORY_USER
);
SectionAddress = mDxeRing3->StartAddress;
for (Index = 0; Index < mDxeRing3->NumSegments; Index++) {
ImageRecordSegment = &mDxeRing3->Segments[Index];
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
SectionAddress,
ImageRecordSegment->Size,
ImageRecordSegment->Attributes | EFI_MEMORY_USER
);
SectionAddress += ImageRecordSegment->Size;
}
//
// Map CoreBootServices
//
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
(EFI_PHYSICAL_ADDRESS)(UINTN)CoreBootServices,
SIZE_4KB,
EFI_MEMORY_RO
);
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
(EFI_PHYSICAL_ADDRESS)(UINTN)&gCorePageTable,
SIZE_4KB,
EFI_MEMORY_RO | EFI_MEMORY_XP
);
//
// Map ExceptionHandlerAsm: AsmIdtVectorBegin - AsmGetTemplateAddressMap
// mCorePageTable, gCoreSysCallStackTop
//
// gCpu->SetUserMemoryAttributes (gCpu, (UINTN)PageMap, BaseAddress, SIZE_4KB, EFI_MEMORY_RO);
//
// gCpu->SetUserMemoryAttributes (gCpu, gUserPageTable, (UINTN)gCoreSysCallStackBase, SizeOfStack, EFI_MEMORY_XP);
//
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
FixedPcdGet32 (PcdOvmfWorkAreaBase),
FixedPcdGet32 (PcdOvmfWorkAreaSize),
EFI_MEMORY_XP | EFI_MEMORY_USER
);
//
// Map User Image
//
UserImageRecord = GetUefiImageRecord (Image);
ASSERT (UserImageRecord != NULL);
SectionAddress = UserImageRecord->StartAddress;
for (Index = 0; Index < UserImageRecord->NumSegments; Index++) {
ImageRecordSegment = &UserImageRecord->Segments[Index];
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
SectionAddress,
ImageRecordSegment->Size,
ImageRecordSegment->Attributes | EFI_MEMORY_USER
);
SectionAddress += ImageRecordSegment->Size;
}
return UserPageTable;
}

View File

@ -10,13 +10,11 @@
#include <Register/Intel/ArchitecturalMsr.h>
#include <IndustryStandard/PageTable.h>
VOID *gUserPageTableTemplate;
UINTN gUserPageTableTemplateSize;
VOID
EFIAPI
MakeUserPageTableTemplate (
VOID
OUT VOID **UserPageTableTemplate,
OUT UINTN *UserPageTableTemplateSize
)
{
EFI_HOB_GUID_TYPE *GuidHob;
@ -167,42 +165,10 @@ MakeUserPageTableTemplate (
ZeroMem (PageMapLevel5Entry, (512 - IndexOfPml5Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER));
}
gUserPageTableTemplate = (VOID *)PageMap;
gUserPageTableTemplateSize = ALIGN_VALUE (EFI_PAGES_TO_SIZE (PageTableInfo->TotalPagesNum), PAGE_TABLE_POOL_ALIGNMENT);
gUserPageTable = (UINTN)gUserPageTableTemplate;
*UserPageTableTemplate = (VOID *)PageMap;
*UserPageTableTemplateSize = ALIGN_VALUE (EFI_PAGES_TO_SIZE (PageTableInfo->TotalPagesNum), PAGE_TABLE_POOL_ALIGNMENT);
SetUefiImageMemoryAttributes ((UINT64)PageMap, gUserPageTableTemplateSize, EFI_MEMORY_XP);
//
// Map CoreBootServices
//
gCpu->SetUserMemoryAttributes (
gCpu,
(UINTN)PageMap,
(EFI_PHYSICAL_ADDRESS)(UINTN)CoreBootServices,
SIZE_4KB,
EFI_MEMORY_RO
);
gCpu->SetUserMemoryAttributes (
gCpu,
(UINTN)PageMap,
(EFI_PHYSICAL_ADDRESS)(UINTN)&gCorePageTable,
SIZE_4KB,
EFI_MEMORY_RO | EFI_MEMORY_XP
);
//
// Map ExceptionHandlerAsm: AsmIdtVectorBegin - AsmGetTemplateAddressMap
// mCorePageTable, gCoreSysCallStackTop
//
// gCpu->SetUserMemoryAttributes (gCpu, (UINTN)PageMap, BaseAddress, SIZE_4KB, EFI_MEMORY_RO);
gCpu->SetUserMemoryAttributes (
gCpu,
(UINTN)PageMap,
FixedPcdGet32 (PcdOvmfWorkAreaBase),
FixedPcdGet32 (PcdOvmfWorkAreaSize),
EFI_MEMORY_XP | EFI_MEMORY_USER
);
SetUefiImageMemoryAttributes ((UINT64)PageMap, *UserPageTableTemplateSize, EFI_MEMORY_XP);
}
VOID