Public bug reported:

static pie binaries may not get a reasonable brk,
with glibc this means they crash in early tls setup code:
https://sourceware.org/bugzilla/show_bug.cgi?id=24152

qemu seems to put brk at the end of the data segment,
but if the stack starts (ends) right next to it then
allocation with brk fails.

in such situation i think qemu should arrange the
stack or brk to be elsewhere so there is plenty
space to grow (in case of glibc it's enough if tls
setup works: later allocations can fall back to mmap).

(ubuntu bionic x86_64 ldconfig.real from libc-bin package)
$ qemu-x86_64 -strace -d page /sbin/ldconfig.real
host mmap_min_addr=0x8000
guest_base  0x0
start            end              size             prot
0000004000000000-00000040000f2000 00000000000f2000 r-x
00000040000f2000-00000040002f2000 0000000000200000 ---
00000040002f2000-00000040002fa000 0000000000008000 rw-
00000040002fa000-00000040002fb000 0000000000001000 ---
00000040002fb000-0000004000afb000 0000000000800000 rw-
start_brk   0x0000000000000000
end_code    0x00000040000f1ee8
start_code  0x0000004000000000
start_data  0x00000040002f2838
end_data    0x00000040002f8518
start_stack 0x0000004000afa130
brk         0x00000040002f9dd8
entry       0x0000004000009bc0
argv_start  0x0000004000afa138
env_start   0x0000004000afa148
auxv_start  0x0000004000afa280
28561 brk(NULL) = 0x00000040002fa000
28561 brk(0x00000040002fb1c0) = 0x00000040002fa000
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0xffffffffffffffc0} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

$ readelf -hldSW /tmp/ldconfig.real
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x9bc0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          1022920 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         38
  Section header string table index: 37

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg 
Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      
0   0  0
  [ 1] .note.ABI-tag     NOTE            0000000000000200 000200 000020 00   A  
0   0  4
  [ 2] .note.gnu.build-id NOTE            0000000000000220 000220 000024 00   A 
 0   0  4
  [ 3] .gnu.hash         GNU_HASH        0000000000000248 000248 00001c 00   A  
4   0  8
  [ 4] .dynsym           DYNSYM          0000000000000268 000268 000018 18   A  
5   1  8
  [ 5] .dynstr           STRTAB          0000000000000280 000280 000001 00   A  
0   0  1
  [ 6] .rela.dyn         RELA            0000000000000288 000288 008748 18   A  
4   0  8
  [ 7] .rela.plt         RELA            00000000000089d0 0089d0 000318 18  AI  
4  27  8
  [ 8] .init             PROGBITS        0000000000008ce8 008ce8 000017 00  AX  
0   0  4
  [ 9] .plt              PROGBITS        0000000000008d00 008d00 000270 10  AX  
0   0 16
  [10] .plt.got          PROGBITS        0000000000008f70 008f70 000060 08  AX  
0   0  8
  [11] .text             PROGBITS        0000000000008fd0 008fd0 0bd29c 00  AX  
0   0 16
  [12] __libc_freeres_fn PROGBITS        00000000000c6270 0c6270 0016b3 00  AX  
0   0 16
  [13] __libc_thread_freeres_fn PROGBITS        00000000000c7930 0c7930 00108f 
00  AX  0   0 16
  [14] .fini             PROGBITS        00000000000c89c0 0c89c0 000009 00  AX  
0   0  4
  [15] .rodata           PROGBITS        00000000000c89e0 0c89e0 01af08 00   A  
0   0 32
  [16] .stapsdt.base     PROGBITS        00000000000e38e8 0e38e8 000001 00   A  
0   0  1
  [17] .eh_frame_hdr     PROGBITS        00000000000e38ec 0e38ec 001f94 00   A  
0   0  4
  [18] .eh_frame         PROGBITS        00000000000e5880 0e5880 00c5b8 00   A  
0   0  8
  [19] .gcc_except_table PROGBITS        00000000000f1e38 0f1e38 0000b0 00   A  
0   0  1
  [20] .tdata            PROGBITS        00000000002f2838 0f2838 000028 00 WAT  
0   0  8
  [21] .tbss             NOBITS          00000000002f2860 0f2860 000040 00 WAT  
0   0  8
  [22] .init_array       INIT_ARRAY      00000000002f2860 0f2860 000010 08  WA  
0   0  8
  [23] .fini_array       FINI_ARRAY      00000000002f2870 0f2870 000010 08  WA  
0   0  8
  [24] .data.rel.ro      PROGBITS        00000000002f2880 0f2880 0034c4 00  WA  
0   0 32
  [25] .dynamic          DYNAMIC         00000000002f5d48 0f5d48 0001a0 10  WA  
5   0  8
  [26] .got              PROGBITS        00000000002f5ee8 0f5ee8 000110 08  WA  
