mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
User: Provide more robust PE example and memory support
This commit is contained in:
parent
a3a48b1933
commit
e0701fbdae
12
User/Include/UserMemory.h
Normal file
12
User/Include/UserMemory.h
Normal file
@ -0,0 +1,12 @@
|
||||
/** @file
|
||||
Copyright (c) 2022, vit9696. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#ifndef USER_MEMORY_H
|
||||
#define USER_MEMORY_H
|
||||
|
||||
extern UINTN mPoolAllocations;
|
||||
extern UINTN mPageAllocations;
|
||||
|
||||
#endif // USER_MEMORY_H
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
@ -16,6 +17,9 @@
|
||||
#include <malloc.h>
|
||||
#endif // WIN32
|
||||
|
||||
UINTN mPoolAllocations;
|
||||
UINTN mPageAllocations;
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
CopyMem (
|
||||
@ -87,7 +91,19 @@ AllocatePool (
|
||||
IN UINTN AllocationSize
|
||||
)
|
||||
{
|
||||
return malloc (AllocationSize);
|
||||
// UEFI guarantees 8-byte alignment.
|
||||
void *p = malloc ((AllocationSize + 7U) & ~7U);
|
||||
DEBUG ((
|
||||
DEBUG_POOL,
|
||||
"UMEM: Allocating pool %u at %p\n",
|
||||
(UINT32) AllocationSize,
|
||||
p
|
||||
));
|
||||
ASSERT (((UINTN)p & 7U) == 0);
|
||||
if (p != NULL) {
|
||||
++mPoolAllocations;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
VOID *
|
||||
@ -140,7 +156,7 @@ ReallocatePool (
|
||||
|
||||
if (NewBuffer != NULL && OldBuffer != NULL) {
|
||||
memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
|
||||
free (OldBuffer);
|
||||
FreePool (OldBuffer);
|
||||
}
|
||||
|
||||
return NewBuffer;
|
||||
@ -152,10 +168,11 @@ AllocatePages (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return _aligned_malloc (Pages * EFI_PAGE_SIZE, EFI_PAGE_SIZE);
|
||||
#else // !WIN32
|
||||
VOID *Memory;
|
||||
|
||||
#ifdef WIN32
|
||||
Memory = _aligned_malloc (Pages * EFI_PAGE_SIZE, EFI_PAGE_SIZE);
|
||||
#else // !WIN32
|
||||
INTN RetVal;
|
||||
|
||||
Memory = NULL;
|
||||
@ -164,11 +181,22 @@ AllocatePages (
|
||||
|
||||
if (RetVal != 0) {
|
||||
DEBUG ((DEBUG_ERROR, "posix_memalign returns error %d\n", RetVal));
|
||||
return NULL;
|
||||
Memory = NULL;
|
||||
}
|
||||
|
||||
return Memory;
|
||||
#endif // WIN32
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_PAGE,
|
||||
"UMEM: Allocating %u pages at %p\n",
|
||||
(UINT32) Pages,
|
||||
Memory
|
||||
));
|
||||
|
||||
if (Memory != NULL) {
|
||||
mPageAllocations += Pages;
|
||||
}
|
||||
|
||||
return Memory;
|
||||
}
|
||||
|
||||
VOID
|
||||
@ -178,6 +206,13 @@ FreePool (
|
||||
)
|
||||
{
|
||||
ASSERT (Buffer != NULL);
|
||||
DEBUG ((
|
||||
DEBUG_POOL,
|
||||
"UMEM: Deallocating pool %p\n",
|
||||
Buffer
|
||||
));
|
||||
|
||||
--mPoolAllocations;
|
||||
|
||||
free (Buffer);
|
||||
}
|
||||
@ -191,6 +226,15 @@ FreePages (
|
||||
{
|
||||
ASSERT (Buffer != NULL);
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_PAGE,
|
||||
"UMEM: Deallocating %u pages at %p\n",
|
||||
(UINT32) Pages,
|
||||
Buffer
|
||||
));
|
||||
|
||||
mPageAllocations -= Pages;
|
||||
|
||||
free (Buffer);
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
**/
|
||||
|
||||
#include <UserFile.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
uint8_t *UserReadFile(const char *str, uint32_t *size) {
|
||||
FILE *f = fopen(str, "rb");
|
||||
@ -14,7 +15,7 @@ uint8_t *UserReadFile(const char *str, uint32_t *size) {
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
uint8_t *string = malloc(fsize + 1);
|
||||
uint8_t *string = AllocatePool(fsize + 1);
|
||||
if (fsize > 0 && fread(string, fsize, 1, f) != 1)
|
||||
abort();
|
||||
fclose(f);
|
||||
|
||||
@ -9,106 +9,195 @@
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <UserFile.h>
|
||||
#include <UserMemory.h>
|
||||
|
||||
EFI_STATUS
|
||||
TestImageLoad (
|
||||
IN VOID *SourceBuffer,
|
||||
IN UINTN SourceSize
|
||||
STATIC UINT64 PcdValidAllocMask = MAX_UINT64;
|
||||
STATIC UINT8 PcdValidHashes = MAX_UINT8;
|
||||
UINTN HashDependency;
|
||||
|
||||
BOOLEAN
|
||||
HashUpdate (
|
||||
IN OUT VOID *HashContext,
|
||||
IN CONST VOID *Data,
|
||||
IN UINTN DataLength
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS ImageStatus;
|
||||
PE_COFF_IMAGE_CONTEXT ImageContext;
|
||||
EFI_PHYSICAL_ADDRESS DestinationArea;
|
||||
VOID *DestinationBuffer;
|
||||
|
||||
CONST UINT8 *D = (CONST UINT8 *)Data;
|
||||
|
||||
//
|
||||
// Initialize the image context.
|
||||
//
|
||||
ImageStatus = PeCoffInitializeContext (
|
||||
&ImageContext,
|
||||
SourceBuffer,
|
||||
SourceSize
|
||||
);
|
||||
if (EFI_ERROR (ImageStatus)) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: PeCoff init failure - %r\n", ImageStatus));
|
||||
return EFI_UNSUPPORTED;
|
||||
(VOID) HashContext;
|
||||
|
||||
for (UINTN i = 0; i < DataLength; i++)
|
||||
HashDependency += D[i];
|
||||
|
||||
if (PcdValidHashes > 0) {
|
||||
PcdValidHashes--;
|
||||
return TRUE;
|
||||
}
|
||||
//
|
||||
// Reject images that are not meant for the platform's architecture.
|
||||
//
|
||||
if (ImageContext.Machine != IMAGE_FILE_MACHINE_X64) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: PeCoff wrong machine - %x\n", ImageContext.Machine));
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC
|
||||
RETURN_STATUS
|
||||
PeCoffTestRtReloc (
|
||||
PE_COFF_IMAGE_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
PE_COFF_RUNTIME_CONTEXT *RtCtx;
|
||||
UINT32 RtCtxSize;
|
||||
|
||||
Status = PeCoffRelocationDataSize (Context, &RtCtxSize);
|
||||
|
||||
if (Status != RETURN_SUCCESS) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
//
|
||||
// Reject RT drivers for the moment.
|
||||
//
|
||||
if (ImageContext.Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: PeCoff no support for RT drivers\n"));
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
RtCtx = AllocatePool (RtCtxSize);
|
||||
|
||||
if (RtCtx == NULL) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
//
|
||||
// Allocate the image destination memory.
|
||||
// FIXME: RT drivers require EfiRuntimeServicesCode.
|
||||
//
|
||||
Status = gBS->AllocatePages (
|
||||
AllocateAnyPages,
|
||||
EfiBootServicesCode,
|
||||
EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage),
|
||||
&DestinationArea
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
Status = PeCoffRelocateImage (Context, 0x69696969, RtCtx, RtCtxSize);
|
||||
|
||||
if (Status != RETURN_SUCCESS) {
|
||||
FreePool (RtCtx);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DestinationBuffer = (VOID *)(UINTN) DestinationArea;
|
||||
Status = PeCoffRelocateImageForRuntime (Context->ImageBuffer, Context->SizeOfImage, 0x96969696, RtCtx);
|
||||
|
||||
FreePool (RtCtx);
|
||||
|
||||
//
|
||||
// Load SourceBuffer into DestinationBuffer.
|
||||
//
|
||||
ImageStatus = PeCoffLoadImage (
|
||||
&ImageContext,
|
||||
DestinationBuffer,
|
||||
ImageContext.SizeOfImage
|
||||
);
|
||||
if (EFI_ERROR (ImageStatus)) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: PeCoff load image error - %r\n", ImageStatus));
|
||||
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
//
|
||||
// Relocate the loaded image to the destination address.
|
||||
//
|
||||
ImageStatus = PeCoffRelocateImage (
|
||||
&ImageContext,
|
||||
(UINTN) DestinationBuffer,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
FreePages (DestinationBuffer, EFI_SIZE_TO_PAGES (ImageContext.SizeOfImage));
|
||||
STATIC
|
||||
RETURN_STATUS
|
||||
PeCoffTestLoad (
|
||||
PE_COFF_IMAGE_CONTEXT *Context,
|
||||
VOID *Destination,
|
||||
UINT32 DestinationSize
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
CHAR8 *PdbPath;
|
||||
UINT32 PdbPathSize;
|
||||
|
||||
if (EFI_ERROR (ImageStatus)) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: PeCoff relocate image error - %d\n", ImageStatus));
|
||||
return EFI_UNSUPPORTED;
|
||||
(VOID) PeCoffLoadImage (Context, Destination, DestinationSize);
|
||||
|
||||
Status = PeCoffGetPdbPath (Context, &PdbPath, &PdbPathSize);
|
||||
|
||||
if (Status == RETURN_SUCCESS) {
|
||||
ZeroMem (PdbPath, PdbPathSize);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
if (!Context->RelocsStripped) {
|
||||
if (Context->Subsystem != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
|
||||
Status = PeCoffRelocateImage (Context, (UINTN) (Context->ImageBuffer), NULL, 0);
|
||||
} else {
|
||||
Status = PeCoffTestRtReloc (Context);
|
||||
}
|
||||
}
|
||||
|
||||
if (Status != RETURN_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
PeCoffDiscardSections (Context);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static void loadConfig(const uint8_t *data, size_t size) {
|
||||
HashDependency = 0;
|
||||
PcdGetBool(PcdImageLoaderRtRelocAllowTargetMismatch) = (data[size - 1] & 1U) != 0;
|
||||
PcdGetBool(PcdImageLoaderHashProhibitOverlap) = (data[size - 1] & 2U) != 0;
|
||||
PcdGetBool(PcdImageLoaderLoadHeader) = (data[size - 1] & 4U) != 0;
|
||||
PcdGetBool(PcdImageLoaderSupportArmThumb) = (data[size - 1] & 8U) != 0;
|
||||
PcdGetBool(PcdImageLoaderForceLoadDebug) = (data[size - 1] & 16U) != 0;
|
||||
PcdGetBool(PcdImageLoaderTolerantLoad) = (data[size - 1] & 32U) != 0;
|
||||
PcdGetBool(PcdImageLoaderSupportDebug) = (data[size - 1] & 64U) != 0;
|
||||
memcpy(&PcdValidAllocMask, &data[size - MIN(size, sizeof(UINT64))], MIN(size, sizeof(UINT64)));
|
||||
PcdValidHashes = data[size - MIN(size, sizeof(UINT64) + sizeof(UINT8))];
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
PeCoffTestLoadFull (
|
||||
IN VOID *FileBuffer,
|
||||
IN UINT32 FileSize
|
||||
)
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
BOOLEAN Result;
|
||||
PE_COFF_IMAGE_CONTEXT Context;
|
||||
VOID *Destination;
|
||||
UINT32 DestinationSize;
|
||||
|
||||
Status = PeCoffInitializeContext (&Context, FileBuffer, FileSize);
|
||||
|
||||
if (Status != RETURN_SUCCESS) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
UINT8 HashContext;
|
||||
Result = PeCoffHashImage (
|
||||
&Context,
|
||||
HashUpdate,
|
||||
&HashContext
|
||||
);
|
||||
|
||||
if (!Result) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
DestinationSize = Context.SizeOfImage + Context.SizeOfImageDebugAdd;
|
||||
|
||||
if (OcOverflowAddU32 (DestinationSize, Context.SectionAlignment, &DestinationSize)) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Destination = AllocatePages (EFI_SIZE_TO_PAGES (DestinationSize));
|
||||
if (Destination == NULL) {
|
||||
return RETURN_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = PeCoffTestLoad (&Context, Destination, DestinationSize);
|
||||
|
||||
FreePages (Destination, EFI_SIZE_TO_PAGES (DestinationSize));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) {
|
||||
if (Data != NULL) {
|
||||
void *DataCopy = AllocateCopyPool(Size, Data);
|
||||
TestImageLoad (DataCopy, Size);
|
||||
FreePool(DataCopy);
|
||||
if (Size == 0)
|
||||
return 0;
|
||||
|
||||
//PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
|
||||
//PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
|
||||
|
||||
void *p = AllocatePool(Size);
|
||||
if (p != NULL) {
|
||||
loadConfig(Data, Size);
|
||||
memcpy(p, Data, Size);
|
||||
PeCoffTestLoadFull(p, Size);
|
||||
FreePool(p);
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_POOL | DEBUG_PAGE,
|
||||
"UMEM: Allocated %u pools %u pages\n",
|
||||
(UINT32) mPoolAllocations,
|
||||
(UINT32) mPageAllocations
|
||||
));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -121,6 +210,9 @@ int ENTRY_POINT (int argc, char *argv[]) {
|
||||
PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_INFO;
|
||||
PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_INFO;
|
||||
|
||||
//PcdGet32 (PcdFixedDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
|
||||
//PcdGet32 (PcdDebugPrintErrorLevel) |= DEBUG_POOL | DEBUG_PAGE;
|
||||
|
||||
uint8_t *Image;
|
||||
uint32_t ImageSize;
|
||||
|
||||
@ -129,8 +221,8 @@ int ENTRY_POINT (int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
EFI_STATUS Status = TestImageLoad (Image, ImageSize);
|
||||
free(Image);
|
||||
EFI_STATUS Status = LLVMFuzzerTestOneInput (Image, ImageSize);
|
||||
FreePool(Image);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user