MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore (CVE-2019-11098)

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614

Introduces new changes to PeiCore to move the contents of temporary
RAM visible to the PeiCore to permanent memory. This expands on
pre-existing shadowing support in the PeiCore to perform the following
additional actions:

 1. Migrate pointers in PPIs installed in PeiCore to the permanent
    memory copy of PeiCore.

 2. Copy all installed firmware volumes to permanent memory.

 3. Relocate and fix up the PEIMs within the firmware volumes.

 4. Convert all PPIs into the migrated firmware volume to the corresponding
    PPI address in the permanent memory location.

    This applies to PPIs and PEI notifications.

 5. Convert all status code callbacks in the migrated firmware volume to
    the corresponding address in the permanent memory location.

 6. Update the FV HOB to the corresponding firmware volume in permanent
    memory.

 7. Use PcdMigrateTemporaryRamFirmwareVolumes to control if enable the
    feature or not. when disable the PCD, the EvacuateTempRam() will
    never be called.

The function control flow as below:
  PeiCore()
    DumpPpiList()
    EvacuateTempRam()
      ConvertPeiCorePpiPointers()
        ConvertPpiPointersFv()
      MigratePeimsInFv()
        MigratePeim()
          PeiGetPe32Data()
          LoadAndRelocatePeCoffImageInPlace()
      MigrateSecModulesInFv()
      ConvertPpiPointersFv()
      ConvertStatusCodeCallbacks()
      ConvertFvHob()
      RemoveFvHobsInTemporaryMemory()
    DumpPpiList()

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Debkumar De <debkumar.de@intel.com>
Cc: Harry Han <harry.han@intel.com>
Cc: Catharine West <catharine.west@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Michael Kubacki
2019-04-12 06:46:02 +08:00
committed by mergify[bot]
parent 1facb8fdef
commit 9bedaec05b
7 changed files with 1099 additions and 9 deletions

View File

@@ -198,6 +198,227 @@ ConvertPpiPointers (
}
}
/**
Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
@param PrivateData Pointer to PeiCore's private data structure.
@param OrgFvHandle Address of FV Handle in temporary memory.
@param FvHandle Address of FV Handle in permanent memory.
@param FvSize Size of the FV.
**/
VOID
ConvertPpiPointersFv (
IN PEI_CORE_INSTANCE *PrivateData,
IN UINTN OrgFvHandle,
IN UINTN FvHandle,
IN UINTN FvSize
)
{
UINT8 Index;
UINTN Offset;
BOOLEAN OffsetPositive;
EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
UINT8 GuidIndex;
EFI_GUID *Guid;
EFI_GUID *GuidCheckList[2];
GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;
GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;
if (FvHandle > OrgFvHandle) {
OffsetPositive = TRUE;
Offset = FvHandle - OrgFvHandle;
} else {
OffsetPositive = FALSE;
Offset = OrgFvHandle - FvHandle;
}
DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));
DEBUG ((
DEBUG_VERBOSE,
" OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
(UINTN) OrgFvHandle,
(UINTN) FvHandle,
FvSize
));
DEBUG ((
DEBUG_VERBOSE,
" OrgFvHandle range: 0x%08x - 0x%08x\n",
OrgFvHandle,
OrgFvHandle + FvSize
));
for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
ConvertPointer (
(VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
}
for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
ConvertPointer (
(VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
}
for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
ConvertPointer (
(VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
ConvertPointer (
(VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;
for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {
//
// Don't use CompareGuid function here for performance reasons.
// Instead we compare the GUID as INT32 at a time and branch
// on the first failed comparison.
//
if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&
(((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&
(((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&
(((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {
FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;
DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));
if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {
ConvertPointer (
(VOID **)&FvInfoPpi->FvInfo,
OrgFvHandle,
OrgFvHandle + FvSize,
Offset,
OffsetPositive
);
DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));
}
DEBUG ((DEBUG_VERBOSE, "\n"));
break;
}
}
}
}
/**
Dumps the PPI lists to debug output.
@param PrivateData Points to PeiCore's private instance data.
**/
VOID
DumpPpiList (
IN PEI_CORE_INSTANCE *PrivateData
)
{
DEBUG_CODE_BEGIN ();
UINTN Index;
if (PrivateData == NULL) {
return;
}
for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
DEBUG ((
DEBUG_VERBOSE,
"CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
Index,
PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
(UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
(
!(
((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
(((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
)
? "CAR" : "Post-Memory"
)
));
}
for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
DEBUG ((DEBUG_VERBOSE,
"DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
Index,
PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
(UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
(
!(
((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&
(((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
)
? "CAR" : "Post-Memory"
)
));
}
for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
DEBUG ((DEBUG_VERBOSE,
"PPI[%2d] {%g} at 0x%x (%a)\n",
Index,
PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
(UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
(
!(
((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
(((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
)
? "CAR" : "Post-Memory"
)
));
}
DEBUG_CODE_END ();
}
/**
This function installs an interface in the PEI PPI database by GUID.
@@ -830,3 +1051,68 @@ ProcessPpiListFromSec (
}
}
/**
Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
@param PrivateData Pointer to PeiCore's private data structure.
@param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
**/
VOID
ConvertPeiCorePpiPointers (
IN PEI_CORE_INSTANCE *PrivateData,
PEI_CORE_FV_HANDLE CoreFvHandle
)
{
EFI_FV_FILE_INFO FileInfo;
EFI_PHYSICAL_ADDRESS OrgImageBase;
EFI_PHYSICAL_ADDRESS MigratedImageBase;
UINTN PeiCoreModuleSize;
EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
VOID *PeiCoreImageBase;
VOID *PeiCoreEntryPoint;
EFI_STATUS Status;
PeiCoreFileHandle = NULL;
//
// Find the PEI Core in the BFV in temporary memory.
//
Status = CoreFvHandle.FvPpi->FindFileByType (
CoreFvHandle.FvPpi,
EFI_FV_FILETYPE_PEI_CORE,
CoreFvHandle.FvHandle,
&PeiCoreFileHandle
);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo);
ASSERT_EFI_ERROR (Status);
Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
ASSERT_EFI_ERROR (Status);
//
// Find PEI Core EntryPoint in the BFV in temporary memory.
//
Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint);
ASSERT_EFI_ERROR (Status);
OrgImageBase = (UINTN) PeiCoreImageBase;
MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);
//
// Size of loaded PEI_CORE in permanent memory.
//
PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);
//
// Migrate PEI_CORE PPI pointers from temporary memory to newly
// installed PEI_CORE in permanent memory.
//
ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);
}
}