Bug 48617

Summary: /usr/bin/qemu-aarch64.static /sbin/ldconfig Segmentation fault (core dumped)
Product: Sisyphus Reporter: Vitaly Chikunov <vt>
Component: glibc-coreAssignee: placeholder <placeholder>
Status: NEW --- QA Contact: qa-sisyphus
Severity: normal    
Priority: P5 CC: glebfm, iv, ldv, placeholder
Version: unstable   
Hardware: x86   
OS: Linux   

Description Vitaly Chikunov 2023-11-28 19:49:31 MSK
На x86_64 в hasher с p10 aarch64 под qemu-user-aarch64 (из Сизифа) ldconfig из p10 падает с Segmentation fault, при этом другие бинарники не падают.

Trace сисколлов средствами qemu-user:

bash-4.4$ /usr/bin/qemu-aarch64.static -strace /sbin/ldconfig
475550 brk(NULL) = 0x00007f4f0b759000
475550 brk(0x00007f4f0b759b38) = 0x00007f4f0b759000
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0000000000000038} ---
Segmentation fault (core dumped)

Сисколлы завершаются успешно, при этом второй вызов brk не выделяет память, после этого ldconfig падает.

Gdb:

1. Подкладываем /usr/bin/qemu-aarch64.static из системы внутрь хэшера, чтоб можно было его запустить. Затем
   hasher$ /usr/bin/qemu-aarch64.static -g 7777 /sbin/ldconfig

2. На aarch64 хосте (так как у нашего gdb на x86-64 нет архитектуры aarch64):
  aarch64$ hsh --ini
  aarch64$ hsh-install glibc-core-debuginfo
  aarch64$ gdb
  (gdb) set sysroot /home/vt/hasher/chroot
  (gdb) set substitute-path / /home/vt/hasher/chroot/
  (gdb) file /home/vt/hasher/chroot/sbin/ldconfig
  (gdb) target remote x.x.x.x:7777
```
_start () at ../sysdeps/aarch64/start.S:46
46      ENTRY(_start)
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x00007fe814288fe8 in __brk (addr=<optimized out>) at ../sysdeps/unix/sysv/linux/generic/brk.c:37
37            __set_errno (ENOMEM);
(gdb) bt
#0  0x00007fe814288fe8 in __brk (addr=<optimized out>) at ../sysdeps/unix/sysv/linux/generic/brk.c:37
#1  0x00007fe81426a0d8 in __sbrk (increment=2872) at sbrk.c:70
#2  __sbrk (increment=2872) at sbrk.c:32
#3  0x00007fe8142426c4 in __libc_setup_tls () at ../csu/libc-tls.c:148
#4  0x00007fe814242348 in __libc_start_main (main=0x7fe81423cfbc <_start+60>, argc=1, argv=0x400000800d88, init=0x7fe8142427f0 <__libc_csu_init>,
    fini=0x7fe8142428b0 <__libc_csu_fini>, rtld_fini=0x0, stack_end=<optimized out>) at ../csu/libc-start.c:197
#5  0x00007fe81423cfb8 in _start () at ../sysdeps/aarch64/start.S:91

(gdb) disas/s __brk
Dump of assembler code for function __brk:
../sysdeps/unix/sysv/linux/generic/brk.c:
33      {
34        __curbrk = (void *) INTERNAL_SYSCALL_CALL (brk, addr);
   0x00007fe814288fb0 <+0>:     mov     x1, x0
   0x00007fe814288fb4 <+4>:     mov     x8, #0xd6                       // #214
   0x00007fe814288fb8 <+8>:     svc     #0x0
   0x00007fe814288fbc <+12>:    adrp    x2, 0x7fe8142e3000 <initial+728>
   0x00007fe814288fc0 <+16>:    str     x0, [x2, #1104]

35        if (__curbrk < addr)
   0x00007fe814288fc4 <+20>:    cmp     x0, x1
   0x00007fe814288fc8 <+24>:    b.cc    0x7fe814288fd4 <__brk+36>  // b.lo, b.ul, b.last

39          }
40
41        return 0;
   0x00007fe814288fcc <+28>:    mov     w0, #0x0                        // #0

42      }
   0x00007fe814288fd0 <+32>:    ret

37            __set_errno (ENOMEM);
   0x00007fe814288fd4 <+36>:    adrp    x1, 0x7fe8142df000 <_nl_C_locobj+16>
   0x00007fe814288fd8 <+40>:    ldr     x1, [x1, #3504]
   0x00007fe814288fdc <+44>:    mrs     x2, tpidr_el0
   0x00007fe814288fe0 <+48>:    mov     w3, #0xc                        // #12

38            return -1;
   0x00007fe814288fe4 <+52>:    mov     w0, #0xffffffff                 // #-1

37            __set_errno (ENOMEM);
=> 0x00007fe814288fe8 <+56>:    str     w3, [x2, x1]

38            return -1;
   0x00007fe814288fec <+60>:    ret
End of assembler dump.

(gdb) i r w3 x1 x2
w3             0xc                 12
x1             0x38                56
x2             0x0                 0

```

Падает на инструкции `str     w3, [x2, x1]`

`12` это ENOMEM, `x2+x1` видимо адрес errno.

```
(gdb) p errno
Cannot access memory at address 0x38
```

То есть когда brk возвращает __curbrk < addr происходит SIGSEGV в `__set_errno (ENOMEM)` так как адрес errno недоступен.
Comment 1 Dmitry V. Levin 2023-11-28 20:19:22 MSK
(In reply to Vitaly Chikunov from comment #0)
> На x86_64 в hasher с p10 aarch64 под qemu-user-aarch64 (из Сизифа) ldconfig
> из p10 падает с Segmentation fault, при этом другие бинарники не падают.
[...]
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007fe814288fe8 in __brk (addr=<optimized out>) at
> ../sysdeps/unix/sysv/linux/generic/brk.c:37
> 37            __set_errno (ENOMEM);
> (gdb) bt
> #0  0x00007fe814288fe8 in __brk (addr=<optimized out>) at
> ../sysdeps/unix/sysv/linux/generic/brk.c:37
> #1  0x00007fe81426a0d8 in __sbrk (increment=2872) at sbrk.c:70
> #2  __sbrk (increment=2872) at sbrk.c:32
> #3  0x00007fe8142426c4 in __libc_setup_tls () at ../csu/libc-tls.c:148

https://sourceware.org/cgit/glibc/commit/?id=f787e138aa0