MdeModulePkg/DxeCore: Ensure FfsFileHeader 8 bytes aligned

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=864
REF: CVE-2018-3630

To follow PI spec, ensure FfsFileHeader 8 bytes aligned.

For the integrity of FV(especially non-MemoryMapped FV) layout,
let CachedFv point to FV beginning, but not (FV + FV header).

And current code only handles (FwVolHeader->ExtHeaderOffset != 0) path,
update code to also handle (FwVolHeader->ExtHeaderOffset == 0) path.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
This commit is contained in:
Star Zeng 2018-01-05 13:46:22 +08:00 committed by Jian J Wang
parent 467e1ffa76
commit 9aef515648
1 changed files with 14 additions and 51 deletions

View File

@ -3,7 +3,7 @@
Layers on top of Firmware Block protocol to produce a file abstraction Layers on top of Firmware Block protocol to produce a file abstraction
of FV based files. of FV based files.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -329,8 +329,6 @@ FvCheck (
FFS_FILE_LIST_ENTRY *FfsFileEntry; FFS_FILE_LIST_ENTRY *FfsFileEntry;
EFI_FFS_FILE_HEADER *FfsHeader; EFI_FFS_FILE_HEADER *FfsHeader;
UINT8 *CacheLocation; UINT8 *CacheLocation;
UINTN LbaOffset;
UINTN HeaderSize;
UINTN Index; UINTN Index;
EFI_LBA LbaIndex; EFI_LBA LbaIndex;
UINTN Size; UINTN Size;
@ -353,11 +351,7 @@ FvCheck (
return Status; return Status;
} }
// Size = (UINTN) FwVolHeader->FvLength;
// Size is the size of the FV minus the head. We have already allocated
// the header to check to make sure the volume is valid
//
Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);
if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
FvDevice->IsMemoryMapped = TRUE; FvDevice->IsMemoryMapped = TRUE;
@ -369,7 +363,7 @@ FvCheck (
// //
// Don't cache memory mapped FV really. // Don't cache memory mapped FV really.
// //
FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength); FvDevice->CachedFv = (UINT8 *) (UINTN) PhysicalAddress;
} else { } else {
FvDevice->IsMemoryMapped = FALSE; FvDevice->IsMemoryMapped = FALSE;
FvDevice->CachedFv = AllocatePool (Size); FvDevice->CachedFv = AllocatePool (Size);
@ -380,52 +374,27 @@ FvCheck (
} }
// //
// Remember a pointer to the end fo the CachedFv // Remember a pointer to the end of the CachedFv
// //
FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;
if (!FvDevice->IsMemoryMapped) { if (!FvDevice->IsMemoryMapped) {
// //
// Copy FV minus header into memory using the block map we have all ready // Copy FV into memory using the block map.
// read into memory.
// //
BlockMap = FwVolHeader->BlockMap; BlockMap = FwVolHeader->BlockMap;
CacheLocation = FvDevice->CachedFv; CacheLocation = FvDevice->CachedFv;
LbaIndex = 0; LbaIndex = 0;
LbaOffset = 0;
HeaderSize = FwVolHeader->HeaderLength;
while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) { while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
Index = 0;
Size = BlockMap->Length;
if (HeaderSize > 0) {
//
// Skip header size
//
for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {
HeaderSize -= BlockMap->Length;
LbaIndex ++;
}
//
// Check whether FvHeader is crossing the multi block range.
//
if (Index >= BlockMap->NumBlocks) {
BlockMap++;
continue;
} else if (HeaderSize > 0) {
LbaOffset = HeaderSize;
Size = BlockMap->Length - HeaderSize;
HeaderSize = 0;
}
}
// //
// read the FV data // read the FV data
// //
for (; Index < BlockMap->NumBlocks; Index ++) { Size = BlockMap->Length;
Status = Fvb->Read (Fvb, for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
Status = Fvb->Read (
Fvb,
LbaIndex, LbaIndex,
LbaOffset, 0,
&Size, &Size,
CacheLocation CacheLocation
); );
@ -438,13 +407,7 @@ FvCheck (
} }
LbaIndex++; LbaIndex++;
CacheLocation += Size; CacheLocation += BlockMap->Length;
//
// After we skip Fv Header always read from start of block
//
LbaOffset = 0;
Size = BlockMap->Length;
} }
BlockMap++; BlockMap++;
@ -475,12 +438,12 @@ FvCheck (
// //
// Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists. // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
// //
FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + (FwVolHeader->ExtHeaderOffset - FwVolHeader->HeaderLength)); FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (FvDevice->CachedFv + FwVolHeader->ExtHeaderOffset);
FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize); FfsHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize);
FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);
} else { } else {
FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv); FfsHeader = (EFI_FFS_FILE_HEADER *) (FvDevice->CachedFv + FwVolHeader->HeaderLength);
} }
FfsHeader = (EFI_FFS_FILE_HEADER *) ALIGN_POINTER (FfsHeader, 8);
TopFvAddress = FvDevice->EndOfCachedFv; TopFvAddress = FvDevice->EndOfCachedFv;
while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) { while (((UINTN) FfsHeader >= (UINTN) FvDevice->CachedFv) && ((UINTN) FfsHeader <= (UINTN) ((UINTN) TopFvAddress - sizeof (EFI_FFS_FILE_HEADER)))) {