[BUG] U-Boot can overwrite itself with "bootelf" command

Hi,
(please CC: me for replies, because I'm not subscribed to the list)
While debugging a U-Boot 2022.10 hang on an NXP i.MX8 board during execution of the the "bootelf" command, I discovered the following general problem:
1) I have an aarch64 ELF binary that looks as follows:
Program Header: LOAD off 0x00000000000000b0 vaddr 0x00000000ff000000 paddr 0x00000000ff000000 align 2**3 filesz 0x000000000000086c memsz 0x0000000000001000 flags rw- LOAD off 0x0000000000001000 vaddr 0x0000ff8000001000 paddr 0x00000000ff001000 align 2**11 filesz 0x000000000000f4dc memsz 0x0000000000fff000 flags rw-
The second PHDR includes a rather large (~16MB) BSS that extends all the way up to the very end of DRAM.
2) U-Boot relocates itself to the end of DRAM (as per bdinfo):
relocaddr = 0x00000000fff2c000 reloc off = 0x00000000bfd2c000 Build = 64-bit
3) When the ELF image from (1) is TFTP'd into memory (at some address <addr>) and then launched via "bootelf -p <addr>", U-Boot does not detect the conflict with its own image (2) and happily overwrites itself (causing the board to hang).
The code in question that does the overwriting is in lib/elf.c in unsigned long load_elf64_image_phdr(unsigned long addr) here:
/* Load each program header */ for (i = 0; i < ehdr->e_phnum; ++i) { void *dst = (void *)(ulong)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset;
debug("Loading phdr %i to 0x%p (%lu bytes)\n", i, dst, (ulong)phdr->p_filesz); if (phdr->p_filesz) memcpy(dst, src, phdr->p_filesz); if (phdr->p_filesz != phdr->p_memsz) ==> memset(dst + phdr->p_filesz, 0x00, phdr->p_memsz - phdr->p_filesz); flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); ++phdr; }
IMHO U-Boot should refuse to load anything into the address range where U-Boot itself lives.
Cheers, Udo
participants (1)
-
Udo Steinberg