[1/5] Linux: Implement a useful version of _startup_fatal

Message ID 7a6a51b346a81484046ba392a9854a88568a92aa.1651518694.git.fweimer@redhat.com
State Superseded
Headers
Series Linux: Fall back to mmap if early sbrk fails |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent

Commit Message

Florian Weimer May 2, 2022, 7:15 p.m. UTC
  ---
 sysdeps/unix/sysv/linux/i386/startup.h | 17 ++----------
 sysdeps/unix/sysv/linux/startup.h      | 38 ++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 15 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/startup.h
  

Comments

H.J. Lu May 2, 2022, 7:45 p.m. UTC | #1
On Mon, May 2, 2022 at 12:16 PM Florian Weimer via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> ---
>  sysdeps/unix/sysv/linux/i386/startup.h | 17 ++----------
>  sysdeps/unix/sysv/linux/startup.h      | 38 ++++++++++++++++++++++++++
>  2 files changed, 40 insertions(+), 15 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/startup.h
>
> diff --git a/sysdeps/unix/sysv/linux/i386/startup.h b/sysdeps/unix/sysv/linux/i386/startup.h
> index 67c9310f3a..694d6cf4e7 100644
> --- a/sysdeps/unix/sysv/linux/i386/startup.h
> +++ b/sysdeps/unix/sysv/linux/i386/startup.h
> @@ -19,19 +19,6 @@
>  #if BUILD_PIE_DEFAULT
>  /* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE.  */
>  # define I386_USE_SYSENTER 0
> -
> -# include <sysdep.h>
> -# include <abort-instr.h>
> -
> -__attribute__ ((__noreturn__))
> -static inline void
> -_startup_fatal (const char *message __attribute__ ((unused)))
> -{
> -  /* This is only called very early during startup in static PIE.
> -     FIXME: How can it be improved?  */
> -  ABORT_INSTRUCTION;
> -  __builtin_unreachable ();
> -}
> -#else
> -# include_next <startup.h>
>  #endif
> +
> +#include_next <startup.h>
> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
> new file mode 100644
> index 0000000000..a5de941759
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/startup.h
> @@ -0,0 +1,38 @@
> +/* Linux definitions of functions used by static libc main startup.
> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
                             Shouldn't it just be 2022?
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifdef SHARED
> +# include_next <startup.h>
> +#else
> +# include <sysdep.h>
> +
> +/* Avoid a run-time invocation of strlen.  */
> +#define _startup_fatal(message)                                         \

Is this needed only for static PIE?

> +  do                                                                    \
> +    {                                                                   \
> +      size_t message_length = __builtin_strlen (message);               \
> +      if (! __builtin_constant_p (message_length))                      \
> +        {                                                               \
> +          extern void _startup_fatal_not_constant (void);               \
> +          _startup_fatal_not_constant ();                               \
> +        }                                                               \
> +      INTERNAL_SYSCALL_CALL (write, STDERR_FILENO, message, message_length); \
> +      INTERNAL_SYSCALL_CALL (exit_group, 127);                          \
> +    }                                                                   \
> +  while (0)
> +#endif  /* !SHARED */
> --
> 2.35.1
>
>
  
Florian Weimer May 2, 2022, 7:52 p.m. UTC | #2
* H. J. Lu:

>> +#include_next <startup.h>
>> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
>> new file mode 100644
>> index 0000000000..a5de941759
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/startup.h
>> @@ -0,0 +1,38 @@
>> +/* Linux definitions of functions used by static libc main startup.
>> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
>                              Shouldn't it just be 2022?
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#ifdef SHARED
>> +# include_next <startup.h>
>> +#else
>> +# include <sysdep.h>
>> +
>> +/* Avoid a run-time invocation of strlen.  */
>> +#define _startup_fatal(message)                                         \
>
> Is this needed only for static PIE?

I don't know.  It's used from csu/libc-tls.c, some targets may need it
for ET_EXEC static linking, too.  I haven't checked.  The additional
code size is minimal.

