On Sun, 20 Jan 2019 17:55:00 +0000 Ben Hutchings <b...@decadent.org.uk> wrote: > Package: qemu-user > Version: 1:3.1+dfsg-2 > Severity: normal > Tags: patch > > I've been building and testing klibc across many architectures using > qemu-user, and I found that qemu-user fails to load a few programs on > a few architectures, reporting an EINVAL error code. Here's the > "readelf -l" output for one such program: > > Elf file type is EXEC (Executable file) > Entry point 0x10000100 > There are 5 program headers, starting at offset 52 > > Program Headers: > Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align > PHDR 0x000034 0x10000034 0x10000034 0x000a0 0x000a0 R 0x4 > INTERP 0x0000d4 0x100000d4 0x100000d4 0x0002a 0x0002a R 0x1 > [Requesting program interpreter: > /lib/klibc-R7FVdnsTBUFpWPgCV6FR07b-mf8.so] > LOAD 0x000000 0x10000000 0x10000000 0x002f8 0x002f8 R E > 0x10000 > LOAD 0x010000 0x10020000 0x10020000 0x00000 0x08000 RW > 0x10000 > GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10 > > Section to Segment mapping: > Segment Sections... > 00 > 01 .interp > 02 .interp .text .rodata .eh_frame > 03 .bss > 04 > > The unusual feature of this program, and all the others that failed, > is that there is a LOAD segment with a file-size of 0 (i.e. only BSS, > no initialised data). load_elf_image() will try to mmap() initialised > data for this section even though there is none and a length of 0 is > invalid. > > The change that seems to fix this is to skip the mmap() in this case: > > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -2316,11 +2316,13 @@ static void load_elf_image(const char *i > vaddr_ps = TARGET_ELF_PAGESTART(vaddr); > vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po); > > - error = target_mmap(vaddr_ps, vaddr_len, > - elf_prot, MAP_PRIVATE | MAP_FIXED, > - image_fd, eppnt->p_offset - vaddr_po); > - if (error == -1) { > - goto exit_perror; > + if (vaddr_len != 0) { > + error = target_mmap(vaddr_ps, vaddr_len, > + elf_prot, MAP_PRIVATE | MAP_FIXED, > + image_fd, eppnt->p_offset - vaddr_po); > + if (error == -1) { > + goto exit_perror; > + } > } > > vaddr_ef = vaddr + eppnt->p_filesz;
I see that qemu 4.1 have this commit: https://salsa.debian.org/qemu-team/qemu/-/commit/d87146bce08d3d2ea6c00025d7ee0bfa77991692 - error = target_mmap(vaddr_ps, vaddr_len, - elf_prot, MAP_PRIVATE | MAP_FIXED, - image_fd, eppnt->p_offset - vaddr_po); - if (error == -1) { - goto exit_perror; + /* + * Some segments may be completely empty without any backing file + * segment, in that case just let zero_bss allocate an empty buffer + * for it. + */ + if (eppnt->p_filesz != 0) { + error = target_mmap(vaddr_ps, vaddr_len, elf_prot, + MAP_PRIVATE | MAP_FIXED, + image_fd, eppnt->p_offset - vaddr_po); + + if (error == -1) { + goto exit_perror; + } } I'm not sure I understand what's going on here. This looks like a different case to me, maybe we still need to add the suggested condition (vaddr_len != 0) to the mix? Thanks, /mjt