UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h | 11 +- .../PayloadLoaderPeim/ElfLib/Elf32Lib.c | 38 ++-- .../PayloadLoaderPeim/ElfLib/Elf64Lib.c | 39 ++-- .../PayloadLoaderPeim/ElfLib/ElfLib.c | 210 +++++++++++++----- .../PayloadLoaderPeim/PayloadLoaderPeim.c | 6 +- 5 files changed, 188 insertions(+), 116 deletions(-)
More checks are added to verify ELF image.
ParseElfImage() is changed to InitializeElfContext()
Signed-off-by: Ray Ni <ray.ni@intel.com>
Cc: Marvin Häuser <mhaeuser@posteo.de>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
---
UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h | 11 +-
.../PayloadLoaderPeim/ElfLib/Elf32Lib.c | 38 ++--
.../PayloadLoaderPeim/ElfLib/Elf64Lib.c | 39 ++--
.../PayloadLoaderPeim/ElfLib/ElfLib.c | 210 +++++++++++++-----
.../PayloadLoaderPeim/PayloadLoaderPeim.c | 6 +-
5 files changed, 188 insertions(+), 116 deletions(-)
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h
index 9cfc2912cf..0ed93140a9 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h
+++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h
@@ -17,7 +17,6 @@
#define ELF_PT_LOAD 1
typedef struct {
- RETURN_STATUS ParseStatus; ///< Return the status after ParseElfImage().
UINT8 *FileBase; ///< The source location in memory.
UINTN FileSize; ///< The size including sections that don't require loading.
UINT8 *PreferredImageAddress; ///< The preferred image to be loaded. No relocation is needed if loaded to this address.
@@ -45,7 +44,10 @@ typedef struct {
/**
Parse the ELF image info.
- @param[in] ImageBase Memory address of an image.
+ On return, all fields in ElfCt are updated except ImageAddress.
+
+ @param[in] FileBase Memory address of an image.
+ @param[in] MaxFileSize The maximum file size.
@param[out] ElfCt The EFL image context pointer.
@retval EFI_INVALID_PARAMETER Input parameters are not valid.
@@ -55,8 +57,9 @@ typedef struct {
**/
EFI_STATUS
EFIAPI
-ParseElfImage (
- IN VOID *ImageBase,
+InitializeElfContext (
+ IN VOID *FileBase,
+ IN UINTN MaxFileSize,
OUT ELF_IMAGE_CONTEXT *ElfCt
);
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c
index 3fa100ce4a..79f4ce623b 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c
@@ -115,7 +115,7 @@ ProcessRelocation32 (
UINT32 Type;
for ( Index = 0
- ; RelaEntrySize * Index < RelaSize
+ ; Index < RelaSize / RelaEntrySize
; Index++, Rela = ELF_NEXT_ENTRY (Elf32_Rela, Rela, RelaEntrySize)
) {
//
@@ -137,7 +137,6 @@ ProcessRelocation32 (
// Dynamic section doesn't contain entries of this type.
//
DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type));
- ASSERT (FALSE);
} else {
*Ptr += (UINT32) Delta;
}
@@ -164,7 +163,6 @@ ProcessRelocation32 (
// Calculation: B + A
//
if (RelaType == SHT_RELA) {
- ASSERT (*Ptr == 0);
*Ptr = (UINT32) Delta + Rela->r_addend;
} else {
//
@@ -177,7 +175,6 @@ ProcessRelocation32 (
// non-Dynamic section doesn't contain entries of this type.
//
DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type));
- ASSERT (FALSE);
}
break;
@@ -236,12 +233,12 @@ RelocateElf32Dynamic (
//
// It's abnormal a DYN ELF doesn't contain a dynamic section.
//
- ASSERT (DynShdr != NULL);
if (DynShdr == NULL) {
return EFI_UNSUPPORTED;
}
- ASSERT (DynShdr->sh_type == SHT_DYNAMIC);
- ASSERT (DynShdr->sh_entsize >= sizeof (*Dyn));
+ if ((DynShdr->sh_type != SHT_DYNAMIC) || DynShdr->sh_entsize < sizeof (*Dyn)) {
+ return EFI_UNSUPPORTED;
+ }
//
// 2. Locate the relocation section from the dynamic section.
@@ -286,9 +283,6 @@ RelocateElf32Dynamic (
}
if (RelaOffset == MAX_UINT64) {
- ASSERT (RelaCount == 0);
- ASSERT (RelaEntrySize == 0);
- ASSERT (RelaSize == 0);
//
// It's fine that a DYN ELF doesn't contain relocation section.
//
@@ -299,23 +293,22 @@ RelocateElf32Dynamic (
// Verify the existence of the relocation section.
//
RelShdr = GetElf32SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize);
- ASSERT (RelShdr != NULL);
if (RelShdr == NULL) {
return EFI_UNSUPPORTED;
}
- ASSERT (RelShdr->sh_type == RelaType);
- ASSERT (RelShdr->sh_entsize == RelaEntrySize);
+ if ((RelShdr->sh_type != RelaType) || (RelShdr->sh_entsize != RelaEntrySize)) {
+ return EFI_UNSUPPORTED;
+ }
//
// 3. Process the relocation section.
//
- ProcessRelocation32 (
- (Elf32_Rela *) (ElfCt->FileBase + RelShdr->sh_offset),
- RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type,
- (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress,
- TRUE
- );
- return EFI_SUCCESS;
+ return ProcessRelocation32 (
+ (Elf32_Rela *) (ElfCt->FileBase + RelShdr->sh_offset),
+ RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type,
+ (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress,
+ TRUE
+ );
}
/**
@@ -331,7 +324,6 @@ RelocateElf32Sections (
IN ELF_IMAGE_CONTEXT *ElfCt
)
{
- EFI_STATUS Status;
Elf32_Ehdr *Ehdr;
Elf32_Shdr *RelShdr;
Elf32_Shdr *Shdr;
@@ -351,9 +343,7 @@ RelocateElf32Sections (
//
if (Ehdr->e_type == ET_DYN) {
DEBUG ((DEBUG_INFO, "DYN ELF: Relocate using dynamic sections...\n"));
- Status = RelocateElf32Dynamic (ElfCt);
- ASSERT_EFI_ERROR (Status);
- return Status;
+ return RelocateElf32Dynamic (ElfCt);
}
//
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c
index e364807007..cfe70639ca 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c
@@ -115,7 +115,7 @@ ProcessRelocation64 (
UINT32 Type;
for ( Index = 0
- ; MultU64x64 (RelaEntrySize, Index) < RelaSize
+ ; Index < DivU64x64Remainder (RelaSize, RelaEntrySize, NULL)
; Index++, Rela = ELF_NEXT_ENTRY (Elf64_Rela, Rela, RelaEntrySize)
) {
//
@@ -138,7 +138,6 @@ ProcessRelocation64 (
// Dynamic section doesn't contain entries of this type.
//
DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type));
- ASSERT (FALSE);
} else {
*Ptr += Delta;
}
@@ -149,7 +148,6 @@ ProcessRelocation64 (
// Dynamic section doesn't contain entries of this type.
//
DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type));
- ASSERT (FALSE);
break;
case R_X86_64_RELATIVE:
@@ -173,7 +171,6 @@ ProcessRelocation64 (
// Calculation: B + A
//
if (RelaType == SHT_RELA) {
- ASSERT (*Ptr == 0);
*Ptr = Delta + Rela->r_addend;
} else {
//
@@ -186,7 +183,6 @@ ProcessRelocation64 (
// non-Dynamic section doesn't contain entries of this type.
//
DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type));
- ASSERT (FALSE);
}
break;
@@ -245,12 +241,12 @@ RelocateElf64Dynamic (
//
// It's abnormal a DYN ELF doesn't contain a dynamic section.
//
- ASSERT (DynShdr != NULL);
if (DynShdr == NULL) {
return EFI_UNSUPPORTED;
}
- ASSERT (DynShdr->sh_type == SHT_DYNAMIC);
- ASSERT (DynShdr->sh_entsize >= sizeof (*Dyn));
+ if ((DynShdr->sh_type != SHT_DYNAMIC) || DynShdr->sh_entsize < sizeof (*Dyn)) {
+ return EFI_UNSUPPORTED;
+ }
//
// 2. Locate the relocation section from the dynamic section.
@@ -295,9 +291,6 @@ RelocateElf64Dynamic (
}
if (RelaOffset == MAX_UINT64) {
- ASSERT (RelaCount == 0);
- ASSERT (RelaEntrySize == 0);
- ASSERT (RelaSize == 0);
//
// It's fine that a DYN ELF doesn't contain relocation section.
//
@@ -308,23 +301,22 @@ RelocateElf64Dynamic (
// Verify the existence of the relocation section.
//
RelShdr = GetElf64SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize);
- ASSERT (RelShdr != NULL);
if (RelShdr == NULL) {
return EFI_UNSUPPORTED;
}
- ASSERT (RelShdr->sh_type == RelaType);
- ASSERT (RelShdr->sh_entsize == RelaEntrySize);
+ if ((RelShdr->sh_type != RelaType) || (RelShdr->sh_entsize != RelaEntrySize)) {
+ return EFI_UNSUPPORTED;
+ }
//
// 3. Process the relocation section.
//
- ProcessRelocation64 (
- (Elf64_Rela *) (ElfCt->FileBase + RelShdr->sh_offset),
- RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type,
- (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress,
- TRUE
- );
- return EFI_SUCCESS;
+ return ProcessRelocation64 (
+ (Elf64_Rela *) (ElfCt->FileBase + RelShdr->sh_offset),
+ RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type,
+ (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress,
+ TRUE
+ );
}
/**
@@ -340,7 +332,6 @@ RelocateElf64Sections (
IN ELF_IMAGE_CONTEXT *ElfCt
)
{
- EFI_STATUS Status;
Elf64_Ehdr *Ehdr;
Elf64_Shdr *RelShdr;
Elf64_Shdr *Shdr;
@@ -360,9 +351,7 @@ RelocateElf64Sections (
//
if (Ehdr->e_type == ET_DYN) {
DEBUG ((DEBUG_INFO, "DYN ELF: Relocate using dynamic sections...\n"));
- Status = RelocateElf64Dynamic (ElfCt);
- ASSERT_EFI_ERROR (Status);
- return Status;
+ return RelocateElf64Dynamic (ElfCt);
}
//
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c
index 531b3486d2..70de81c3ac 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c
@@ -11,22 +11,32 @@
/**
Check if the ELF image is valid.
- @param[in] ImageBase Memory address of an image.
+ @param[in] FileBase Memory address of an image.
+ @param[in] MaxFileSize The maximum file size.
@retval TRUE if valid.
**/
BOOLEAN
IsElfFormat (
- IN CONST UINT8 *ImageBase
+ IN CONST UINT8 *FileBase,
+ IN UINTN MaxFileSize
)
{
Elf32_Ehdr *Elf32Hdr;
Elf64_Ehdr *Elf64Hdr;
- ASSERT (ImageBase != NULL);
+ ASSERT (FileBase != NULL);
- Elf32Hdr = (Elf32_Ehdr *)ImageBase;
+ Elf32Hdr = (Elf32_Ehdr *)FileBase;
+ Elf64Hdr = (Elf64_Ehdr *)FileBase;
+
+ //
+ // Make sure MaxFileSize covers e_ident[].
+ //
+ if (MaxFileSize < sizeof (Elf32Hdr->e_ident)) {
+ return FALSE;
+ }
//
// Start with correct signature "\7fELF"
@@ -50,15 +60,13 @@ IsElfFormat (
// Check 32/64-bit architecture
//
if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS64) {
- Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr;
- Elf32Hdr = NULL;
- } else if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS32) {
- Elf64Hdr = NULL;
- } else {
- return FALSE;
- }
+ //
+ // Before accessing fields in Elf64_Ehdr, make sure the MaxFileSize covers the entire header.
+ //
+ if (MaxFileSize < sizeof (Elf64_Ehdr)) {
+ return FALSE;
+ }
- if (Elf64Hdr != NULL) {
//
// Support intel architecture only for now
//
@@ -79,7 +87,7 @@ IsElfFormat (
if (Elf64Hdr->e_version != EV_CURRENT) {
return FALSE;
}
- } else {
+ } else if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS32) {
//
// Support intel architecture only for now
//
@@ -100,7 +108,10 @@ IsElfFormat (
if (Elf32Hdr->e_version != EV_CURRENT) {
return FALSE;
}
+ } else {
+ return FALSE;
}
+
return TRUE;
}
@@ -108,6 +119,7 @@ IsElfFormat (
Calculate a ELF file size.
@param[in] ElfCt ELF image context pointer.
+ @param[in] MaxFileSize The maximum file size.
@param[out] FileSize Return the file size.
@retval EFI_INVALID_PARAMETER ElfCt or SecPos is NULL.
@@ -117,12 +129,12 @@ IsElfFormat (
EFI_STATUS
CalculateElfFileSize (
IN ELF_IMAGE_CONTEXT *ElfCt,
+ IN UINTN MaxFileSize,
OUT UINTN *FileSize
)
{
EFI_STATUS Status;
- UINTN FileSize1;
- UINTN FileSize2;
+ UINT32 Index;
Elf32_Ehdr *Elf32Hdr;
Elf64_Ehdr *Elf64Hdr;
UINTN Offset;
@@ -132,24 +144,34 @@ CalculateElfFileSize (
return EFI_INVALID_PARAMETER;
}
- // Use last section as end of file
- Status = GetElfSectionPos (ElfCt, ElfCt->ShNum - 1, &Offset, &Size);
- if (EFI_ERROR(Status)) {
- return EFI_UNSUPPORTED;
- }
- FileSize1 = Offset + Size;
-
- // Use end of section header as end of file
- FileSize2 = 0;
+ //
+ // Optional section headers might exist in the end of file.
+ //
+ *FileSize = 0;
if (ElfCt->EiClass == ELFCLASS32) {
Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase;
- FileSize2 = Elf32Hdr->e_shoff + Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum;
+ *FileSize = Elf32Hdr->e_shoff + Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum;
} else if (ElfCt->EiClass == ELFCLASS64) {
Elf64Hdr = (Elf64_Ehdr *)ElfCt->FileBase;
- FileSize2 = (UINTN)(Elf64Hdr->e_shoff + Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum);
+ *FileSize = (UINTN)(Elf64Hdr->e_shoff + Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum);
}
- *FileSize = MAX(FileSize1, FileSize2);
+ //
+ // Get the end of section body.
+ //
+ for (Index = 0; Index < ElfCt->ShNum; Index++) {
+ Status = GetElfSectionPos (ElfCt, Index, &Offset, &Size);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((Offset >= MaxFileSize) || (Size > MaxFileSize - Offset)) {
+ //
+ // Section body is outside of file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ *FileSize = MAX (*FileSize, Offset + Size);
+ }
return EFI_SUCCESS;
}
@@ -213,7 +235,8 @@ GetElfSegmentInfo (
On return, all fields in ElfCt are updated except ImageAddress.
- @param[in] ImageBase Memory address of an image.
+ @param[in] FileBase Memory address of an image.
+ @param[in] MaxFileSize The maximum file size.
@param[out] ElfCt The EFL image context pointer.
@retval EFI_INVALID_PARAMETER Input parameters are not valid.
@@ -223,8 +246,9 @@ GetElfSegmentInfo (
**/
EFI_STATUS
EFIAPI
-ParseElfImage (
- IN VOID *ImageBase,
+InitializeElfContext (
+ IN VOID *FileBase,
+ IN UINTN MaxFileSize,
OUT ELF_IMAGE_CONTEXT *ElfCt
)
{
@@ -238,30 +262,58 @@ ParseElfImage (
UINTN End;
UINTN Base;
- if (ElfCt == NULL) {
- return EFI_INVALID_PARAMETER;
- }
+ ASSERT (ElfCt != NULL);
+
ZeroMem (ElfCt, sizeof(ELF_IMAGE_CONTEXT));
- if (ImageBase == NULL) {
- return (ElfCt->ParseStatus = EFI_INVALID_PARAMETER);
+ if (FileBase == NULL) {
+ return EFI_INVALID_PARAMETER;
}
- ElfCt->FileBase = (UINT8 *)ImageBase;
- if (!IsElfFormat (ElfCt->FileBase)) {
- return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
+ ElfCt->FileBase = (UINT8 *)FileBase;
+ if (!IsElfFormat (ElfCt->FileBase, MaxFileSize)) {
+ return EFI_UNSUPPORTED;
}
Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase;
ElfCt->EiClass = Elf32Hdr->e_ident[EI_CLASS];
if (ElfCt->EiClass == ELFCLASS32) {
if ((Elf32Hdr->e_type != ET_EXEC) && (Elf32Hdr->e_type != ET_DYN)) {
- return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
}
- Elf32Shdr = (Elf32_Shdr *)GetElf32SectionByIndex (ElfCt->FileBase, Elf32Hdr->e_shstrndx);
+
+ if ((Elf32Hdr->e_phoff >= MaxFileSize) || ((UINT32) (Elf32Hdr->e_phentsize * Elf32Hdr->e_phnum) > MaxFileSize - Elf32Hdr->e_phoff)) {
+ //
+ // Program headers are outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Elf32Hdr->e_shoff >= MaxFileSize) || ((UINT32) (Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum) > MaxFileSize - Elf32Hdr->e_shoff)) {
+ //
+ // Section headers are outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Elf32Hdr->e_entry >= MaxFileSize) {
+ //
+ // Entrypoint is outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, Elf32Hdr->e_shstrndx);
if (Elf32Shdr == NULL) {
- return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
}
+ if ((Elf32Shdr->sh_offset >= MaxFileSize) || (Elf32Shdr->sh_size > MaxFileSize - Elf32Shdr->sh_offset)) {
+ //
+ // String section is outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
ElfCt->EntryPoint = (UINTN)Elf32Hdr->e_entry;
ElfCt->ShNum = Elf32Hdr->e_shnum;
ElfCt->PhNum = Elf32Hdr->e_phnum;
@@ -270,12 +322,41 @@ ParseElfImage (
} else {
Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr;
if ((Elf64Hdr->e_type != ET_EXEC) && (Elf64Hdr->e_type != ET_DYN)) {
- return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Elf64Hdr->e_phoff >= MaxFileSize) || ((UINT32) Elf64Hdr->e_phentsize * Elf64Hdr->e_phnum > MaxFileSize - (UINTN) Elf64Hdr->e_phoff)) {
+ //
+ // Program headers are outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Elf64Hdr->e_shoff >= MaxFileSize) || ((UINT32) Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum > MaxFileSize - (UINTN) Elf64Hdr->e_shoff)) {
+ //
+ // Section headers are outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Elf64Hdr->e_entry >= MaxFileSize) {
+ //
+ // Entrypoint is outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
}
- Elf64Shdr = (Elf64_Shdr *)GetElf64SectionByIndex (ElfCt->FileBase, Elf64Hdr->e_shstrndx);
+
+ Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, Elf64Hdr->e_shstrndx);
if (Elf64Shdr == NULL) {
- return (ElfCt->ParseStatus = EFI_UNSUPPORTED);
+ return EFI_UNSUPPORTED;
+ }
+ if ((Elf64Shdr->sh_offset >= MaxFileSize) || (Elf64Shdr->sh_size > MaxFileSize - Elf64Shdr->sh_offset)) {
+ //
+ // String section is outside of the file range.
+ //
+ return EFI_UNSUPPORTED;
}
+
ElfCt->EntryPoint = (UINTN)Elf64Hdr->e_entry;
ElfCt->ShNum = Elf64Hdr->e_shnum;
ElfCt->PhNum = Elf64Hdr->e_phnum;
@@ -297,6 +378,13 @@ ParseElfImage (
continue;
}
+ //
+ // Loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size.
+ //
+ if ((SegInfo.MemAddr % EFI_PAGE_SIZE) != (SegInfo.Offset % EFI_PAGE_SIZE)) {
+ return EFI_UNSUPPORTED;
+ }
+
if (SegInfo.MemLen != SegInfo.Length) {
//
// Not enough space to execute at current location.
@@ -317,8 +405,7 @@ ParseElfImage (
ElfCt->ImageSize = End - Base + 1;
ElfCt->PreferredImageAddress = (VOID *) Base;
- CalculateElfFileSize (ElfCt, &ElfCt->FileSize);
- return (ElfCt->ParseStatus = EFI_SUCCESS);;
+ return CalculateElfFileSize (ElfCt, MaxFileSize, &ElfCt->FileSize);
}
/**
@@ -348,10 +435,6 @@ LoadElfImage (
return EFI_INVALID_PARAMETER;
}
- if (EFI_ERROR (ElfCt->ParseStatus)) {
- return ElfCt->ParseStatus;
- }
-
if (ElfCt->ImageAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
@@ -370,6 +453,8 @@ LoadElfImage (
/**
Get a ELF section name from its index.
+ ElfCt is returned from InitializeElfContext().
+
@param[in] ElfCt ELF image context pointer.
@param[in] SectionIndex ELF section index.
@param[out] SectionName The pointer to the section name.
@@ -389,25 +474,25 @@ GetElfSectionName (
Elf32_Shdr *Elf32Shdr;
Elf64_Shdr *Elf64Shdr;
CHAR8 *Name;
+ UINTN MaxSize;
if ((ElfCt == NULL) || (SectionName == NULL)) {
return EFI_INVALID_PARAMETER;
}
- if (EFI_ERROR (ElfCt->ParseStatus)) {
- return ElfCt->ParseStatus;
- }
-
- Name = NULL;
+ Name = NULL;
+ MaxSize = 0;
if (ElfCt->EiClass == ELFCLASS32) {
Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, SectionIndex);
if ((Elf32Shdr != NULL) && (Elf32Shdr->sh_name < ElfCt->ShStrLen)) {
- Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf32Shdr->sh_name);
+ Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf32Shdr->sh_name);
+ MaxSize = ElfCt->ShStrLen - Elf32Shdr->sh_name;
}
} else if (ElfCt->EiClass == ELFCLASS64) {
Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, SectionIndex);
if ((Elf64Shdr != NULL) && (Elf64Shdr->sh_name < ElfCt->ShStrLen)) {
- Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf64Shdr->sh_name);
+ Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf64Shdr->sh_name);
+ MaxSize = ElfCt->ShStrLen - Elf64Shdr->sh_name;
}
}
@@ -415,6 +500,13 @@ GetElfSectionName (
return EFI_NOT_FOUND;
}
+ if (AsciiStrnLenS (Name, MaxSize) == MaxSize) {
+ //
+ // No null terminator is found for the section name.
+ //
+ return EFI_NOT_FOUND;
+ }
+
*SectionName = Name;
return EFI_SUCCESS;
}
@@ -449,10 +541,6 @@ GetElfSectionPos (
return EFI_INVALID_PARAMETER;
}
- if (EFI_ERROR (ElfCt->ParseStatus)) {
- return ElfCt->ParseStatus;
- }
-
if (ElfCt->EiClass == ELFCLASS32) {
Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, Index);
if (Elf32Shdr != NULL) {
diff --git a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
index 44639f9fd2..efedaef1b3 100644
--- a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
+++ b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c
@@ -69,8 +69,10 @@ PeiLoadFileLoadPayload (
return Status;
}
- ZeroMem (&Context, sizeof (Context));
- Status = ParseElfImage (Elf, &Context);
+ //
+ // Trust the ELF image loaded from FV.
+ //
+ Status = InitializeElfContext (Elf, MAX_UINTN - (UINTN) Elf, &Context);
} while (EFI_ERROR (Status));
DEBUG ((
--
2.31.1.windows.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#76429): https://edk2.groups.io/g/devel/message/76429
Mute This Topic: https://groups.io/mt/83485388/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Hey Ray, Sorry for not having properly checked yet, I definitely plan to still. However, I probably won't till a pointer alignment macro lands (I plan to submit a bunch of things, including this, within the next two weeks). Once it has been merged, I think this patch can be improved with alignment checks. Thanks for your time! Best regards, Marvin On 12.06.21 08:03, Ni, Ray wrote: > More checks are added to verify ELF image. > ParseElfImage() is changed to InitializeElfContext() > > Signed-off-by: Ray Ni <ray.ni@intel.com> > Cc: Marvin Häuser <mhaeuser@posteo.de> > Cc: Guo Dong <guo.dong@intel.com> > Cc: Benjamin You <benjamin.you@intel.com> > --- > UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h | 11 +- > .../PayloadLoaderPeim/ElfLib/Elf32Lib.c | 38 ++-- > .../PayloadLoaderPeim/ElfLib/Elf64Lib.c | 39 ++-- > .../PayloadLoaderPeim/ElfLib/ElfLib.c | 210 +++++++++++++----- > .../PayloadLoaderPeim/PayloadLoaderPeim.c | 6 +- > 5 files changed, 188 insertions(+), 116 deletions(-) > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h > index 9cfc2912cf..0ed93140a9 100644 > --- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h > +++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib.h > @@ -17,7 +17,6 @@ > #define ELF_PT_LOAD 1 > > > > typedef struct { > > - RETURN_STATUS ParseStatus; ///< Return the status after ParseElfImage(). > > UINT8 *FileBase; ///< The source location in memory. > > UINTN FileSize; ///< The size including sections that don't require loading. > > UINT8 *PreferredImageAddress; ///< The preferred image to be loaded. No relocation is needed if loaded to this address. > > @@ -45,7 +44,10 @@ typedef struct { > /** > > Parse the ELF image info. > > > > - @param[in] ImageBase Memory address of an image. > > + On return, all fields in ElfCt are updated except ImageAddress. > > + > > + @param[in] FileBase Memory address of an image. > > + @param[in] MaxFileSize The maximum file size. > > @param[out] ElfCt The EFL image context pointer. > > > > @retval EFI_INVALID_PARAMETER Input parameters are not valid. > > @@ -55,8 +57,9 @@ typedef struct { > **/ > > EFI_STATUS > > EFIAPI > > -ParseElfImage ( > > - IN VOID *ImageBase, > > +InitializeElfContext ( > > + IN VOID *FileBase, > > + IN UINTN MaxFileSize, > > OUT ELF_IMAGE_CONTEXT *ElfCt > > ); > > > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c > index 3fa100ce4a..79f4ce623b 100644 > --- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c > +++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c > @@ -115,7 +115,7 @@ ProcessRelocation32 ( > UINT32 Type; > > > > for ( Index = 0 > > - ; RelaEntrySize * Index < RelaSize > > + ; Index < RelaSize / RelaEntrySize > > ; Index++, Rela = ELF_NEXT_ENTRY (Elf32_Rela, Rela, RelaEntrySize) > > ) { > > // > > @@ -137,7 +137,6 @@ ProcessRelocation32 ( > // Dynamic section doesn't contain entries of this type. > > // > > DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type)); > > - ASSERT (FALSE); > > } else { > > *Ptr += (UINT32) Delta; > > } > > @@ -164,7 +163,6 @@ ProcessRelocation32 ( > // Calculation: B + A > > // > > if (RelaType == SHT_RELA) { > > - ASSERT (*Ptr == 0); > > *Ptr = (UINT32) Delta + Rela->r_addend; > > } else { > > // > > @@ -177,7 +175,6 @@ ProcessRelocation32 ( > // non-Dynamic section doesn't contain entries of this type. > > // > > DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type)); > > - ASSERT (FALSE); > > } > > break; > > > > @@ -236,12 +233,12 @@ RelocateElf32Dynamic ( > // > > // It's abnormal a DYN ELF doesn't contain a dynamic section. > > // > > - ASSERT (DynShdr != NULL); > > if (DynShdr == NULL) { > > return EFI_UNSUPPORTED; > > } > > - ASSERT (DynShdr->sh_type == SHT_DYNAMIC); > > - ASSERT (DynShdr->sh_entsize >= sizeof (*Dyn)); > > + if ((DynShdr->sh_type != SHT_DYNAMIC) || DynShdr->sh_entsize < sizeof (*Dyn)) { > > + return EFI_UNSUPPORTED; > > + } > > > > // > > // 2. Locate the relocation section from the dynamic section. > > @@ -286,9 +283,6 @@ RelocateElf32Dynamic ( > } > > > > if (RelaOffset == MAX_UINT64) { > > - ASSERT (RelaCount == 0); > > - ASSERT (RelaEntrySize == 0); > > - ASSERT (RelaSize == 0); > > // > > // It's fine that a DYN ELF doesn't contain relocation section. > > // > > @@ -299,23 +293,22 @@ RelocateElf32Dynamic ( > // Verify the existence of the relocation section. > > // > > RelShdr = GetElf32SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize); > > - ASSERT (RelShdr != NULL); > > if (RelShdr == NULL) { > > return EFI_UNSUPPORTED; > > } > > - ASSERT (RelShdr->sh_type == RelaType); > > - ASSERT (RelShdr->sh_entsize == RelaEntrySize); > > + if ((RelShdr->sh_type != RelaType) || (RelShdr->sh_entsize != RelaEntrySize)) { > > + return EFI_UNSUPPORTED; > > + } > > > > // > > // 3. Process the relocation section. > > // > > - ProcessRelocation32 ( > > - (Elf32_Rela *) (ElfCt->FileBase + RelShdr->sh_offset), > > - RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type, > > - (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress, > > - TRUE > > - ); > > - return EFI_SUCCESS; > > + return ProcessRelocation32 ( > > + (Elf32_Rela *) (ElfCt->FileBase + RelShdr->sh_offset), > > + RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type, > > + (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress, > > + TRUE > > + ); > > } > > > > /** > > @@ -331,7 +324,6 @@ RelocateElf32Sections ( > IN ELF_IMAGE_CONTEXT *ElfCt > > ) > > { > > - EFI_STATUS Status; > > Elf32_Ehdr *Ehdr; > > Elf32_Shdr *RelShdr; > > Elf32_Shdr *Shdr; > > @@ -351,9 +343,7 @@ RelocateElf32Sections ( > // > > if (Ehdr->e_type == ET_DYN) { > > DEBUG ((DEBUG_INFO, "DYN ELF: Relocate using dynamic sections...\n")); > > - Status = RelocateElf32Dynamic (ElfCt); > > - ASSERT_EFI_ERROR (Status); > > - return Status; > > + return RelocateElf32Dynamic (ElfCt); > > } > > > > // > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c > index e364807007..cfe70639ca 100644 > --- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c > +++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c > @@ -115,7 +115,7 @@ ProcessRelocation64 ( > UINT32 Type; > > > > for ( Index = 0 > > - ; MultU64x64 (RelaEntrySize, Index) < RelaSize > > + ; Index < DivU64x64Remainder (RelaSize, RelaEntrySize, NULL) > > ; Index++, Rela = ELF_NEXT_ENTRY (Elf64_Rela, Rela, RelaEntrySize) > > ) { > > // > > @@ -138,7 +138,6 @@ ProcessRelocation64 ( > // Dynamic section doesn't contain entries of this type. > > // > > DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type)); > > - ASSERT (FALSE); > > } else { > > *Ptr += Delta; > > } > > @@ -149,7 +148,6 @@ ProcessRelocation64 ( > // Dynamic section doesn't contain entries of this type. > > // > > DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type)); > > - ASSERT (FALSE); > > break; > > > > case R_X86_64_RELATIVE: > > @@ -173,7 +171,6 @@ ProcessRelocation64 ( > // Calculation: B + A > > // > > if (RelaType == SHT_RELA) { > > - ASSERT (*Ptr == 0); > > *Ptr = Delta + Rela->r_addend; > > } else { > > // > > @@ -186,7 +183,6 @@ ProcessRelocation64 ( > // non-Dynamic section doesn't contain entries of this type. > > // > > DEBUG ((DEBUG_INFO, "Unsupported relocation type %02X\n", Type)); > > - ASSERT (FALSE); > > } > > break; > > > > @@ -245,12 +241,12 @@ RelocateElf64Dynamic ( > // > > // It's abnormal a DYN ELF doesn't contain a dynamic section. > > // > > - ASSERT (DynShdr != NULL); > > if (DynShdr == NULL) { > > return EFI_UNSUPPORTED; > > } > > - ASSERT (DynShdr->sh_type == SHT_DYNAMIC); > > - ASSERT (DynShdr->sh_entsize >= sizeof (*Dyn)); > > + if ((DynShdr->sh_type != SHT_DYNAMIC) || DynShdr->sh_entsize < sizeof (*Dyn)) { > > + return EFI_UNSUPPORTED; > > + } > > > > // > > // 2. Locate the relocation section from the dynamic section. > > @@ -295,9 +291,6 @@ RelocateElf64Dynamic ( > } > > > > if (RelaOffset == MAX_UINT64) { > > - ASSERT (RelaCount == 0); > > - ASSERT (RelaEntrySize == 0); > > - ASSERT (RelaSize == 0); > > // > > // It's fine that a DYN ELF doesn't contain relocation section. > > // > > @@ -308,23 +301,22 @@ RelocateElf64Dynamic ( > // Verify the existence of the relocation section. > > // > > RelShdr = GetElf64SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize); > > - ASSERT (RelShdr != NULL); > > if (RelShdr == NULL) { > > return EFI_UNSUPPORTED; > > } > > - ASSERT (RelShdr->sh_type == RelaType); > > - ASSERT (RelShdr->sh_entsize == RelaEntrySize); > > + if ((RelShdr->sh_type != RelaType) || (RelShdr->sh_entsize != RelaEntrySize)) { > > + return EFI_UNSUPPORTED; > > + } > > > > // > > // 3. Process the relocation section. > > // > > - ProcessRelocation64 ( > > - (Elf64_Rela *) (ElfCt->FileBase + RelShdr->sh_offset), > > - RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type, > > - (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress, > > - TRUE > > - ); > > - return EFI_SUCCESS; > > + return ProcessRelocation64 ( > > + (Elf64_Rela *) (ElfCt->FileBase + RelShdr->sh_offset), > > + RelShdr->sh_size, RelShdr->sh_entsize, RelShdr->sh_type, > > + (UINTN) ElfCt->ImageAddress - (UINTN) ElfCt->PreferredImageAddress, > > + TRUE > > + ); > > } > > > > /** > > @@ -340,7 +332,6 @@ RelocateElf64Sections ( > IN ELF_IMAGE_CONTEXT *ElfCt > > ) > > { > > - EFI_STATUS Status; > > Elf64_Ehdr *Ehdr; > > Elf64_Shdr *RelShdr; > > Elf64_Shdr *Shdr; > > @@ -360,9 +351,7 @@ RelocateElf64Sections ( > // > > if (Ehdr->e_type == ET_DYN) { > > DEBUG ((DEBUG_INFO, "DYN ELF: Relocate using dynamic sections...\n")); > > - Status = RelocateElf64Dynamic (ElfCt); > > - ASSERT_EFI_ERROR (Status); > > - return Status; > > + return RelocateElf64Dynamic (ElfCt); > > } > > > > // > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c > index 531b3486d2..70de81c3ac 100644 > --- a/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c > +++ b/UefiPayloadPkg/PayloadLoaderPeim/ElfLib/ElfLib.c > @@ -11,22 +11,32 @@ > /** > > Check if the ELF image is valid. > > > > - @param[in] ImageBase Memory address of an image. > > + @param[in] FileBase Memory address of an image. > > + @param[in] MaxFileSize The maximum file size. > > > > @retval TRUE if valid. > > > > **/ > > BOOLEAN > > IsElfFormat ( > > - IN CONST UINT8 *ImageBase > > + IN CONST UINT8 *FileBase, > > + IN UINTN MaxFileSize > > ) > > { > > Elf32_Ehdr *Elf32Hdr; > > Elf64_Ehdr *Elf64Hdr; > > > > - ASSERT (ImageBase != NULL); > > + ASSERT (FileBase != NULL); > > > > - Elf32Hdr = (Elf32_Ehdr *)ImageBase; > > + Elf32Hdr = (Elf32_Ehdr *)FileBase; > > + Elf64Hdr = (Elf64_Ehdr *)FileBase; > > + > > + // > > + // Make sure MaxFileSize covers e_ident[]. > > + // > > + if (MaxFileSize < sizeof (Elf32Hdr->e_ident)) { > > + return FALSE; > > + } > > > > // > > // Start with correct signature "\7fELF" > > @@ -50,15 +60,13 @@ IsElfFormat ( > // Check 32/64-bit architecture > > // > > if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS64) { > > - Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr; > > - Elf32Hdr = NULL; > > - } else if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS32) { > > - Elf64Hdr = NULL; > > - } else { > > - return FALSE; > > - } > > + // > > + // Before accessing fields in Elf64_Ehdr, make sure the MaxFileSize covers the entire header. > > + // > > + if (MaxFileSize < sizeof (Elf64_Ehdr)) { > > + return FALSE; > > + } > > > > - if (Elf64Hdr != NULL) { > > // > > // Support intel architecture only for now > > // > > @@ -79,7 +87,7 @@ IsElfFormat ( > if (Elf64Hdr->e_version != EV_CURRENT) { > > return FALSE; > > } > > - } else { > > + } else if (Elf32Hdr->e_ident[EI_CLASS] == ELFCLASS32) { > > // > > // Support intel architecture only for now > > // > > @@ -100,7 +108,10 @@ IsElfFormat ( > if (Elf32Hdr->e_version != EV_CURRENT) { > > return FALSE; > > } > > + } else { > > + return FALSE; > > } > > + > > return TRUE; > > } > > > > @@ -108,6 +119,7 @@ IsElfFormat ( > Calculate a ELF file size. > > > > @param[in] ElfCt ELF image context pointer. > > + @param[in] MaxFileSize The maximum file size. > > @param[out] FileSize Return the file size. > > > > @retval EFI_INVALID_PARAMETER ElfCt or SecPos is NULL. > > @@ -117,12 +129,12 @@ IsElfFormat ( > EFI_STATUS > > CalculateElfFileSize ( > > IN ELF_IMAGE_CONTEXT *ElfCt, > > + IN UINTN MaxFileSize, > > OUT UINTN *FileSize > > ) > > { > > EFI_STATUS Status; > > - UINTN FileSize1; > > - UINTN FileSize2; > > + UINT32 Index; > > Elf32_Ehdr *Elf32Hdr; > > Elf64_Ehdr *Elf64Hdr; > > UINTN Offset; > > @@ -132,24 +144,34 @@ CalculateElfFileSize ( > return EFI_INVALID_PARAMETER; > > } > > > > - // Use last section as end of file > > - Status = GetElfSectionPos (ElfCt, ElfCt->ShNum - 1, &Offset, &Size); > > - if (EFI_ERROR(Status)) { > > - return EFI_UNSUPPORTED; > > - } > > - FileSize1 = Offset + Size; > > - > > - // Use end of section header as end of file > > - FileSize2 = 0; > > + // > > + // Optional section headers might exist in the end of file. > > + // > > + *FileSize = 0; > > if (ElfCt->EiClass == ELFCLASS32) { > > Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase; > > - FileSize2 = Elf32Hdr->e_shoff + Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum; > > + *FileSize = Elf32Hdr->e_shoff + Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum; > > } else if (ElfCt->EiClass == ELFCLASS64) { > > Elf64Hdr = (Elf64_Ehdr *)ElfCt->FileBase; > > - FileSize2 = (UINTN)(Elf64Hdr->e_shoff + Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum); > > + *FileSize = (UINTN)(Elf64Hdr->e_shoff + Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum); > > } > > > > - *FileSize = MAX(FileSize1, FileSize2); > > + // > > + // Get the end of section body. > > + // > > + for (Index = 0; Index < ElfCt->ShNum; Index++) { > > + Status = GetElfSectionPos (ElfCt, Index, &Offset, &Size); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + if ((Offset >= MaxFileSize) || (Size > MaxFileSize - Offset)) { > > + // > > + // Section body is outside of file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + *FileSize = MAX (*FileSize, Offset + Size); > > + } > > > > return EFI_SUCCESS; > > } > > @@ -213,7 +235,8 @@ GetElfSegmentInfo ( > > > On return, all fields in ElfCt are updated except ImageAddress. > > > > - @param[in] ImageBase Memory address of an image. > > + @param[in] FileBase Memory address of an image. > > + @param[in] MaxFileSize The maximum file size. > > @param[out] ElfCt The EFL image context pointer. > > > > @retval EFI_INVALID_PARAMETER Input parameters are not valid. > > @@ -223,8 +246,9 @@ GetElfSegmentInfo ( > **/ > > EFI_STATUS > > EFIAPI > > -ParseElfImage ( > > - IN VOID *ImageBase, > > +InitializeElfContext ( > > + IN VOID *FileBase, > > + IN UINTN MaxFileSize, > > OUT ELF_IMAGE_CONTEXT *ElfCt > > ) > > { > > @@ -238,30 +262,58 @@ ParseElfImage ( > UINTN End; > > UINTN Base; > > > > - if (ElfCt == NULL) { > > - return EFI_INVALID_PARAMETER; > > - } > > + ASSERT (ElfCt != NULL); > > + > > ZeroMem (ElfCt, sizeof(ELF_IMAGE_CONTEXT)); > > > > - if (ImageBase == NULL) { > > - return (ElfCt->ParseStatus = EFI_INVALID_PARAMETER); > > + if (FileBase == NULL) { > > + return EFI_INVALID_PARAMETER; > > } > > > > - ElfCt->FileBase = (UINT8 *)ImageBase; > > - if (!IsElfFormat (ElfCt->FileBase)) { > > - return (ElfCt->ParseStatus = EFI_UNSUPPORTED); > > + ElfCt->FileBase = (UINT8 *)FileBase; > > + if (!IsElfFormat (ElfCt->FileBase, MaxFileSize)) { > > + return EFI_UNSUPPORTED; > > } > > > > Elf32Hdr = (Elf32_Ehdr *)ElfCt->FileBase; > > ElfCt->EiClass = Elf32Hdr->e_ident[EI_CLASS]; > > if (ElfCt->EiClass == ELFCLASS32) { > > if ((Elf32Hdr->e_type != ET_EXEC) && (Elf32Hdr->e_type != ET_DYN)) { > > - return (ElfCt->ParseStatus = EFI_UNSUPPORTED); > > + return EFI_UNSUPPORTED; > > } > > - Elf32Shdr = (Elf32_Shdr *)GetElf32SectionByIndex (ElfCt->FileBase, Elf32Hdr->e_shstrndx); > > + > > + if ((Elf32Hdr->e_phoff >= MaxFileSize) || ((UINT32) (Elf32Hdr->e_phentsize * Elf32Hdr->e_phnum) > MaxFileSize - Elf32Hdr->e_phoff)) { > > + // > > + // Program headers are outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > + if ((Elf32Hdr->e_shoff >= MaxFileSize) || ((UINT32) (Elf32Hdr->e_shentsize * Elf32Hdr->e_shnum) > MaxFileSize - Elf32Hdr->e_shoff)) { > > + // > > + // Section headers are outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > + if (Elf32Hdr->e_entry >= MaxFileSize) { > > + // > > + // Entrypoint is outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > + Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, Elf32Hdr->e_shstrndx); > > if (Elf32Shdr == NULL) { > > - return (ElfCt->ParseStatus = EFI_UNSUPPORTED); > > + return EFI_UNSUPPORTED; > > } > > + if ((Elf32Shdr->sh_offset >= MaxFileSize) || (Elf32Shdr->sh_size > MaxFileSize - Elf32Shdr->sh_offset)) { > > + // > > + // String section is outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > ElfCt->EntryPoint = (UINTN)Elf32Hdr->e_entry; > > ElfCt->ShNum = Elf32Hdr->e_shnum; > > ElfCt->PhNum = Elf32Hdr->e_phnum; > > @@ -270,12 +322,41 @@ ParseElfImage ( > } else { > > Elf64Hdr = (Elf64_Ehdr *)Elf32Hdr; > > if ((Elf64Hdr->e_type != ET_EXEC) && (Elf64Hdr->e_type != ET_DYN)) { > > - return (ElfCt->ParseStatus = EFI_UNSUPPORTED); > > + return EFI_UNSUPPORTED; > > + } > > + > > + if ((Elf64Hdr->e_phoff >= MaxFileSize) || ((UINT32) Elf64Hdr->e_phentsize * Elf64Hdr->e_phnum > MaxFileSize - (UINTN) Elf64Hdr->e_phoff)) { > > + // > > + // Program headers are outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > + if ((Elf64Hdr->e_shoff >= MaxFileSize) || ((UINT32) Elf64Hdr->e_shentsize * Elf64Hdr->e_shnum > MaxFileSize - (UINTN) Elf64Hdr->e_shoff)) { > > + // > > + // Section headers are outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > + } > > + > > + if (Elf64Hdr->e_entry >= MaxFileSize) { > > + // > > + // Entrypoint is outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > } > > - Elf64Shdr = (Elf64_Shdr *)GetElf64SectionByIndex (ElfCt->FileBase, Elf64Hdr->e_shstrndx); > > + > > + Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, Elf64Hdr->e_shstrndx); > > if (Elf64Shdr == NULL) { > > - return (ElfCt->ParseStatus = EFI_UNSUPPORTED); > > + return EFI_UNSUPPORTED; > > + } > > + if ((Elf64Shdr->sh_offset >= MaxFileSize) || (Elf64Shdr->sh_size > MaxFileSize - Elf64Shdr->sh_offset)) { > > + // > > + // String section is outside of the file range. > > + // > > + return EFI_UNSUPPORTED; > > } > > + > > ElfCt->EntryPoint = (UINTN)Elf64Hdr->e_entry; > > ElfCt->ShNum = Elf64Hdr->e_shnum; > > ElfCt->PhNum = Elf64Hdr->e_phnum; > > @@ -297,6 +378,13 @@ ParseElfImage ( > continue; > > } > > > > + // > > + // Loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size. > > + // > > + if ((SegInfo.MemAddr % EFI_PAGE_SIZE) != (SegInfo.Offset % EFI_PAGE_SIZE)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > if (SegInfo.MemLen != SegInfo.Length) { > > // > > // Not enough space to execute at current location. > > @@ -317,8 +405,7 @@ ParseElfImage ( > ElfCt->ImageSize = End - Base + 1; > > ElfCt->PreferredImageAddress = (VOID *) Base; > > > > - CalculateElfFileSize (ElfCt, &ElfCt->FileSize); > > - return (ElfCt->ParseStatus = EFI_SUCCESS);; > > + return CalculateElfFileSize (ElfCt, MaxFileSize, &ElfCt->FileSize); > > } > > > > /** > > @@ -348,10 +435,6 @@ LoadElfImage ( > return EFI_INVALID_PARAMETER; > > } > > > > - if (EFI_ERROR (ElfCt->ParseStatus)) { > > - return ElfCt->ParseStatus; > > - } > > - > > if (ElfCt->ImageAddress == NULL) { > > return EFI_INVALID_PARAMETER; > > } > > @@ -370,6 +453,8 @@ LoadElfImage ( > /** > > Get a ELF section name from its index. > > > > + ElfCt is returned from InitializeElfContext(). > > + > > @param[in] ElfCt ELF image context pointer. > > @param[in] SectionIndex ELF section index. > > @param[out] SectionName The pointer to the section name. > > @@ -389,25 +474,25 @@ GetElfSectionName ( > Elf32_Shdr *Elf32Shdr; > > Elf64_Shdr *Elf64Shdr; > > CHAR8 *Name; > > + UINTN MaxSize; > > > > if ((ElfCt == NULL) || (SectionName == NULL)) { > > return EFI_INVALID_PARAMETER; > > } > > > > - if (EFI_ERROR (ElfCt->ParseStatus)) { > > - return ElfCt->ParseStatus; > > - } > > - > > - Name = NULL; > > + Name = NULL; > > + MaxSize = 0; > > if (ElfCt->EiClass == ELFCLASS32) { > > Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, SectionIndex); > > if ((Elf32Shdr != NULL) && (Elf32Shdr->sh_name < ElfCt->ShStrLen)) { > > - Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf32Shdr->sh_name); > > + Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf32Shdr->sh_name); > > + MaxSize = ElfCt->ShStrLen - Elf32Shdr->sh_name; > > } > > } else if (ElfCt->EiClass == ELFCLASS64) { > > Elf64Shdr = GetElf64SectionByIndex (ElfCt->FileBase, SectionIndex); > > if ((Elf64Shdr != NULL) && (Elf64Shdr->sh_name < ElfCt->ShStrLen)) { > > - Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf64Shdr->sh_name); > > + Name = (CHAR8 *)(ElfCt->FileBase + ElfCt->ShStrOff + Elf64Shdr->sh_name); > > + MaxSize = ElfCt->ShStrLen - Elf64Shdr->sh_name; > > } > > } > > > > @@ -415,6 +500,13 @@ GetElfSectionName ( > return EFI_NOT_FOUND; > > } > > > > + if (AsciiStrnLenS (Name, MaxSize) == MaxSize) { > > + // > > + // No null terminator is found for the section name. > > + // > > + return EFI_NOT_FOUND; > > + } > > + > > *SectionName = Name; > > return EFI_SUCCESS; > > } > > @@ -449,10 +541,6 @@ GetElfSectionPos ( > return EFI_INVALID_PARAMETER; > > } > > > > - if (EFI_ERROR (ElfCt->ParseStatus)) { > > - return ElfCt->ParseStatus; > > - } > > - > > if (ElfCt->EiClass == ELFCLASS32) { > > Elf32Shdr = GetElf32SectionByIndex (ElfCt->FileBase, Index); > > if (Elf32Shdr != NULL) { > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c > index 44639f9fd2..efedaef1b3 100644 > --- a/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c > +++ b/UefiPayloadPkg/PayloadLoaderPeim/PayloadLoaderPeim.c > @@ -69,8 +69,10 @@ PeiLoadFileLoadPayload ( > return Status; > > } > > > > - ZeroMem (&Context, sizeof (Context)); > > - Status = ParseElfImage (Elf, &Context); > > + // > > + // Trust the ELF image loaded from FV. > > + // > > + Status = InitializeElfContext (Elf, MAX_UINTN - (UINTN) Elf, &Context); > > } while (EFI_ERROR (Status)); > > > > DEBUG (( > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#77178): https://edk2.groups.io/g/devel/message/77178 Mute This Topic: https://groups.io/mt/83485388/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.