Thanks,
Florian
  
H.J. Lu May 2, 2022, 8:06 p.m. UTC | #3
On Mon, May 2, 2022 at 12:53 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> >> +#include_next <startup.h>
> >> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
> >> new file mode 100644
> >> index 0000000000..a5de941759
> >> --- /dev/null
> >> +++ b/sysdeps/unix/sysv/linux/startup.h
> >> @@ -0,0 +1,38 @@
> >> +/* Linux definitions of functions used by static libc main startup.
> >> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
> >                              Shouldn't it just be 2022?
> >> +   This file is part of the GNU C Library.
> >> +
> >> +   The GNU C Library is free software; you can redistribute it and/or
> >> +   modify it under the terms of the GNU Lesser General Public
> >> +   License as published by the Free Software Foundation; either
> >> +   version 2.1 of the License, or (at your option) any later version.
> >> +
> >> +   The GNU C Library is distributed in the hope that it will be useful,
> >> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >> +   Lesser General Public License for more details.
> >> +
> >> +   You should have received a copy of the GNU Lesser General Public
> >> +   License along with the GNU C Library; if not, see
> >> +   <https://www.gnu.org/licenses/>.  */
> >> +
> >> +#ifdef SHARED
> >> +# include_next <startup.h>
> >> +#else
> >> +# include <sysdep.h>
> >> +
> >> +/* Avoid a run-time invocation of strlen.  */
> >> +#define _startup_fatal(message)                                         \
> >
> > Is this needed only for static PIE?
>
> I don't know.  It's used from csu/libc-tls.c, some targets may need it
> for ET_EXEC static linking, too.  I haven't checked.  The additional
> code size is minimal.

_startup_fatal was added for i386 static PIE.  I don't think it is
needed for normal static executables.
  
Florian Weimer May 2, 2022, 8:37 p.m. UTC | #4
* H. J. Lu:

> On Mon, May 2, 2022 at 12:53 PM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> >> +#include_next <startup.h>
>> >> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
>> >> new file mode 100644
>> >> index 0000000000..a5de941759
>> >> --- /dev/null
>> >> +++ b/sysdeps/unix/sysv/linux/startup.h
>> >> @@ -0,0 +1,38 @@
>> >> +/* Linux definitions of functions used by static libc main startup.
>> >> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
>> >                              Shouldn't it just be 2022?
>> >> +   This file is part of the GNU C Library.
>> >> +
>> >> +   The GNU C Library is free software; you can redistribute it and/or
>> >> +   modify it under the terms of the GNU Lesser General Public
>> >> +   License as published by the Free Software Foundation; either
>> >> +   version 2.1 of the License, or (at your option) any later version.
>> >> +
>> >> +   The GNU C Library is distributed in the hope that it will be useful,
>> >> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> >> +   Lesser General Public License for more details.
>> >> +
>> >> +   You should have received a copy of the GNU Lesser General Public
>> >> +   License along with the GNU C Library; if not, see
>> >> +   <https://www.gnu.org/licenses/>.  */
>> >> +
>> >> +#ifdef SHARED
>> >> +# include_next <startup.h>
>> >> +#else
>> >> +# include <sysdep.h>
>> >> +
>> >> +/* Avoid a run-time invocation of strlen.  */
>> >> +#define _startup_fatal(message)                                         \
>> >
>> > Is this needed only for static PIE?
>>
>> I don't know.  It's used from csu/libc-tls.c, some targets may need it
>> for ET_EXEC static linking, too.  I haven't checked.  The additional
>> code size is minimal.
>
> _startup_fatal was added for i386 static PIE.  I don't think it is
> needed for normal static executables.

Based on the current initialization ordering, it seems to me that we
need it for non-PIE static programs, too.  Maybe I should check this
tomorrow.

Thanks,
Florian
  
Florian Weimer May 3, 2022, 5:18 a.m. UTC | #5
* Florian Weimer:

