summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-06-22 16:42:41 -0600
committerTom Rini <[email protected]>2026-06-22 16:42:41 -0600
commit9f16b258e5632d74fa4a1c2c93bea4474e05234b (patch)
treed7c5baa0d3c6027e9e43b16030e4e0ecd43b9d77 /lib
parent298d44464dc63a4f3f5489150acd7958f359f9bd (diff)
parentf072620dc9ffda00b010783da27c41231c3a439b (diff)
Merge tag 'v2026.07-rc5' into next
Prepare v2026.07-rc5
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig2
-rw-r--r--lib/efi_loader/efi_disk.c1
-rw-r--r--lib/efi_loader/efi_image_loader.c86
-rw-r--r--lib/efi_loader/efi_var_common.c4
-rw-r--r--lib/efi_selftest/efi_selftest_loaded_image.c4
-rw-r--r--lib/efi_selftest/efi_selftest_memory.c17
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;
}