Skip to content

Commit

Permalink
MdeModulePkg/PiSmmCore: MemoryAttributeTable need keep non-PE record.
Browse files Browse the repository at this point in the history
Current memory attribute table implementation will only mark PE code
to be EfiRuntimeServicesCode, and mark rest to be EfiRuntimeServicesData.

However, there might be a case that a SMM code wants to allocate
EfiRuntimeServicesCode explicitly to let page table protect this region
to be read only. It is unsupported.

This patch enhances the current solution so that MemoryAttributeTable
does not touch non PE image record.
Only the PE image region is forced to be EfiRuntimeServicesCode for
code and EfiRuntimeServicesData for data.

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
  • Loading branch information
jyao1 committed Dec 7, 2016
1 parent 5f4d3e1 commit 026e2ca
Showing 1 changed file with 51 additions and 40 deletions.
91 changes: 51 additions & 40 deletions MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
Expand Up @@ -268,15 +268,19 @@ EnforceMemoryMapAttribute (
MemoryMapEntry = MemoryMap;
MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
switch (MemoryMapEntry->Type) {
case EfiRuntimeServicesCode:
MemoryMapEntry->Attribute |= EFI_MEMORY_RO;
break;
case EfiRuntimeServicesData:
MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
break;
if (MemoryMapEntry->Attribute != 0) {
// It is PE image, the attribute is already set.
} else {
switch (MemoryMapEntry->Type) {
case EfiRuntimeServicesCode:
MemoryMapEntry->Attribute = EFI_MEMORY_RO;
break;
case EfiRuntimeServicesData:
default:
MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
break;
}
}

MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
}

Expand Down Expand Up @@ -358,6 +362,21 @@ SetNewRecord (
PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
NewRecordCount = 0;

//
// Always create a new entry for non-PE image record
//
if (ImageRecord->ImageBase > TempRecord.PhysicalStart) {
NewRecord->Type = TempRecord.Type;
NewRecord->PhysicalStart = TempRecord.PhysicalStart;
NewRecord->VirtualStart = 0;
NewRecord->NumberOfPages = EfiSizeToPages(ImageRecord->ImageBase - TempRecord.PhysicalStart);
NewRecord->Attribute = TempRecord.Attribute;
NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
NewRecordCount ++;
TempRecord.PhysicalStart = ImageRecord->ImageBase;
TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
}

ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;

ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
Expand Down Expand Up @@ -452,14 +471,10 @@ GetMaxSplitRecordCount (
if (ImageRecord == NULL) {
break;
}
SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 2);
PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
} while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));

if (SplitRecordCount != 0) {
SplitRecordCount--;
}

return SplitRecordCount;
}

Expand Down Expand Up @@ -516,28 +531,16 @@ SplitRecord (
//
// No more image covered by this range, stop
//
if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
if (PhysicalEnd > PhysicalStart) {
//
// If this is still address in this record, need record.
// Always create a new entry for non-PE image record
//
NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
if (NewRecord->Type == EfiRuntimeServicesData) {
//
// Last record is DATA, just merge it.
//
NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);
} else {
//
// Last record is CODE, create a new DATA entry.
//
NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
NewRecord->Type = EfiRuntimeServicesData;
NewRecord->PhysicalStart = TempRecord.PhysicalStart;
NewRecord->VirtualStart = 0;
NewRecord->NumberOfPages = TempRecord.NumberOfPages;
NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
TotalNewRecordCount ++;
}
NewRecord->Type = TempRecord.Type;
NewRecord->PhysicalStart = TempRecord.PhysicalStart;
NewRecord->VirtualStart = 0;
NewRecord->NumberOfPages = TempRecord.NumberOfPages;
NewRecord->Attribute = TempRecord.Attribute;
TotalNewRecordCount ++;
}
break;
}
Expand Down Expand Up @@ -580,19 +583,25 @@ SplitRecord (
==>
+---------------+
| Record X |
+---------------+
| Record RtCode |
+---------------+ ----
| Record RtData | |
+---------------+ |
| Record RtCode | |-> PE/COFF1
+---------------+ |
| Record RtData | |
+---------------+ ----
| Record RtCode |
+---------------+ ----
| Record RtData | |
+---------------+ |
| Record RtCode | |-> PE/COFF2
+---------------+ |
| Record RtData | |
+---------------+ ----
| Record RtCode |
+---------------+
| Record Y |
+---------------+
Expand Down Expand Up @@ -622,7 +631,7 @@ SplitTable (
UINTN TotalSplitRecordCount;
UINTN AdditionalRecordCount;

AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;

TotalSplitRecordCount = 0;
//
Expand All @@ -648,11 +657,13 @@ SplitTable (
//
// Adjust IndexNew according to real split.
//
CopyMem (
((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
RealSplitRecordCount * DescriptorSize
);
if (MaxSplitRecordCount != RealSplitRecordCount) {
CopyMem (
((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
(RealSplitRecordCount + 1) * DescriptorSize
);
}
IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
TotalSplitRecordCount += RealSplitRecordCount;
IndexNew --;
Expand Down Expand Up @@ -744,7 +755,7 @@ SmmCoreGetMemoryMapMemoryAttributesTable (
return EFI_INVALID_PARAMETER;
}

AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;

OldMemoryMapSize = *MemoryMapSize;
Status = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
Expand Down

0 comments on commit 026e2ca

Please sign in to comment.