> * H. J. Lu:
>
>> On Mon, May 2, 2022 at 12:53 PM Florian Weimer <fweimer@redhat.com> wrote:
>>>
>>> * H. J. Lu:
>>>
>>> >> +#include_next <startup.h>
>>> >> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
>>> >> new file mode 100644
>>> >> index 0000000000..a5de941759
>>> >> --- /dev/null
>>> >> +++ b/sysdeps/unix/sysv/linux/startup.h
>>> >> @@ -0,0 +1,38 @@
>>> >> +/* Linux definitions of functions used by static libc main startup.
>>> >> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
>>> >                              Shouldn't it just be 2022?
>>> >> +   This file is part of the GNU C Library.
>>> >> +
>>> >> +   The GNU C Library is free software; you can redistribute it and/or
>>> >> +   modify it under the terms of the GNU Lesser General Public
>>> >> +   License as published by the Free Software Foundation; either
>>> >> +   version 2.1 of the License, or (at your option) any later version.
>>> >> +
>>> >> +   The GNU C Library is distributed in the hope that it will be useful,
>>> >> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> >> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> >> +   Lesser General Public License for more details.
>>> >> +
>>> >> +   You should have received a copy of the GNU Lesser General Public
>>> >> +   License along with the GNU C Library; if not, see
>>> >> +   <https://www.gnu.org/licenses/>.  */
>>> >> +
>>> >> +#ifdef SHARED
>>> >> +# include_next <startup.h>
>>> >> +#else
>>> >> +# include <sysdep.h>
>>> >> +
>>> >> +/* Avoid a run-time invocation of strlen.  */
>>> >> +#define _startup_fatal(message)                                         \
>>> >
>>> > Is this needed only for static PIE?
>>>
>>> I don't know.  It's used from csu/libc-tls.c, some targets may need it
>>> for ET_EXEC static linking, too.  I haven't checked.  The additional
>>> code size is minimal.
>>
>> _startup_fatal was added for i386 static PIE.  I don't think it is
>> needed for normal static executables.
>
> Based on the current initialization ordering, it seems to me that we
> need it for non-PIE static programs, too.  Maybe I should check this
> tomorrow.

It does not work on x86-64 because cancellation handling needs the TCB:

Breakpoint 1, _dl_early_allocate (size=size@entry=3520) at ../sysdeps/unix/sysv/linux/dl-early_allocate.c:41
41	  if (__curbrk != NULL)
(gdb) finish
Run till exit from #0  _dl_early_allocate (size=size@entry=3520)
    at ../sysdeps/unix/sysv/linux/dl-early_allocate.c:41
