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

Udo Steinberg udo at hypervisor.org
Tue Oct 4 21:36:04 CEST 2022


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


More information about the U-Boot mailing list