Bug 27033

Summary: glibc-2.32 on gcc-11 generates %fs:0x10 access before TLS is registered.
Product: glibc Reporter: Sergei Trofimovich <slyich>
Component: dynamic-linkAssignee: Not yet assigned to anyone <unassigned>
Severity: normal CC: hjl.tools
Priority: P2    
Version: 2.32   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: gcc-11-glibc-tls.tar.gz

Description Sergei Trofimovich 2020-12-08 00:36:19 UTC
Created attachment 13025 [details]

Noticed the failure as a crash of binaries ran against glibc-2.32. glibc-2.32 is built by gcc-11.

The backtrace:

$ gdb --args ./ld-*.so --library-path . /usr/bin/cal
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
(gdb) bt
#0  0x00007ffff7fdcbe7 in add_dependency (flags=<optimized out>, map=<optimized out>,
    undef_map=<optimized out>) at dl-lookup.c:640
#1  _dl_lookup_symbol_x (undef_name=0x7ffff7ff4141 "__vdso_clock_gettime", undef_map=0x7ffff7ffe770,
    ref=0x7fffffffe198, symbol_scope=0x7ffff7ffeb08, version=0x7fffffffe1c0, type_class=0, flags=0,
    skip_map=0x0) at dl-lookup.c:929
#2  0x00007ffff7fd5648 in dl_vdso_vsym (name=0x7ffff7ff4141 "__vdso_clock_gettime")
    at ../sysdeps/unix/sysv/linux/dl-vdso.h:52
#3  setup_vdso_pointers () at ../sysdeps/unix/sysv/linux/dl-vdso-setup.h:30
#4  dl_main (phdr=<optimized out>, phdr@entry=0x7ffff7fd2040, phnum=11, phnum@entry=8,
    user_entry=user_entry@entry=0x7fffffffe420, auxv=0x7fffffffe5d8) at rtld.c:1614
#5  0x00007ffff7feba79 in _dl_sysdep_start (start_argptr=start_argptr@entry=0x7fffffffe4e0,
    dl_main=dl_main@entry=0x7ffff7fd44a0 <dl_main>) at ../elf/dl-sysdep.c:252
#6  0x00007ffff7fd3fc5 in _dl_start_final (arg=0x7fffffffe4e0) at rtld.c:506
#7  _dl_start (arg=0x7fffffffe4e0) at rtld.c:599
(gdb) disassemble
Dump of assembler code for function _dl_lookup_symbol_x:
   0x00007ffff7fdcbd0 <+0>:     push   %r15
   0x00007ffff7fdcbd2 <+2>:     push   %r14
   0x00007ffff7fdcbd4 <+4>:     push   %r13
   0x00007ffff7fdcbd6 <+6>:     mov    %rdx,%r13
   0x00007ffff7fdcbd9 <+9>:     push   %r12
   0x00007ffff7fdcbdb <+11>:    mov    %rdi,%r12
   0x00007ffff7fdcbde <+14>:    push   %rbp
   0x00007ffff7fdcbdf <+15>:    push   %rbx
   0x00007ffff7fdcbe0 <+16>:    sub    $0xa8,%rsp
=> 0x00007ffff7fdcbe7 <+23>:    mov    %fs:0x10,%rax
   0x00007ffff7fdcbf0 <+32>:    mov    %rsi,0x10(%rsp)

Note: 'mov %fs:0x10,%rax' is a 'THREAD_GSCOPE_RESET_FLAG ();' call.

I'm not sure if it's a glibc bug of using the macro in rtld before TLS is set up  (or a missing compiler barrier) or a gcc bug of hoisting the %fs: access outside an 'if (__builtin_expect ((flags & DL_LOOKUP_GSCOPE_LOCK), 0))' condition.

I'm assuming it's a glibc bug.

Attached gcc-11-glibc-tls.tar.gz contains:
1. preprocessed dl-lookup.c file
2. script to compile dl-loookup.c into .o and .S files with gcc-10 and gcc-11.
3. .o and .S files as well for both gcc-10 (good) and gcc11 (bad) files.

10.s (good) entry _dl_lookup_symbol_x:

   0x0000000000000d40 <+0>:     push   %r15
   0x0000000000000d42 <+2>:     push   %r14
   0x0000000000000d44 <+4>:     push   %r13
   0x0000000000000d46 <+6>:     mov    %rdx,%r13
   0x0000000000000d49 <+9>:     push   %r12
   0x0000000000000d4b <+11>:    mov    %rdi,%r12
   0x0000000000000d4e <+14>:    push   %rbp
   0x0000000000000d4f <+15>:    push   %rbx
   0x0000000000000d50 <+16>:    sub    $0x98,%rsp
   0x0000000000000d57 <+23>:    movzbl (%rdi),%edx
   0x0000000000000d5a <+26>:    mov    %rsi,0x10(%rsp)
   0x0000000000000d5f <+31>:    mov    %rcx,0x20(%rsp)
   0x0000000000000d64 <+36>:    mov    %r8,0x8(%rsp)
   0x0000000000000d69 <+41>:    mov    %r9d,0x1c(%rsp)
   0x0000000000000d6e <+46>:    test   %dl,%dl

11.s (bad) entry _dl_lookup_symbol_x:

   0x0000000000000d70 <+0>:     push   %r15
   0x0000000000000d72 <+2>:     push   %r14
   0x0000000000000d74 <+4>:     push   %r13
   0x0000000000000d76 <+6>:     push   %r12
   0x0000000000000d78 <+8>:     mov    %rdi,%r12
   0x0000000000000d7b <+11>:    push   %rbp
   0x0000000000000d7c <+12>:    mov    %rdx,%rbp
   0x0000000000000d7f <+15>:    push   %rbx
   0x0000000000000d80 <+16>:    mov    %fs:0x10,%rax ; <<<- bad, crashes libc
   0x0000000000000d89 <+25>:    sub    $0xa8,%rsp
   0x0000000000000d90 <+32>:    mov    %rsi,0x10(%rsp)
   0x0000000000000d95 <+37>:    mov    %rcx,0x20(%rsp)
   0x0000000000000d9a <+42>:    mov    %r8,0x8(%rsp)
   0x0000000000000d9f <+47>:    mov    %r9d,0x1c(%rsp)
   0x0000000000000da4 <+52>:    mov    %rax,0x30(%rsp)
   0x0000000000000da9 <+57>:    movzbl (%r12),%edx
   0x0000000000000dae <+62>:    test   %dl,%dl
Comment 1 H.J. Lu 2020-12-08 00:46:03 UTC

*** This bug has been marked as a duplicate of bug 27004 ***