__libc_setup_tls () at libc-tls.c:149
149	  if (tlsblock == NULL)
Value returned is $1 = (void *) 0x4eb000
(gdb) set $rax = 0
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
__writev (fd=fd@entry=2, iov=iov@entry=0x7fffffffddb0, iovcnt=iovcnt@entry=1) at ../sysdeps/unix/sysv/linux/writev.c:26
26	  return SYSCALL_CANCEL (writev, fd, iov, iovcnt);
(gdb) disas
Dump of assembler code for function __writev:
=> 0x000000000044e3c0 <+0>:	mov    %fs:0x18,%eax
   0x000000000044e3c8 <+8>:	test   %eax,%eax
   0x000000000044e3ca <+10>:	jne    0x44e3e0 <__writev+32>
   0x000000000044e3cc <+12>:	mov    $0x14,%eax
   0x000000000044e3d1 <+17>:	syscall 
   0x000000000044e3d3 <+19>:	cmp    $0xfffffffffffff000,%rax
   0x000000000044e3d9 <+25>:	ja     0x44e430 <__writev+112>
   0x000000000044e3db <+27>:	ret    
   0x000000000044e3dc <+28>:	nopl   0x0(%rax)
   0x000000000044e3e0 <+32>:	sub    $0x28,%rsp
   0x000000000044e3e4 <+36>:	mov    %edx,0x1c(%rsp)
   0x000000000044e3e8 <+40>:	mov    %rsi,0x10(%rsp)
   0x000000000044e3ed <+45>:	mov    %edi,0x8(%rsp)
   0x000000000044e3f1 <+49>:	call   0x46d2b0 <__pthread_enable_asynccancel>
   0x000000000044e3f6 <+54>:	mov    0x1c(%rsp),%edx
   0x000000000044e3fa <+58>:	mov    0x10(%rsp),%rsi
   0x000000000044e3ff <+63>:	mov    %eax,%r8d
   0x000000000044e402 <+66>:	mov    0x8(%rsp),%edi
   0x000000000044e406 <+70>:	mov    $0x14,%eax
   0x000000000044e40b <+75>:	syscall 
   0x000000000044e40d <+77>:	cmp    $0xfffffffffffff000,%rax
   0x000000000044e413 <+83>:	ja     0x44e448 <__writev+136>
   0x000000000044e415 <+85>:	mov    %r8d,%edi
   0x000000000044e418 <+88>:	mov    %rax,0x8(%rsp)
   0x000000000044e41d <+93>:	call   0x46d330 <__pthread_disable_asynccancel>
   0x000000000044e422 <+98>:	mov    0x8(%rsp),%rax
   0x000000000044e427 <+103>:	add    $0x28,%rsp
   0x000000000044e42b <+107>:	ret    
   0x000000000044e42c <+108>:	nopl   0x0(%rax)
   0x000000000044e430 <+112>:	mov    $0xffffffffffffffa8,%rdx
   0x000000000044e437 <+119>:	neg    %eax
   0x000000000044e439 <+121>:	mov    %eax,%fs:(%rdx)
   0x000000000044e43c <+124>:	mov    $0xffffffffffffffff,%rax
   0x000000000044e443 <+131>:	ret    
   0x000000000044e444 <+132>:	nopl   0x0(%rax)
   0x000000000044e448 <+136>:	mov    $0xffffffffffffffa8,%rdx
   0x000000000044e44f <+143>:	neg    %eax
   0x000000000044e451 <+145>:	mov    %eax,%fs:(%rdx)
   0x000000000044e454 <+148>:	mov    $0xffffffffffffffff,%rax
   0x000000000044e45b <+155>:	jmp    0x44e415 <__writev+85>
End of assembler dump.
(gdb) bt
#0  __writev (fd=fd@entry=2, iov=iov@entry=0x7fffffffddb0, 
    iovcnt=iovcnt@entry=1) at ../sysdeps/unix/sysv/linux/writev.c:26
#1  0x00000000004077aa in writev_for_fatal (fd=<optimized out>, 
    total=<optimized out>, niov=<optimized out>, iov=<optimized out>)
    at ../sysdeps/posix/libc_fatal.c:44
#2  __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x4c70ad "%s")
    at ../sysdeps/posix/libc_fatal.c:124
#3  0x000000000040789c in __libc_fatal (
    message=message@entry=0x4adb60 "Fatal glibc error: Cannot allocate TLS block\n") at ../sysdeps/posix/libc_fatal.c:164
#4  0x000000000040a3c0 in __libc_setup_tls () at libc-tls.c:150
#5  0x0000000000409709 in __libc_start_main_impl (main=0x401740 <main>, 
    argc=1, argv=0x7fffffffe008, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=0x0, stack_end=0x7fffffffdff8) at ../csu/libc-start.c:301
#6  0x0000000000401da1 in _start () at ../sysdeps/x86_64/start.S:115
(gdb) 

That might be a different bug.

Thanks,
Florian
  