0   0  8
  [27] .got.plt          PROGBITS        00000000002f6000 0f6000 000148 08  WA  
0   0  8
  [28] .data             PROGBITS        00000000002f6160 0f6160 001bd4 00  WA  
0   0 32
  [29] __libc_subfreeres PROGBITS        00000000002f7d38 0f7d38 000060 00  WA  
0   0  8
  [30] __libc_IO_vtables PROGBITS        00000000002f7da0 0f7da0 000768 00  WA  
0   0 32
  [31] __libc_atexit     PROGBITS        00000000002f8508 0f8508 000008 00  WA  
0   0  8
  [32] __libc_thread_subfreeres PROGBITS        00000000002f8510 0f8510 000008 
00  WA  0   0  8
  [33] .bss              NOBITS          00000000002f8520 0f8518 001890 00  WA  
0   0 32
  [34] __libc_freeres_ptrs NOBITS          00000000002f9db0 0f8518 000028 00  
WA  0   0  8
  [35] .note.stapsdt     NOTE            0000000000000000 0f8518 0014cc 00      
0   0  4
  [36] .gnu_debuglink    PROGBITS        0000000000000000 0f99e4 000034 00      
0   0  4
  [37] .shstrtab         STRTAB          0000000000000000 0f9a18 0001ab 00      
0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz 
  Flg Align
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0f1ee8 
0x0f1ee8 R E 0x200000
  LOAD           0x0f2838 0x00000000002f2838 0x00000000002f2838 0x005ce0 
0x0075a0 RW  0x200000
  DYNAMIC        0x0f5d48 0x00000000002f5d48 0x00000000002f5d48 0x0001a0 
0x0001a0 RW  0x8
  NOTE           0x000200 0x0000000000000200 0x0000000000000200 0x000044 
0x000044 R   0x4
  TLS            0x0f2838 0x00000000002f2838 0x00000000002f2838 0x000028 
0x000068 R   0x8
  GNU_EH_FRAME   0x0e38ec 0x00000000000e38ec 0x00000000000e38ec 0x001f94 
0x001f94 R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 
0x000000 RW  0x10
  GNU_RELRO      0x0f2838 0x00000000002f2838 0x00000000002f2838 0x0037c8 
0x0037c8 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn 
.rela.plt .init .plt .plt.got .text __libc_freeres_fn __libc_thread_freeres_fn 
.fini .rodata .stapsdt.base .eh_frame_hdr .eh_frame .gcc_except_table 
   01     .tdata .init_array .fini_array .data.rel.ro .dynamic .got .got.plt 
.data __libc_subfreeres __libc_IO_vtables __libc_atexit 
__libc_thread_subfreeres .bss __libc_freeres_ptrs 
   02     .dynamic 
   03     .note.ABI-tag .note.gnu.build-id 
   04     .tdata .tbss 
   05     .eh_frame_hdr 
   06     
   07     .tdata .init_array .fini_array .data.rel.ro .dynamic .got 

Dynamic section at offset 0xf5d48 contains 22 entries:
  Tag        Type                         Name/Value
 0x000000000000000c (INIT)               0x8ce8
 0x000000000000000d (FINI)               0xc89c0
 0x0000000000000019 (INIT_ARRAY)         0x2f2860
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x2f2870
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x248
 0x0000000000000005 (STRTAB)             0x280
 0x0000000000000006 (SYMTAB)             0x268
 0x000000000000000a (STRSZ)              1 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x2f6000
 0x0000000000000002 (PLTRELSZ)           792 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x89d0
 0x0000000000000007 (RELA)               0x288
 0x0000000000000008 (RELASZ)             34632 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffb (FLAGS_1)            Flags: PIE
 0x000000006ffffff9 (RELACOUNT)          1443
 0x0000000000000000 (NULL)               0x0

** Affects: qemu
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1814128

Title:
  qemu-user fails to set up a reasonable brk for static-pie

Status in QEMU:
  New

