]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
lib: elf: Fix bootelf -p crash issue
authorJianfengA.Zhu@sony.com <JianfengA.Zhu@sony.com>
Wed, 7 Aug 2024 02:20:07 +0000 (02:20 +0000)
committerTom Rini <trini@konsulko.com>
Thu, 15 Aug 2024 20:26:59 +0000 (14:26 -0600)
Do not load and flush segments whose program header type is not
PT_LOAD to avoid crash happen.

bootelf will load all program headers and then flush cache.
Since PT_GNU_STACK start address is 0x0, crash happens when
it flushes PT_GNU_STACK area for target that memory cannot be
accessed from address 0x0.

crash call stack:
====================================================================
bootelf -p
|-> do_bootelf (cmd/elf.c)
 |-> load_elf_image_phdr (lib/elf.c) /* Load each program header */
  |-> for (i = 0; i < ehdr->e_phnum; ++i) { /* e_phnum is 2 */
   |-> flush_cache(start=0, size=0) (arch/arm/lib/cache.c) (*1)
    |-> flush_dcache_range(start=0, 0); (arch/arm/cpu/armv8/cache_v8.c)
     |-> __asm_flush_dcache_range(start=0, 0) (arch/arm/cpu/armv8/cache.S)
      |-> /* clean & invalidate data or unified cache */
      |-> dc      civac, x0       <<== crash happen x0:start=0
====================================================================
*1 Here the p_paddr and p_filesz of the GNU_STACK program are 0.

hello_world elf image program headers
====================================================================
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000080ff0000 0x0000000080ff0000
                 0x0000000000010390 0x0000000000010390  R E    0x10000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata .eh_frame
   01
====================================================================

bootelf -p crash error log
====================================================================
bootelf -p 0x80f00000
"Synchronous Abort" handler, esr 0x96000147, far 0x0
elr: 000000008f6035bc lr : 000000008f66ff54 (reloc)
elr: 00000000bd9475bc lr : 00000000bd9b3f54
x0 : 0000000000000000 x1 : 0000000000000000
x2 : 0000000000000040 x3 : 000000000000003f
x4 : 0000000081000390 x5 : 00000000bd12da98
x6 : 0000000000000010 x7 : 0000000000000010
x8 : 000000000000000a x9 : 00000000bd156b30
x10: 00000000bd1526e0 x11: 0000000000000000
x12: 0000000000000004 x13: 00000000bda00000
x14: 00000000ffffffff x15: 00000000bd12dab7
x16: 00000000bd957b14 x17: 0000000000000000
x18: 00000000bd13fd90 x19: 0000000080f000b0
x20: 0000000080f00000 x21: 0000000000000002
x22: 0000000000000000 x23: 0000000000000003
x24: 00000000bd9eacc0 x25: 0000000000000000
x26: 0000000000000000 x27: 0000000000000000
x28: 00000000bd154c80 x29: 00000000bd12da70

Code: d2800082 9ac32042 d1000443 8a230000 (d50b7e20)
====================================================================

Signed-off-by: Jianfeng Zhu <JianfengA.Zhu@sony.com>
Reviewed-by: Jacky Cao <Jacky.Cao@sony.com>
Reviewed-by: Toyama, Yoshihiro <Yoshihiro.Toyama@sony.com>
lib/elf.c

index dc13935e1035107630e800fa15be46e8f49edc61..28ec87b8e4827537a0e8122fd55d0facdf7b9c02 100644 (file)
--- a/lib/elf.c
+++ b/lib/elf.c
@@ -90,6 +90,10 @@ unsigned long load_elf64_image_phdr(unsigned long addr)
                void *dst = (void *)(ulong)phdr->p_paddr;
                void *src = (void *)addr + phdr->p_offset;
 
+               /* Only load PT_LOAD program header */
+               if (phdr->p_type != PT_LOAD)
+                       continue;
+
                debug("Loading phdr %i to 0x%p (%lu bytes)\n",
                      i, dst, (ulong)phdr->p_filesz);
                if (phdr->p_filesz)
@@ -205,6 +209,10 @@ unsigned long load_elf_image_phdr(unsigned long addr)
                void *dst = (void *)(uintptr_t)phdr->p_paddr;
                void *src = (void *)addr + phdr->p_offset;
 
+               /* Only load PT_LOAD program header */
+               if (phdr->p_type != PT_LOAD)
+                       continue;
+
                debug("Loading phdr %i to 0x%p (%i bytes)\n",
                      i, dst, phdr->p_filesz);
                if (phdr->p_filesz)