diff options
| author | Tom Rini <[email protected]> | 2026-06-22 16:42:41 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-06-22 16:42:41 -0600 |
| commit | 9f16b258e5632d74fa4a1c2c93bea4474e05234b (patch) | |
| tree | d7c5baa0d3c6027e9e43b16030e4e0ecd43b9d77 /lib | |
| parent | 298d44464dc63a4f3f5489150acd7958f359f9bd (diff) | |
| parent | f072620dc9ffda00b010783da27c41231c3a439b (diff) | |
Merge tag 'v2026.07-rc5' into next
Prepare v2026.07-rc5
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig | 2 | ||||
| -rw-r--r-- | lib/efi_loader/efi_disk.c | 1 | ||||
| -rw-r--r-- | lib/efi_loader/efi_image_loader.c | 86 | ||||
| -rw-r--r-- | lib/efi_loader/efi_var_common.c | 4 | ||||
| -rw-r--r-- | lib/efi_selftest/efi_selftest_loaded_image.c | 4 | ||||
| -rw-r--r-- | lib/efi_selftest/efi_selftest_memory.c | 17 |
6 files changed, 91 insertions, 23 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index cf13ac1bdad..9e0f0ad7d06 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1298,7 +1298,7 @@ config SPL_LMB_ARCH_MEM_MAP config LMB_LIMIT_DMA_BELOW_RAM_TOP bool depends on LMB - default y if ARCH_BCM283X + default y if ARCH_BCM283X || ARCH_ROCKCHIP help Some architectures can not DMA above ram_top boundary, which is after 4 GiB or 32-bit boundary too. Limit the diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index f8a57539ec6..4a3ace3a304 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -305,6 +305,7 @@ static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this) } static const struct efi_block_io block_io_disk_template = { + .revision = EFI_BLOCK_IO_PROTOCOL_REVISION3, .reset = &efi_disk_reset, .read_blocks = &efi_disk_read_blocks, .write_blocks = &efi_disk_write_blocks, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index d002eb0c744..f9a2d2df405 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -108,11 +108,13 @@ void efi_print_image_infos(void *pc) * @rel_size: size of the relocation table in bytes * @efi_reloc: actual load address of the image * @pref_address: preferred load address of the image + * @virt_size: virtual image size as provided in the PE-COFF header * Return: status code */ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, - unsigned long rel_size, void *efi_reloc, - unsigned long pref_address) + unsigned long rel_size, void *efi_reloc, + unsigned long pref_address, + unsigned long virt_size) { unsigned long delta = (unsigned long)efi_reloc - pref_address; const IMAGE_BASE_RELOCATION *end; @@ -122,34 +124,95 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, return EFI_SUCCESS; end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size); - while (rel + 1 < end && rel->SizeOfBlock) { + while (rel + 1 < end) { const uint16_t *relocs = (const uint16_t *)(rel + 1); + + /* Each block must start on a 32-bit boundary */ + if (!IS_ALIGNED((uintptr_t)rel, sizeof(uint32_t))) { + log_debug("Relocation block not 32-bit aligned\n"); + return EFI_LOAD_ERROR; + } + /* Relocation block cannot be shorter than its header */ + if (rel->SizeOfBlock < sizeof(*rel)) { + log_debug("Relocation block too small: %u\n", + rel->SizeOfBlock); + return EFI_LOAD_ERROR; + } + /* All relocation entries must be inside the .reloc section */ + if ((const char *)rel + rel->SizeOfBlock > (const char *)end) { + log_debug("Relocation block exceeds relocation data\n"); + return EFI_LOAD_ERROR; + } + /* + * Relocations must be within the virtual address range. + * This also ensures that there is no overflow in the + * entry_offset check below. + */ + if (rel->VirtualAddress > virt_size) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } + i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t); while (i--) { - uint32_t offset = (uint32_t)(*relocs & 0xfff) + - rel->VirtualAddress; + uint32_t entry_offset = *relocs & 0xfff; + unsigned long offset; int type = *relocs >> EFI_PAGE_SHIFT; - uint64_t *x64 = efi_reloc + offset; - uint32_t *x32 = efi_reloc + offset; - uint16_t *x16 = efi_reloc + offset; + uint64_t *x64; + uint32_t *x32; + uint16_t *x16; + + /* + * Relocation address must be within virtual address + * range. + */ + if (entry_offset > virt_size - rel->VirtualAddress) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } + + offset = rel->VirtualAddress + entry_offset; + x64 = efi_reloc + offset; + x32 = efi_reloc + offset; + x16 = efi_reloc + offset; switch (type) { case IMAGE_REL_BASED_ABSOLUTE: break; case IMAGE_REL_BASED_HIGH: + if (sizeof(uint16_t) > virt_size - offset) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } *x16 += ((uint32_t)delta) >> 16; break; case IMAGE_REL_BASED_LOW: + if (sizeof(uint16_t) > virt_size - offset) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } *x16 += (uint16_t)delta; break; case IMAGE_REL_BASED_HIGHLOW: + if (sizeof(uint32_t) > virt_size - offset) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } *x32 += (uint32_t)delta; break; case IMAGE_REL_BASED_DIR64: + if (sizeof(uint64_t) > virt_size - offset) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } *x64 += (uint64_t)delta; break; #ifdef __riscv case IMAGE_REL_BASED_RISCV_HI20: + if (sizeof(uint32_t) > virt_size - offset) { + log_debug("relocation address out of bounds\n"); + return EFI_LOAD_ERROR; + } *x32 = ((*x32 & 0xfffff000) + (uint32_t)delta) | (*x32 & 0x00000fff); break; @@ -163,7 +226,7 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, break; #endif default: - log_err("Unknown Relocation off %x type %x\n", + log_err("Unknown Relocation off %lx type %x\n", offset, type); return EFI_LOAD_ERROR; } @@ -970,8 +1033,9 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, /* Run through relocations */ if (efi_loader_relocate(rel, rel_size, efi_reloc, - (unsigned long)image_base) != EFI_SUCCESS) { - efi_free_pages((uintptr_t) efi_reloc, + (unsigned long)image_base, + virt_size) != EFI_SUCCESS) { + efi_free_pages((uintptr_t)efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); ret = EFI_LOAD_ERROR; goto err; diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index d63c2d1b1cd..e51b21fe0b0 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -446,8 +446,10 @@ efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t * efi_status_t ret; if ((uintptr_t)buf + len <= - (uintptr_t)var->name + old_var_name_length) + (uintptr_t)var->name + old_var_name_length) { + free(buf); return EFI_BUFFER_TOO_SMALL; + } var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name; memcpy(var->name, old_var->name, old_var_name_length); diff --git a/lib/efi_selftest/efi_selftest_loaded_image.c b/lib/efi_selftest/efi_selftest_loaded_image.c index 5889ab12617..e0668f60ebd 100644 --- a/lib/efi_selftest/efi_selftest_loaded_image.c +++ b/lib/efi_selftest/efi_selftest_loaded_image.c @@ -60,8 +60,8 @@ static int execute(void) efi_st_printf("%u protocols installed on image handle\n", (unsigned int)protocol_buffer_count); for (i = 0; i < protocol_buffer_count; ++i) { - if (memcmp(protocol_buffer[i], &loaded_image_protocol_guid, - sizeof(efi_guid_t))) + if (!memcmp(protocol_buffer[i], &loaded_image_protocol_guid, + sizeof(efi_guid_t))) found = true; } if (!found) { diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c index 7320964c129..450470ceedd 100644 --- a/lib/efi_selftest/efi_selftest_memory.c +++ b/lib/efi_selftest/efi_selftest_memory.c @@ -155,6 +155,15 @@ static int execute(void) EFI_RUNTIME_SERVICES_DATA) != EFI_ST_SUCCESS) return EFI_ST_FAILURE; + /* Check memory reservation for the device tree */ + if (fdt_addr && + find_in_memory_map(map_size, memory_map, desc_size, fdt_addr, + EFI_ACPI_RECLAIM_MEMORY) != EFI_ST_SUCCESS) { + efi_st_error + ("Device tree not marked as ACPI reclaim memory\n"); + return EFI_ST_FAILURE; + } + /* Free memory */ ret = boottime->free_pages(p1, EFI_ST_NUM_PAGES); if (ret != EFI_SUCCESS) { @@ -172,14 +181,6 @@ static int execute(void) return EFI_ST_FAILURE; } - /* Check memory reservation for the device tree */ - if (fdt_addr && - find_in_memory_map(map_size, memory_map, desc_size, fdt_addr, - EFI_ACPI_RECLAIM_MEMORY) != EFI_ST_SUCCESS) { - efi_st_error - ("Device tree not marked as ACPI reclaim memory\n"); - return EFI_ST_FAILURE; - } return EFI_ST_SUCCESS; } |