Bug description:
  static pie binaries may not get a reasonable brk,
  with glibc this means they crash in early tls setup code:
  https://sourceware.org/bugzilla/show_bug.cgi?id=24152

  qemu seems to put brk at the end of the data segment,
  but if the stack starts (ends) right next to it then
  allocation with brk fails.

  in such situation i think qemu should arrange the
  stack or brk to be elsewhere so there is plenty
  space to grow (in case of glibc it's enough if tls
  setup works: later allocations can fall back to mmap).

  (ubuntu bionic x86_64 ldconfig.real from libc-bin package)
  $ qemu-x86_64 -strace -d page /sbin/ldconfig.real
  host mmap_min_addr=0x8000
  guest_base  0x0
  start            end              size             prot
  0000004000000000-00000040000f2000 00000000000f2000 r-x
  00000040000f2000-00000040002f2000 0000000000200000 ---
  00000040002f2000-00000040002fa000 0000000000008000 rw-
  00000040002fa000-00000040002fb000 0000000000001000 ---
  00000040002fb000-0000004000afb000 0000000000800000 rw-
  start_brk   0x0000000000000000
  end_code    0x00000040000f1ee8
  start_code  0x0000004000000000
  start_data  0x00000040002f2838
  end_data    0x00000040002f8518
  start_stack 0x0000004000afa130
  brk         0x00000040002f9dd8
  entry       0x0000004000009bc0
  argv_start  0x0000004000afa138
  env_start   0x0000004000afa148
  auxv_start  0x0000004000afa280
  28561 brk(NULL) = 0x00000040002fa000
  28561 brk(0x00000040002fb1c0) = 0x00000040002fa000
  --- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0xffffffffffffffc0} ---
  qemu: uncaught target signal 11 (Segmentation fault) - core dumped

  $ readelf -hldSW /tmp/ldconfig.real
  ELF Header:
    Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00 
    Class:                             ELF64
    Data:                              2's complement, little endian
    Version:                           1 (current)
    OS/ABI:                            UNIX - GNU
    ABI Version:                       0
    Type:                              DYN (Shared object file)
    Machine:                           Advanced Micro Devices X86-64
    Version:                           0x1
    Entry point address:               0x9bc0
    Start of program headers:          64 (bytes into file)
    Start of section headers:          1022920 (bytes into file)
    Flags:                             0x0
    Size of this header:               64 (bytes)
    Size of program headers:           56 (bytes)
    Number of program headers:         8
    Size of section headers:           64 (bytes)
    Number of section headers:         38
    Section header string table index: 37

  Section Headers:
    [Nr] Name              Type            Address          Off    Size   ES 
Flg Lk Inf Al
    [ 0]                   NULL            0000000000000000 000000 000000 00    
  0   0  0
    [ 1] .note.ABI-tag     NOTE            0000000000000200 000200 000020 00   
A  0   0  4
    [ 2] .note.gnu.build-id NOTE            0000000000000220 000220 000024 00   
A  0   0  4
    [ 3] .gnu.hash         GNU_HASH        0000000000000248 000248 00001c 00   
A  4   0  8
    [ 4] .dynsym           DYNSYM          0000000000000268 000268 000018 18   
A  5   1  8
    [ 5] .dynstr           STRTAB          0000000000000280 000280 000001 00   
A  0   0  1
    [ 6] .rela.dyn         RELA            0000000000000288 000288 008748 18   
A  4   0  8
    [ 7] .rela.plt         RELA            00000000000089d0 0089d0 000318 18  
AI  4  27  8
    [ 8] .init             PROGBITS        0000000000008ce8 008ce8 000017 00  
AX  0   0  4
    [ 9] .plt              PROGBITS        0000000000008d00 008d00 000270 10  
AX  0   0 16
    [10] .plt.got          PROGBITS        0000000000008f70 008f70 000060 08  
AX  0   0  8
    [11] .text             PROGBITS        0000000000008fd0 008fd0 0bd29c 00  
AX  0   0 16
    [12] __libc_freeres_fn PROGBITS        00000000000c6270 0c6270 0016b3 00  
AX  0   0 16
    [13] __libc_thread_freeres_fn PROGBITS        00000000000c7930 0c7930 
00108f 00  AX  0   0 16
    [14] .fini             PROGBITS        00000000000c89c0 0c89c0 000009 00  
AX  0   0  4
    [15] .rodata           PROGBITS        00000000000c89e0 0c89e0 01af08 00   
A  0   0 32
    [16] .stapsdt.base     PROGBITS        00000000000e38e8 0e38e8 000001 00   
A  0   0  1
    [17] .eh_frame_hdr     PROGBITS        00000000000e38ec 0e38ec 001f94 00   
A  0   0  4
    [18] .eh_frame         PROGBITS        00000000000e5880 0e5880 00c5b8 00   
A  0   0  8
    [19] .gcc_except_table PROGBITS        00000000000f1e38 0f1e38 0000b0 00   
A  0   0  1
    [20] .tdata            PROGBITS        00000000002f2838 0f2838 000028 00 
WAT  0   0  8
    [21] .tbss             NOBITS          00000000002f2860 0f2860 000040 00 
WAT  0   0  8
    [22] .init_array       INIT_ARRAY      00000000002f2860 0f2860 000010 08  
WA  0   0  8
    [23] .fini_array       FINI_ARRAY      00000000002f2870 0f2870 000010 08  
WA  0   0  8
    [24] .data.rel.ro      PROGBITS        00000000002f2880 0f2880 0034c4 00  
WA  0   0 32
    [25] .dynamic          DYNAMIC         00000000002f5d48 0f5d48 0001a0 10  
WA  5   0  8
    [26] .got              PROGBITS        00000000002f5ee8 0f5ee8 000110 08  