H.J. Lu May 3, 2022, 3:54 p.m. UTC | #6
On Mon, May 2, 2022 at 10:18 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * Florian Weimer:
>
> > * H. J. Lu:
> >
> >> On Mon, May 2, 2022 at 12:53 PM Florian Weimer <fweimer@redhat.com> wrote:
> >>>
> >>> * H. J. Lu:
> >>>
> >>> >> +#include_next <startup.h>
> >>> >> diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
> >>> >> new file mode 100644
> >>> >> index 0000000000..a5de941759
> >>> >> --- /dev/null
> >>> >> +++ b/sysdeps/unix/sysv/linux/startup.h
> >>> >> @@ -0,0 +1,38 @@
> >>> >> +/* Linux definitions of functions used by static libc main startup.
> >>> >> +   Copyright (C) 2017-2022 Free Software Foundation, Inc.
> >>> >                              Shouldn't it just be 2022?
> >>> >> +   This file is part of the GNU C Library.
> >>> >> +
> >>> >> +   The GNU C Library is free software; you can redistribute it and/or
> >>> >> +   modify it under the terms of the GNU Lesser General Public
> >>> >> +   License as published by the Free Software Foundation; either
> >>> >> +   version 2.1 of the License, or (at your option) any later version.
> >>> >> +
> >>> >> +   The GNU C Library is distributed in the hope that it will be useful,
> >>> >> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> >> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> >>> >> +   Lesser General Public License for more details.
> >>> >> +
> >>> >> +   You should have received a copy of the GNU Lesser General Public
> >>> >> +   License along with the GNU C Library; if not, see
> >>> >> +   <https://www.gnu.org/licenses/>.  */
> >>> >> +
> >>> >> +#ifdef SHARED
> >>> >> +# include_next <startup.h>
> >>> >> +#else
> >>> >> +# include <sysdep.h>
> >>> >> +
> >>> >> +/* Avoid a run-time invocation of strlen.  */
> >>> >> +#define _startup_fatal(message)                                         \
> >>> >
> >>> > Is this needed only for static PIE?
> >>>
> >>> I don't know.  It's used from csu/libc-tls.c, some targets may need it
> >>> for ET_EXEC static linking, too.  I haven't checked.  The additional
> >>> code size is minimal.
> >>
> >> _startup_fatal was added for i386 static PIE.  I don't think it is
> >> needed for normal static executables.
> >
> > Based on the current initialization ordering, it seems to me that we
> > need it for non-PIE static programs, too.  Maybe I should check this
> > tomorrow.
>
> It does not work on x86-64 because cancellation handling needs the TCB:
>
> Breakpoint 1, _dl_early_allocate (size=size@entry=3520) at ../sysdeps/unix/sysv/linux/dl-early_allocate.c:41
> 41        if (__curbrk != NULL)
> (gdb) finish
> Run till exit from #0  _dl_early_allocate (size=size@entry=3520)
>     at ../sysdeps/unix/sysv/linux/dl-early_allocate.c:41
> __libc_setup_tls () at libc-tls.c:149
> 149       if (tlsblock == NULL)
> Value returned is $1 = (void *) 0x4eb000
> (gdb) set $rax = 0
> (gdb) c
> Continuing.
>
> Program received signal SIGSEGV, Segmentation fault.
> __writev (fd=fd@entry=2, iov=iov@entry=0x7fffffffddb0, iovcnt=iovcnt@entry=1) at ../sysdeps/unix/sysv/linux/writev.c:26
> 26        return SYSCALL_CANCEL (writev, fd, iov, iovcnt);
> (gdb) disas
> Dump of assembler code for function __writev:
> => 0x000000000044e3c0 <+0>:     mov    %fs:0x18,%eax
>    0x000000000044e3c8 <+8>:     test   %eax,%eax
>    0x000000000044e3ca <+10>:    jne    0x44e3e0 <__writev+32>
>    0x000000000044e3cc <+12>:    mov    $0x14,%eax
>    0x000000000044e3d1 <+17>:    syscall
>    0x000000000044e3d3 <+19>:    cmp    $0xfffffffffffff000,%rax
>    0x000000000044e3d9 <+25>:    ja     0x44e430 <__writev+112>
>    0x000000000044e3db <+27>:    ret
>    0x000000000044e3dc <+28>:    nopl   0x0(%rax)
>    0x000000000044e3e0 <+32>:    sub    $0x28,%rsp
>    0x000000000044e3e4 <+36>:    mov    %edx,0x1c(%rsp)
>    0x000000000044e3e8 <+40>:    mov    %rsi,0x10(%rsp)
>    0x000000000044e3ed <+45>:    mov    %edi,0x8(%rsp)
>    0x000000000044e3f1 <+49>:    call   0x46d2b0 <__pthread_enable_asynccancel>
>    0x000000000044e3f6 <+54>:    mov    0x1c(%rsp),%edx
>    0x000000000044e3fa <+58>:    mov    0x10(%rsp),%rsi
>    0x000000000044e3ff <+63>:    mov    %eax,%r8d
>    0x000000000044e402 <+66>:    mov    0x8(%rsp),%edi
>    0x000000000044e406 <+70>:    mov    $0x14,%eax
>    0x000000000044e40b <+75>:    syscall
>    0x000000000044e40d <+77>:    cmp    $0xfffffffffffff000,%rax
>    0x000000000044e413 <+83>:    ja     0x44e448 <__writev+136>
>    0x000000000044e415 <+85>:    mov    %r8d,%edi
>    0x000000000044e418 <+88>:    mov    %rax,0x8(%rsp)
>    0x000000000044e41d <+93>:    call   0x46d330 <__pthread_disable_asynccancel>
>    0x000000000044e422 <+98>:    mov    0x8(%rsp),%rax
>    0x000000000044e427 <+103>:   add    $0x28,%rsp
>    0x000000000044e42b <+107>:   ret
>    0x000000000044e42c <+108>:   nopl   0x0(%rax)
>    0x000000000044e430 <+112>:   mov    $0xffffffffffffffa8,%rdx
>    0x000000000044e437 <+119>:   neg    %eax
>    0x000000000044e439 <+121>:   mov    %eax,%fs:(%rdx)
>    0x000000000044e43c <+124>:   mov    $0xffffffffffffffff,%rax
>    0x000000000044e443 <+131>:   ret
>    0x000000000044e444 <+132>:   nopl   0x0(%rax)
>    0x000000000044e448 <+136>:   mov    $0xffffffffffffffa8,%rdx
>    0x000000000044e44f <+143>:   neg    %eax
>    0x000000000044e451 <+145>:   mov    %eax,%fs:(%rdx)
>    0x000000000044e454 <+148>:   mov    $0xffffffffffffffff,%rax
>    0x000000000044e45b <+155>:   jmp    0x44e415 <__writev+85>
> End of assembler dump.
> (gdb) bt
> #0  __writev (fd=fd@entry=2, iov=iov@entry=0x7fffffffddb0,
>     iovcnt=iovcnt@entry=1) at ../sysdeps/unix/sysv/linux/writev.c:26
> #1  0x00000000004077aa in writev_for_fatal (fd=<optimized out>,
>     total=<optimized out>, niov=<optimized out>, iov=<optimized out>)
>     at ../sysdeps/posix/libc_fatal.c:44
> #2  __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x4c70ad "%s")
>     at ../sysdeps/posix/libc_fatal.c:124
> #3  0x000000000040789c in __libc_fatal (
>     message=message@entry=0x4adb60 "Fatal glibc error: Cannot allocate TLS block\n") at ../sysdeps/posix/libc_fatal.c:164
> #4  0x000000000040a3c0 in __libc_setup_tls () at libc-tls.c:150
> #5  0x0000000000409709 in __libc_start_main_impl (main=0x401740 <main>,
>     argc=1, argv=0x7fffffffe008, init=<optimized out>, fini=<optimized out>,
>     rtld_fini=0x0, stack_end=0x7fffffffdff8) at ../csu/libc-start.c:301
> #6  0x0000000000401da1 in _start () at ../sysdeps/x86_64/start.S:115
> (gdb)
>
> That might be a different bug.

