From ae96764ad5146ad6a3efb4be224cf9b39b2cd6a7 Mon Sep 17 00:00:00 2001 From: Kelvin Zhang Date: Wed, 3 Sep 2025 15:36:35 -0700 Subject: [PATCH] [lib][uefi] Fix error in relocation --- lib/uefi/include/uefi/system_table.h | 2 +- lib/uefi/pe.h | 2 +- lib/uefi/relocation.cpp | 21 ++++++++++----------- lib/uefi/uefi.cpp | 17 +++++++++++------ 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/uefi/include/uefi/system_table.h b/lib/uefi/include/uefi/system_table.h index 9b7ded9159..5b153e9bde 100644 --- a/lib/uefi/include/uefi/system_table.h +++ b/lib/uefi/include/uefi/system_table.h @@ -38,7 +38,7 @@ typedef struct { typedef struct EfiSystemTable { EfiTableHeader header; - const char16_t* firmware_vendor; + const EfiChar16* firmware_vendor; uint32_t firmware_revision; EfiHandle console_in_handle; void* con_in; diff --git a/lib/uefi/pe.h b/lib/uefi/pe.h index 562a388113..c4bb9e2b15 100644 --- a/lib/uefi/pe.h +++ b/lib/uefi/pe.h @@ -63,7 +63,7 @@ struct IMAGE_DOS_HEADER { // DOS .EXE header u16 e_res2[10]; // Reserved words u32 e_lfanew; // File address of new exe header - // ASCII "PE\x0\x0" + // DOS "MZ" signature constexpr bool CheckMagic() const { return LE32(e_magic) == 0x5A4D; } IMAGE_NT_HEADERS64 *GetPEHeader() { auto address = reinterpret_cast(this); diff --git a/lib/uefi/relocation.cpp b/lib/uefi/relocation.cpp index 6279cce760..8519baffe6 100644 --- a/lib/uefi/relocation.cpp +++ b/lib/uefi/relocation.cpp @@ -77,24 +77,23 @@ int relocate_image(char *image) { case EFI_IMAGE_REL_BASED_LOONGARCH64_MARK_LA: { // The next four instructions are used to load a 64 bit address, // relocate all of them + if (reinterpret_cast(Fixup32) + 4 * sizeof(uint32_t) > image + optional_header->SizeOfImage) { + printf("Relocation out of bounds\n"); + return -1; + } + uint64_t Value = - (*Fixup32 & 0x1ffffe0) << 7 | // lu12i.w 20bits from bit5 + (*(Fixup32 + 0) & 0x1ffffe0) << 7 | // lu12i.w 20bits from bit5 (*(Fixup32 + 1) & 0x3ffc00) >> 10; // ori 12bits from bit10 uint64_t Tmp1 = *(Fixup32 + 2) & 0x1ffffe0; // lu32i.d 20bits from bit5 uint64_t Tmp2 = *(Fixup32 + 3) & 0x3ffc00; // lu52i.d 12bits from bit10 Value = Value | (Tmp1 << 27) | (Tmp2 << 42); Value += Adjust; - *Fixup32 = (*Fixup32 & ~0x1ffffe0) | (((Value >> 12) & 0xfffff) << 5); - - Fixup += sizeof(uint32_t); - *Fixup32 = (*Fixup32 & ~0x3ffc00) | ((Value & 0xfff) << 10); - - Fixup += sizeof(uint32_t); - *Fixup32 = (*Fixup32 & ~0x1ffffe0) | (((Value >> 32) & 0xfffff) << 5); - - Fixup += sizeof(uint32_t); - *Fixup32 = (*Fixup32 & ~0x3ffc00) | (((Value >> 52) & 0xfff) << 10); + *(Fixup32 + 0) = (*(Fixup32 + 0) & ~0x1ffffe0) | (((Value >> 12) & 0xfffff) << 5); + *(Fixup32 + 1) = (*(Fixup32 + 1) & ~0x3ffc00) | ((Value & 0xfff) << 10); + *(Fixup32 + 2) = (*(Fixup32 + 2) & ~0x1ffffe0) | (((Value >> 32) & 0xfffff) << 5); + *(Fixup32 + 3) = (*(Fixup32 + 3) & ~0x3ffc00) | (((Value >> 52) & 0xfff) << 10); break; } default: diff --git a/lib/uefi/uefi.cpp b/lib/uefi/uefi.cpp index 91681bcdf4..77bde8fe39 100644 --- a/lib/uefi/uefi.cpp +++ b/lib/uefi/uefi.cpp @@ -44,6 +44,7 @@ #include "runtime_service_provider.h" #include "switch_stack.h" #include "text_protocol.h" +#include "uefi/types.h" #include "uefi_platform.h" #include "variable_mem.h" @@ -130,7 +131,7 @@ int load_sections_and_execute(ImageReader *reader, } for (size_t i = 0; i < sections; i++) { if (section_header[i].NumberOfRelocations != 0) { - printf("Section %s requires relocation, which is not supported.\n", + printf("Section %.8s requires relocation, which is not supported.\n", section_header[i].Name); return ERR_NOT_SUPPORTED; } @@ -153,8 +154,8 @@ int load_sections_and_execute(ImageReader *reader, DEFER { free_pages(image_base, virtual_size / PAGE_SIZE); }; ssize_t bytes_read = reader->read(image_base, 0, section_header[0].PointerToRawData); - if (bytes_read != section_header[0].SizeOfRawData) { - printf("Failed to read section %s\n", section_header[0].Name); + if (bytes_read != static_cast(section_header[0].PointerToRawData)) { + printf("Failed to read PE headers before first section\n"); return ERR_IO; } @@ -163,7 +164,7 @@ int load_sections_and_execute(ImageReader *reader, bytes_read = reader->read(image_base + section.VirtualAddress, section.PointerToRawData, section.SizeOfRawData); if (bytes_read != section.SizeOfRawData) { - printf("Failed to read section %s %zu\n", section.Name, bytes_read); + printf("Failed to read section %.8s %zd\n", section.Name, bytes_read); return ERR_IO; } } @@ -183,7 +184,7 @@ int load_sections_and_execute(ImageReader *reader, fill(&boot_service, 0); setup_runtime_service_table(&runtime_service); setup_boot_service_table(&boot_service); - table.firmware_vendor = reinterpret_cast(firmwareVendor); + table.firmware_vendor = reinterpret_cast(firmwareVendor); table.runtime_services = &runtime_service; table.boot_services = &boot_service; table.header.signature = EFI_SYSTEM_TABLE_SIGNATURE; @@ -208,6 +209,7 @@ int load_sections_and_execute(ImageReader *reader, } char path[FS_MAX_PATH_LEN]; reader->get_name(path, sizeof(path)); + path[sizeof(path) - 1] = '\0'; setup_debug_support(table, image_base, virtual_size, path); constexpr size_t kStackSize = 1 * 1024ul * 1024; @@ -276,10 +278,12 @@ int load_pe_file(ImageReader *reader) { } DEFER { free(address); }; ssize_t err = reader->read(reinterpret_cast(address), 0, kBlocKSize); - t = current_time() - t; + // Prevent divide by 0 errors + t = MAX(current_time() - t, 1); if (err < 0) { char name[128]; reader->get_name(name, sizeof(name)); + name[sizeof(name) - 1] = '\0'; printf("error reading PE header from %s: %zd\n", name, err); return ERR_IO; } @@ -306,6 +310,7 @@ int load_pe_file(ImageReader *reader) { if (file_header->Machine != ArchitectureType::ARM64) { printf("Unsupported PE header machine type: %x\n", static_cast(file_header->Machine)); + return ERR_NOT_SUPPORTED; } if (file_header->SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER64) || file_header->SizeOfOptionalHeader <