UINT16 Magic;\r
UINT32 SectionHeaderOffset;\r
UINT32 Index;\r
+ UINT32 HeaderWithoutDataDir;\r
CHAR8 BufferData;\r
UINTN NumberOfSections;\r
EFI_IMAGE_SECTION_HEADER SectionHeader;\r
\r
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
- // 1. Check FileHeader.SizeOfOptionalHeader filed.\r
+ // 1. Check OptionalHeader.NumberOfRvaAndSizes filed.\r
//\r
if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {\r
ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
}\r
\r
//\r
- // 2. Check the OptionalHeader.SizeOfHeaders field.\r
- // This field will be use like the following mode, so just compare the result.\r
- // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.\r
+ // 2. Check the FileHeader.SizeOfOptionalHeader field.\r
+ // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so \r
+ // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow.\r
//\r
- if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1 < Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes) {\r
- if (Hdr.Pe32->OptionalHeader.SizeOfHeaders < (UINT32)((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) &Hdr)) {\r
- ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
- return RETURN_UNSUPPORTED;\r
- }\r
+ HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER32) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
+ if (((UINT32)Hdr.Pe32->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=\r
+ Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader;\r
+ //\r
+ // 3. Check the FileHeader.NumberOfSections field.\r
+ //\r
+ if ((Hdr.Pe32->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
}\r
\r
//\r
- // 2.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file.\r
+ // 4. Check the OptionalHeader.SizeOfHeaders field.\r
+ //\r
+ if ((Hdr.Pe32->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // 4.2 Read last byte of Hdr.Pe32.OptionalHeader.SizeOfHeaders from the file.\r
//\r
Size = 1;\r
ReadSize = Size;\r
\r
} else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
//\r
- // 1. Check FileHeader.SizeOfOptionalHeader filed.\r
+ // 1. Check FileHeader.NumberOfRvaAndSizes filed.\r
//\r
if (EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {\r
ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
return RETURN_UNSUPPORTED;\r
}\r
+ //\r
+ // 2. Check the FileHeader.SizeOfOptionalHeader field.\r
+ // OptionalHeader.NumberOfRvaAndSizes is not bigger than 16, so \r
+ // OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY) will not overflow.\r
+ //\r
+ HeaderWithoutDataDir = sizeof (EFI_IMAGE_OPTIONAL_HEADER64) - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
+ if (((UINT32)Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=\r
+ Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
\r
+ SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + Hdr.Pe32Plus->FileHeader.SizeOfOptionalHeader;\r
//\r
- // 2. Check the OptionalHeader.SizeOfHeaders field.\r
- // This field will be use like the following mode, so just compare the result.\r
- // The DataDirectory array begin with 1, not 0, so here use < to compare not <=.\r
+ // 3. Check the FileHeader.NumberOfSections field.\r
//\r
- if (EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1 < Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes) {\r
- if (Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders < (UINT32)((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) &Hdr)) {\r
- ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
- return RETURN_UNSUPPORTED;\r
- }\r
+ if ((Hdr.Pe32Plus->OptionalHeader.SizeOfImage - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <= Hdr.Pe32Plus->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // 4. Check the OptionalHeader.SizeOfHeaders field.\r
+ //\r
+ if ((Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)Hdr.Pe32Plus->FileHeader.NumberOfSections) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
}\r
\r
//\r
- // 2.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file.\r
+ // 4.2 Read last byte of Hdr.Pe32Plus.OptionalHeader.SizeOfHeaders from the file.\r
//\r
Size = 1;\r
ReadSize = Size;\r
}\r
\r
if (SectionHeader.SizeOfRawData > 0) {\r
+ //\r
+ // Section data should bigger than the Pe header.\r
+ //\r
+ if (SectionHeader.VirtualAddress < ImageContext->SizeOfHeaders || \r
+ SectionHeader.PointerToRawData < ImageContext->SizeOfHeaders) {\r
+ ImageContext->ImageError = IMAGE_ERROR_UNSUPPORTED;\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
//\r
// Check the member data to avoid overflow.\r
//\r
while (RelocBase < RelocBaseEnd) {\r
\r
Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
- RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
- \r
//\r
- // Make sure RelocEnd is in the Image range.\r
+ // Add check for RelocBase->SizeOfBlock field.\r
//\r
- if ((CHAR8 *) RelocEnd < (CHAR8 *)((UINTN) ImageContext->ImageAddress) ||\r
- (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + (UINTN)ImageContext->ImageSize)) {\r
+ if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) {\r
ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
return RETURN_LOAD_ERROR;\r
}\r
\r
+ RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
+\r
if (!(ImageContext->IsTeImage)) {\r
FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
if (FixupBase == NULL) {\r
FixupData = FixupData + sizeof (UINT64);\r
break;\r
\r
- case EFI_IMAGE_REL_BASED_HIGHADJ:\r
- //\r
- // Not valid Relocation type for UEFI image, ASSERT\r
- //\r
- ASSERT (FALSE);\r
- break;\r
-\r
default:\r
//\r
// Only Itanium requires ConvertPeImage_Ex\r