The startup codes can't use cancellation before it is ready.  Do we need to
check SHARED in this case?
  
Florian Weimer May 3, 2022, 4 p.m. UTC | #7
* H. J. Lu:

> The startup codes can't use cancellation before it is ready.  Do we need to
> check SHARED in this case?

I think __libc_fatal shouldn't be a cancellation point.  That's not
really related to SHARED.

We can reimplement __libc_fatal in terms of direct system calls (with
some caveats), so that it is guaranteed to be usable at this point.  But
I think that would be a different patch series.

Thanks,
Florian
  
H.J. Lu May 3, 2022, 4:36 p.m. UTC | #8
On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > The startup codes can't use cancellation before it is ready.  Do we need to
> > check SHARED in this case?
>
> I think __libc_fatal shouldn't be a cancellation point.  That's not
> really related to SHARED.

Should we define _startup_fatal unconditionally and always define
I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
used safely during startup?

> We can reimplement __libc_fatal in terms of direct system calls (with
> some caveats), so that it is guaranteed to be usable at this point.  But
> I think that would be a different patch series.

__libc_fatal shouldn't be used in csu/libc-tls.c.
  
Florian Weimer May 3, 2022, 4:43 p.m. UTC | #9
* H. J. Lu:

> On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > The startup codes can't use cancellation before it is ready.  Do we need to
>> > check SHARED in this case?
>>
>> I think __libc_fatal shouldn't be a cancellation point.  That's not
>> really related to SHARED.
>
> Should we define _startup_fatal unconditionally and always define
> I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
> used safely during startup?

