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

Reply via email to