diff options
Diffstat (limited to 'MdeModulePkg')
-rw-r--r-- | MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c | 241 |
1 files changed, 28 insertions, 213 deletions
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c index eb243a0..2c069cc 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c @@ -281,80 +281,43 @@ SetUefiImageProtectionAttributes ( }
/**
- Return if the PE image section is aligned.
+ Return the section alignment requirement for the PE image section type.
- @param[in] SectionAlignment PE/COFF section alignment
- @param[in] MemoryType PE/COFF image memory type
+ @param[in] MemoryType PE/COFF image memory type
+
+ @retval The required section alignment for this memory type
- @retval TRUE The PE image section is aligned.
- @retval FALSE The PE image section is not aligned.
**/
-BOOLEAN
-IsMemoryProtectionSectionAligned (
- IN UINT32 SectionAlignment,
+STATIC
+UINT32
+GetMemoryProtectionSectionAlignment (
IN EFI_MEMORY_TYPE MemoryType
)
{
- UINT32 PageAlignment;
+ UINT32 SectionAlignment;
switch (MemoryType) {
case EfiRuntimeServicesCode:
case EfiACPIMemoryNVS:
case EfiReservedMemoryType:
- PageAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
break;
case EfiRuntimeServicesData:
ASSERT (FALSE);
- PageAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
+ SectionAlignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
break;
case EfiBootServicesCode:
case EfiLoaderCode:
- PageAlignment = EFI_PAGE_SIZE;
+ SectionAlignment = EFI_PAGE_SIZE;
break;
case EfiACPIReclaimMemory:
default:
ASSERT (FALSE);
- PageAlignment = EFI_PAGE_SIZE;
+ SectionAlignment = EFI_PAGE_SIZE;
break;
}
- if ((SectionAlignment & (PageAlignment - 1)) != 0) {
- return FALSE;
- } else {
- return TRUE;
- }
-}
-
-/**
- Free Image record.
-
- @param[in] ImageRecord A UEFI image record
-**/
-VOID
-FreeImageRecord (
- IN IMAGE_PROPERTIES_RECORD *ImageRecord
- )
-{
- LIST_ENTRY *CodeSegmentListHead;
- IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
-
- CodeSegmentListHead = &ImageRecord->CodeSegmentList;
- while (!IsListEmpty (CodeSegmentListHead)) {
- ImageRecordCodeSection = CR (
- CodeSegmentListHead->ForwardLink,
- IMAGE_PROPERTIES_RECORD_CODE_SECTION,
- Link,
- IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
- );
- RemoveEntryList (&ImageRecordCodeSection->Link);
- FreePool (ImageRecordCodeSection);
- }
-
- if (ImageRecord->Link.ForwardLink != NULL) {
- RemoveEntryList (&ImageRecord->Link);
- }
-
- FreePool (ImageRecord);
+ return SectionAlignment;
}
/**
@@ -369,19 +332,10 @@ ProtectUefiImage ( IN EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath
)
{
- VOID *ImageAddress;
- EFI_IMAGE_DOS_HEADER *DosHdr;
- UINT32 PeCoffHeaderOffset;
- UINT32 SectionAlignment;
- EFI_IMAGE_SECTION_HEADER *Section;
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
- UINT8 *Name;
- UINTN Index;
- IMAGE_PROPERTIES_RECORD *ImageRecord;
- CHAR8 *PdbPointer;
- IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
- BOOLEAN IsAligned;
- UINT32 ProtectionPolicy;
+ IMAGE_PROPERTIES_RECORD *ImageRecord;
+ UINT32 ProtectionPolicy;
+ EFI_STATUS Status;
+ UINT32 RequiredAlignment;
DEBUG ((DEBUG_INFO, "ProtectUefiImageCommon - 0x%x\n", LoadedImage));
DEBUG ((DEBUG_INFO, " - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase, LoadedImage->ImageSize));
@@ -406,161 +360,22 @@ ProtectUefiImage ( return;
}
- ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
-
- //
- // Step 1: record whole region
- //
- ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImage->ImageBase;
- ImageRecord->ImageSize = LoadedImage->ImageSize;
-
- ImageAddress = LoadedImage->ImageBase;
-
- PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
- if (PdbPointer != NULL) {
- DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));
- }
-
- //
- // Check PE/COFF image
- //
- DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
- PeCoffHeaderOffset = 0;
- if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
- PeCoffHeaderOffset = DosHdr->e_lfanew;
- }
+ RequiredAlignment = GetMemoryProtectionSectionAlignment (LoadedImage->ImageCodeType);
- Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
- if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
- DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
- // It might be image in SMM.
- goto Finish;
- }
-
- //
- // Get SectionAlignment
- //
- if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
- SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
- } else {
- SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
- }
-
- IsAligned = IsMemoryProtectionSectionAligned (SectionAlignment, LoadedImage->ImageCodeType);
- if (!IsAligned) {
- DEBUG ((
- DEBUG_VERBOSE,
- "!!!!!!!! ProtectUefiImageCommon - Section Alignment(0x%x) is incorrect !!!!!!!!\n",
- SectionAlignment
- ));
- PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
- if (PdbPointer != NULL) {
- DEBUG ((DEBUG_VERBOSE, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
- }
-
- goto Finish;
- }
-
- Section = (EFI_IMAGE_SECTION_HEADER *)(
- (UINT8 *)(UINTN)ImageAddress +
- PeCoffHeaderOffset +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
- Hdr.Pe32->FileHeader.SizeOfOptionalHeader
- );
- ImageRecord->CodeSegmentCount = 0;
- InitializeListHead (&ImageRecord->CodeSegmentList);
- for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
- Name = Section[Index].Name;
- DEBUG ((
- DEBUG_VERBOSE,
- " Section - '%c%c%c%c%c%c%c%c'\n",
- Name[0],
- Name[1],
- Name[2],
- Name[3],
- Name[4],
- Name[5],
- Name[6],
- Name[7]
- ));
-
- //
- // Instead of assuming that a PE/COFF section of type EFI_IMAGE_SCN_CNT_CODE
- // can always be mapped read-only, classify a section as a code section only
- // if it has the executable attribute set and the writable attribute cleared.
- //
- // This adheres more closely to the PE/COFF spec, and avoids issues with
- // Linux OS loaders that may consist of a single read/write/execute section.
- //
- if ((Section[Index].Characteristics & (EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_EXECUTE)) == EFI_IMAGE_SCN_MEM_EXECUTE) {
- DEBUG ((DEBUG_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));
- DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));
- DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));
- DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));
- DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
- DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
- DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));
- DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));
- DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));
-
- //
- // Step 2: record code section
- //
- ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
- if (ImageRecordCodeSection == NULL) {
- return;
- }
-
- ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
-
- ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
- ImageRecordCodeSection->CodeSegmentSize = ALIGN_VALUE (Section[Index].SizeOfRawData, SectionAlignment);
-
- DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
-
- InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
- ImageRecord->CodeSegmentCount++;
- }
- }
-
- if (ImageRecord->CodeSegmentCount == 0) {
- //
- // If a UEFI executable consists of a single read+write+exec PE/COFF
- // section, that isn't actually an error. The image can be launched
- // alright, only image protection cannot be applied to it fully.
- //
- // One example that elicits this is (some) Linux kernels (with the EFI stub
- // of course).
- //
- DEBUG ((DEBUG_WARN, "!!!!!!!! ProtectUefiImageCommon - CodeSegmentCount is 0 !!!!!!!!\n"));
- PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
- if (PdbPointer != NULL) {
- DEBUG ((DEBUG_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
- }
-
- goto Finish;
- }
+ Status = CreateImagePropertiesRecord (
+ LoadedImage->ImageBase,
+ LoadedImage->ImageSize,
+ &RequiredAlignment,
+ ImageRecord
+ );
- //
- // Final
- //
- SortImageRecordCodeSection (ImageRecord);
- //
- // Check overlap all section in ImageBase/Size
- //
- if (!IsImageRecordCodeSectionValid (ImageRecord)) {
- DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
+ FreePool (ImageRecord);
goto Finish;
}
//
- // Round up the ImageSize, some CPU arch may return EFI_UNSUPPORTED if ImageSize is not aligned.
- // Given that the loader always allocates full pages, we know the space after the image is not used.
- //
- ImageRecord->ImageSize = ALIGN_VALUE (LoadedImage->ImageSize, EFI_PAGE_SIZE);
-
- //
// CPU ARCH present. Update memory attribute directly.
//
SetUefiImageProtectionAttributes (ImageRecord);
@@ -607,7 +422,7 @@ UnprotectUefiImage ( ImageRecord->ImageSize,
0
);
- FreeImageRecord (ImageRecord);
+ DeleteImagePropertiesRecord (ImageRecord);
return;
}
}
|