Hmm.  Isn't that what my patch does?

Thanks,
Florian
  
H.J. Lu May 3, 2022, 4:46 p.m. UTC | #10
On Tue, May 3, 2022 at 9:44 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> > The startup codes can't use cancellation before it is ready.  Do we need to
> >> > check SHARED in this case?
> >>
> >> I think __libc_fatal shouldn't be a cancellation point.  That's not
> >> really related to SHARED.
> >
> > Should we define _startup_fatal unconditionally and always define
> > I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
> > used safely during startup?
>
> Hmm.  Isn't that what my patch does?
>

Your patch still checks BUILD_PIE_DEFAULT and SHARED.
  
Florian Weimer May 3, 2022, 4:57 p.m. UTC | #11
* H. J. Lu:

> On Tue, May 3, 2022 at 9:44 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
>> >>
>> >> * H. J. Lu:
>> >>
>> >> > The startup codes can't use cancellation before it is ready.  Do we need to
>> >> > check SHARED in this case?
>> >>
>> >> I think __libc_fatal shouldn't be a cancellation point.  That's not
>> >> really related to SHARED.
>> >
>> > Should we define _startup_fatal unconditionally and always define
>> > I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
>> > used safely during startup?
>>
>> Hmm.  Isn't that what my patch does?
>>
>
> Your patch still checks BUILD_PIE_DEFAULT and SHARED.

Ah, I see, thanks.  You are right, the i386 version should define
I386_USE_SYSENTER unconditionally.  Will fix.

Florian
  
Adhemerval Zanella Netto May 3, 2022, 5:01 p.m. UTC | #12
On 03/05/2022 13:57, Florian Weimer via Libc-alpha wrote:
> * H. J. Lu:
> 
>> On Tue, May 3, 2022 at 9:44 AM Florian Weimer <fweimer@redhat.com> wrote:
>>>
>>> * H. J. Lu:
>>>
>>>> On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
>>>>>
>>>>> * H. J. Lu:
>>>>>
>>>>>> The startup codes can't use cancellation before it is ready.  Do we need to
>>>>>> check SHARED in this case?
>>>>>
>>>>> I think __libc_fatal shouldn't be a cancellation point.  That's not
>>>>> really related to SHARED.
>>>>
>>>> Should we define _startup_fatal unconditionally and always define
>>>> I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
>>>> used safely during startup?
>>>
>>> Hmm.  Isn't that what my patch does?
>>>
>>
>> Your patch still checks BUILD_PIE_DEFAULT and SHARED.
> 
> Ah, I see, thanks.  You are right, the i386 version should define
> I386_USE_SYSENTER unconditionally.  Will fix.