WA  0   0  8
    [27] .got.plt          PROGBITS        00000000002f6000 0f6000 000148 08  
WA  0   0  8
    [28] .data             PROGBITS        00000000002f6160 0f6160 001bd4 00  
WA  0   0 32
    [29] __libc_subfreeres PROGBITS        00000000002f7d38 0f7d38 000060 00  
WA  0   0  8
    [30] __libc_IO_vtables PROGBITS        00000000002f7da0 0f7da0 000768 00  
WA  0   0 32
    [31] __libc_atexit     PROGBITS        00000000002f8508 0f8508 000008 00  
WA  0   0  8
    [32] __libc_thread_subfreeres PROGBITS        00000000002f8510 0f8510 
000008 00  WA  0   0  8
    [33] .bss              NOBITS          00000000002f8520 0f8518 001890 00  
WA  0   0 32
    [34] __libc_freeres_ptrs NOBITS          00000000002f9db0 0f8518 000028 00  
WA  0   0  8
    [35] .note.stapsdt     NOTE            0000000000000000 0f8518 0014cc 00    
  0   0  4
    [36] .gnu_debuglink    PROGBITS        0000000000000000 0f99e4 000034 00    
  0   0  4
    [37] .shstrtab         STRTAB          0000000000000000 0f9a18 0001ab 00    
  0   0  1
  Key to Flags:
    W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
    L (link order), O (extra OS processing required), G (group), T (TLS),
    C (compressed), x (unknown), o (OS specific), E (exclude),
    l (large), p (processor specific)

  Program Headers:
    Type           Offset   VirtAddr           PhysAddr           FileSiz  
MemSiz   Flg Align
    LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0f1ee8 
0x0f1ee8 R E 0x200000
    LOAD           0x0f2838 0x00000000002f2838 0x00000000002f2838 0x005ce0 
0x0075a0 RW  0x200000
    DYNAMIC        0x0f5d48 0x00000000002f5d48 0x00000000002f5d48 0x0001a0 
0x0001a0 RW  0x8
    NOTE           0x000200 0x0000000000000200 0x0000000000000200 0x000044 
0x000044 R   0x4
    TLS            0x0f2838 0x00000000002f2838 0x00000000002f2838 0x000028 
0x000068 R   0x8
    GNU_EH_FRAME   0x0e38ec 0x00000000000e38ec 0x00000000000e38ec 0x001f94 
0x001f94 R   0x4
    GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 
0x000000 RW  0x10
    GNU_RELRO      0x0f2838 0x00000000002f2838 0x00000000002f2838 0x0037c8 
0x0037c8 R   0x1

   Section to Segment mapping:
    Segment Sections...
     00     .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr 
.rela.dyn .rela.plt .init .plt .plt.got .text __libc_freeres_fn 
__libc_thread_freeres_fn .fini .rodata .stapsdt.base .eh_frame_hdr .eh_frame 
.gcc_except_table 
     01     .tdata .init_array .fini_array .data.rel.ro .dynamic .got .got.plt 
.data __libc_subfreeres __libc_IO_vtables __libc_atexit 
__libc_thread_subfreeres .bss __libc_freeres_ptrs 
     02     .dynamic 
     03     .note.ABI-tag .note.gnu.build-id 
     04     .tdata .tbss 
     05     .eh_frame_hdr 
     06     
     07     .tdata .init_array .fini_array .data.rel.ro .dynamic .got 

  Dynamic section at offset 0xf5d48 contains 22 entries:
    Tag        Type                         Name/Value
   0x000000000000000c (INIT)               0x8ce8
   0x000000000000000d (FINI)               0xc89c0
   0x0000000000000019 (INIT_ARRAY)         0x2f2860
   0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
   0x000000000000001a (FINI_ARRAY)         0x2f2870
   0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
   0x000000006ffffef5 (GNU_HASH)           0x248
   0x0000000000000005 (STRTAB)             0x280
   0x0000000000000006 (SYMTAB)             0x268
   0x000000000000000a (STRSZ)              1 (bytes)
   0x000000000000000b (SYMENT)             24 (bytes)
   0x0000000000000015 (DEBUG)              0x0
   0x0000000000000003 (PLTGOT)             0x2f6000
   0x0000000000000002 (PLTRELSZ)           792 (bytes)
   0x0000000000000014 (PLTREL)             RELA
   0x0000000000000017 (JMPREL)             0x89d0
   0x0000000000000007 (RELA)               0x288
   0x0000000000000008 (RELASZ)             34632 (bytes)
   0x0000000000000009 (RELAENT)            24 (bytes)
   0x000000006ffffffb (FLAGS_1)            Flags: PIE
   0x000000006ffffff9 (RELACOUNT)          1443
   0x0000000000000000 (NULL)               0x0

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1814128/+subscriptions

Reply via email to