I think you might want to check ia64 as well, since it uses a TCB variable
to call the syscall in some cases.
  
Florian Weimer May 3, 2022, 8:16 p.m. UTC | #13
* Adhemerval Zanella via Libc-alpha:

> On 03/05/2022 13:57, Florian Weimer via Libc-alpha wrote:
>> * H. J. Lu:
>> 
>>> On Tue, May 3, 2022 at 9:44 AM Florian Weimer <fweimer@redhat.com> wrote:
>>>>
>>>> * H. J. Lu:
>>>>
>>>>> On Tue, May 3, 2022 at 9:01 AM Florian Weimer <fweimer@redhat.com> wrote:
>>>>>>
>>>>>> * H. J. Lu:
>>>>>>
>>>>>>> The startup codes can't use cancellation before it is ready.  Do we need to
>>>>>>> check SHARED in this case?
>>>>>>
>>>>>> I think __libc_fatal shouldn't be a cancellation point.  That's not
>>>>>> really related to SHARED.
>>>>>
>>>>> Should we define _startup_fatal unconditionally and always define
>>>>> I386_USE_SYSENTER as 0 for i386 so that _startup_fatal can be
>>>>> used safely during startup?
>>>>
>>>> Hmm.  Isn't that what my patch does?
>>>>
>>>
>>> Your patch still checks BUILD_PIE_DEFAULT and SHARED.
>> 
>> Ah, I see, thanks.  You are right, the i386 version should define
>> I386_USE_SYSENTER unconditionally.  Will fix.
>
> I think you might want to check ia64 as well, since it uses a TCB variable
> to call the syscall in some cases.

“might want to check“ isn't a phrase I would use in the context with
ia64, but yes, I can add a startup.h file for it, too.  Thanks for the
suggestion.

Florian
  

Patch

diff --git a/sysdeps/unix/sysv/linux/i386/startup.h b/sysdeps/unix/sysv/linux/i386/startup.h
index 67c9310f3a..694d6cf4e7 100644
--- a/sysdeps/unix/sysv/linux/i386/startup.h
+++ b/sysdeps/unix/sysv/linux/i386/startup.h
@@ -19,19 +19,6 @@ 
 #if BUILD_PIE_DEFAULT
 /* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE.  */
 # define I386_USE_SYSENTER 0
-
-# include <sysdep.h>
-# include <abort-instr.h>
-
-__attribute__ ((__noreturn__))
-static inline void
-_startup_fatal (const char *message __attribute__ ((unused)))
-{
-  /* This is only called very early during startup in static PIE.
-     FIXME: How can it be improved?  */
-  ABORT_INSTRUCTION;
-  __builtin_unreachable ();
-}
-#else
-# include_next <startup.h>
 #endif
+
+#include_next <startup.h>
diff --git a/sysdeps/unix/sysv/linux/startup.h b/sysdeps/unix/sysv/linux/startup.h
new file mode 100644
index 0000000000..a5de941759
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/startup.h
@@ -0,0 +1,38 @@ 
+/* Linux definitions of functions used by static libc main startup.
+   Copyright (C) 2017-2022 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifdef SHARED
+# include_next <startup.h>
+#else
+# include <sysdep.h>
+
+/* Avoid a run-time invocation of strlen.  */
+#define _startup_fatal(message)                                         \
+  do                                                                    \
+    {                                                                   \
+      size_t message_length = __builtin_strlen (message);               \
+      if (! __builtin_constant_p (message_length))                      \
+        {                                                               \
+          extern void _startup_fatal_not_constant (void);               \
+          _startup_fatal_not_constant ();                               \
+        }                                                               \
+      INTERNAL_SYSCALL_CALL (write, STDERR_FILENO, message, message_length); \
+      INTERNAL_SYSCALL_CALL (exit_group, 127);                          \
+    }                                                                   \
+  while (0)
+#endif  /* !SHARED */