public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro
@ 2022-05-05 15:06 Florian Weimer
  2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Florian Weimer @ 2022-05-05 15:06 UTC (permalink / raw)
  To: libc-alpha

And keep the previous definition if it exists.  This allows
disabling IA64_USE_NEW_STUB while keeping USE_DL_SYSINFO defined.
---
v4: Unchanged.
v3: Fix “statup” typo.  Do not use libpthread and librt in conditional.

 sysdeps/unix/sysv/linux/ia64/brk.c    |  5 ++---
 sysdeps/unix/sysv/linux/ia64/sysdep.h | 23 +++++++++++++----------
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/ia64/brk.c b/sysdeps/unix/sysv/linux/ia64/brk.c
index 65142aeae9..d2135b74fc 100644
--- a/sysdeps/unix/sysv/linux/ia64/brk.c
+++ b/sysdeps/unix/sysv/linux/ia64/brk.c
@@ -16,7 +16,6 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <dl-sysdep.h>
-/* brk is used by statup before TCB is properly set.  */
-#undef USE_DL_SYSINFO
+/* brk is used by startup before TCB is properly set up.  */
+#define IA64_USE_NEW_STUB 0
 #include <sysdeps/unix/sysv/linux/brk.c>
diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h
index 193ecee023..14adbdf4ff 100644
--- a/sysdeps/unix/sysv/linux/ia64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h
@@ -44,12 +44,15 @@
 #undef SYS_ify
 #define SYS_ify(syscall_name)	__NR_##syscall_name
 
-#if defined USE_DL_SYSINFO \
-	&& (IS_IN (libc) \
-	    || IS_IN (libpthread) || IS_IN (librt))
-# define IA64_USE_NEW_STUB
-#else
-# undef IA64_USE_NEW_STUB
+#ifndef IA64_USE_NEW_STUB
+# if defined USE_DL_SYSINFO && IS_IN (libc)
+#  define IA64_USE_NEW_STUB 1
+# else
+#  define IA64_USE_NEW_STUB 0
+# endif
+#endif
+#if IA64_USE_NEW_STUB && !USE_DL_SYSINFO
+# error IA64_USE_NEW_STUB needs USE_DL_SYSINFO
 #endif
 
 #ifdef __ASSEMBLER__
@@ -101,7 +104,7 @@
 	mov r15=num;				\
 	break __IA64_BREAK_SYSCALL
 
-#ifdef IA64_USE_NEW_STUB
+#if IA64_USE_NEW_STUB
 # ifdef SHARED
 #  define DO_CALL(num)				\
 	.prologue;				\
@@ -185,7 +188,7 @@
    (non-negative) errno on error or the return value on success.
  */
 
-#ifdef IA64_USE_NEW_STUB
+#if IA64_USE_NEW_STUB
 
 # define INTERNAL_SYSCALL_NCS(name, nr, args...)			      \
 ({									      \
@@ -277,7 +280,7 @@
 #define ASM_OUTARGS_5	ASM_OUTARGS_4, "=r" (_out4)
 #define ASM_OUTARGS_6	ASM_OUTARGS_5, "=r" (_out5)
 
-#ifdef IA64_USE_NEW_STUB
+#if IA64_USE_NEW_STUB
 #define ASM_ARGS_0
 #define ASM_ARGS_1	ASM_ARGS_0, "4" (_out0)
 #define ASM_ARGS_2	ASM_ARGS_1, "5" (_out1)
@@ -313,7 +316,7 @@
   /* Branch registers.  */						\
   "b6"
 
-#ifdef IA64_USE_NEW_STUB
+#if IA64_USE_NEW_STUB
 # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON
 #else
 # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON , "b7"

base-commit: c1b68685d438373efe64e5f076f4215723004dfb
-- 
2.35.1



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal
  2022-05-05 15:06 [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Florian Weimer
@ 2022-05-05 15:07 ` Florian Weimer
  2022-05-05 15:28   ` Andreas Schwab
  2022-05-05 17:29   ` Adhemerval Zanella
  2022-05-05 15:08 ` [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup Florian Weimer
  2022-05-05 17:28 ` [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Adhemerval Zanella
  2 siblings, 2 replies; 17+ messages in thread
From: Florian Weimer @ 2022-05-05 15:07 UTC (permalink / raw)
  To: libc-alpha

On i386 and ia64, the TCB is not available at this point.
---
v4: Unchanged.
v3: Use 2022 copyright year.  Fix “statup” typo.  Use __message_length
    local variable in _startup_fatal.
 sysdeps/unix/sysv/linux/i386/startup.h | 23 +++------------
 sysdeps/unix/sysv/linux/ia64/startup.h | 22 +++++++++++++++
 sysdeps/unix/sysv/linux/startup.h      | 39 ++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 19 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/ia64/startup.h
 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..213805d7d2 100644
--- a/sysdeps/unix/sysv/linux/i386/startup.h
+++ b/sysdeps/unix/sysv/linux/i386/startup.h
@@ -1,5 +1,5 @@
 /* Linux/i386 definitions of functions used by static libc main startup.
-   Copyright (C) 2017-2022 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -16,22 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#if BUILD_PIE_DEFAULT
-/* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE.  */
-# define I386_USE_SYSENTER 0
+/* Can't use "call *%gs:SYSINFO_OFFSET" during startup.  */
+#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/ia64/startup.h b/sysdeps/unix/sysv/linux/ia64/startup.h
new file mode 100644
index 0000000000..77f29f15a2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/startup.h
@@ -0,0 +1,22 @@
+/* Linux/ia64 definitions of functions used by static libc main startup.
+   Copyright (C) 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/>.  */
+
+/* This code is used before the TCB is set up.  */
+#define IA64_USE_NEW_STUB 0
+
+#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..39859b404a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/startup.h
@@ -0,0 +1,39 @@
+/* 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 */
-- 
2.35.1



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 15:06 [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Florian Weimer
  2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
@ 2022-05-05 15:08 ` Florian Weimer
  2022-05-05 17:48   ` Adhemerval Zanella
  2022-05-06 13:19   ` Adhemerval Zanella
  2022-05-05 17:28 ` [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Adhemerval Zanella
  2 siblings, 2 replies; 17+ messages in thread
From: Florian Weimer @ 2022-05-05 15:08 UTC (permalink / raw)
  To: libc-alpha

This implements mmap fallback for a brk failure during TLS
allocation.

scripts/tls-elf-edit.py is updated to support the new patching method.
The script no longer requires that in the input object is of ET_DYN
type.
---
v4: Do not call __libc_fatal from generic _dl_early_allocate.
v3: Remove spurious empty line change.
 csu/libc-tls.c                              | 11 ++-
 elf/Makefile                                | 19 +++++
 elf/dl-early_allocate.c                     | 30 ++++++++
 elf/tst-tls-allocation-failure-static.c     | 31 ++++++++
 scripts/tst-elf-edit.py                     | 34 +++++++--
 sysdeps/generic/ldsodefs.h                  |  5 ++
 sysdeps/unix/sysv/linux/dl-early_allocate.c | 81 +++++++++++++++++++++
 7 files changed, 201 insertions(+), 10 deletions(-)
 create mode 100644 elf/dl-early_allocate.c
 create mode 100644 elf/tst-tls-allocation-failure-static.c
 create mode 100644 sysdeps/unix/sysv/linux/dl-early_allocate.c

diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index bef92a7568..0a216c5502 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -145,11 +145,16 @@ __libc_setup_tls (void)
      _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
      and dl_tls_static_align.  */
   tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align);
-  tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
+  tlsblock = _dl_early_allocate (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
+  if (tlsblock == NULL)
+    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
 #elif TLS_DTV_AT_TP
   tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
-  tlsblock = __sbrk (tcb_offset + memsz + max_align
-		     + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus));
+  tlsblock = _dl_early_allocate (tcb_offset + memsz + max_align
+				 + TLS_PRE_TCB_SIZE
+				 + GLRO(dl_tls_static_surplus));
+  if (tlsblock == NULL)
+    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
   tlsblock += TLS_PRE_TCB_SIZE;
 #else
   /* In case a model with a different layout for the TCB and DTV
diff --git a/elf/Makefile b/elf/Makefile
index fc9860edee..ce3345ed92 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -33,6 +33,7 @@ routines = \
   $(all-dl-routines) \
   dl-addr \
   dl-addr-obj \
+  dl-early_allocate \
   dl-error \
   dl-iteratephdr \
   dl-libc \
@@ -108,6 +109,7 @@ all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
 # But they are absent from the shared libc, because that code is in ld.so.
 elide-routines.os = \
   $(all-dl-routines) \
+  dl-early_allocate \
   dl-exception \
   dl-origin \
   dl-reloc-static-pie \
@@ -276,6 +278,7 @@ tests-static-normal := \
   tst-linkall-static \
   tst-single_threaded-pthread-static \
   tst-single_threaded-static \
+  tst-tls-allocation-failure-static \
   tst-tlsalign-extern-static \
   tst-tlsalign-static \
   # tests-static-normal
@@ -1213,6 +1216,10 @@ $(objpfx)tst-glibcelf.out: tst-glibcelf.py elf.h $(..)/scripts/glibcelf.py \
           --cc="$(CC) $(patsubst -DMODULE_NAME=%,-DMODULE_NAME=testsuite,$(CPPFLAGS))" \
 	  < /dev/null > $@ 2>&1; $(evaluate-test)
 
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-tls-allocation-failure-static-patched.out
+endif
+
 # The test requires shared _and_ PIE because the executable
 # unit test driver must be able to link with the shared object
 # that is going to eventually go into an installed DSO.
@@ -2937,3 +2944,15 @@ $(eval $(call tst-trace-skeleton,4,\
 	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4))
 $(eval $(call tst-trace-skeleton,5,\
 	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4:$(objpfx)libtracemod5))
+
+$(objpfx)tst-tls-allocation-failure-static-patched: \
+  $(objpfx)tst-tls-allocation-failure-static $(..)scripts/tst-elf-edit.py
+	cp $< $@
+	$(PYTHON) $(..)scripts/tst-elf-edit.py --maximize-tls-size $@
+
+$(objpfx)tst-tls-allocation-failure-static-patched.out: \
+  $(objpfx)tst-tls-allocation-failure-static-patched
+	$< > $@ 2>&1; echo "status: $$?" >> $@
+	grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
+	  && grep -q '^status: 127$$' $@; \
+	  $(evaluate-test)
diff --git a/elf/dl-early_allocate.c b/elf/dl-early_allocate.c
new file mode 100644
index 0000000000..61677aaa03
--- /dev/null
+++ b/elf/dl-early_allocate.c
@@ -0,0 +1,30 @@
+/* Early memory allocation for the dynamic loader.  Generic version.
+   Copyright (C) 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/>.  */
+
+#include <ldsodefs.h>
+#include <stddef.h>
+#include <unistd.h>
+
+void *
+_dl_early_allocate (size_t size)
+{
+  void *result = __sbrk (size);
+  if (result == (void *) -1)
+    result = NULL;
+  return result;
+}
diff --git a/elf/tst-tls-allocation-failure-static.c b/elf/tst-tls-allocation-failure-static.c
new file mode 100644
index 0000000000..8de831b246
--- /dev/null
+++ b/elf/tst-tls-allocation-failure-static.c
@@ -0,0 +1,31 @@
+/* Base for test program with impossiblyh large PT_TLS segment.
+   Copyright (C) 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/>.  */
+
+/* The test actual binary is patched using scripts/tst-elf-edit.py
+   --maximize-tls-size, and this introduces the expected test
+   allocation failure due to an excessive PT_LS p_memsz value.
+
+   Patching the binary is required because on some 64-bit targets, TLS
+   relocations can only cover a 32-bit range, and glibc-internal TLS
+   variables such as errno end up outside that range.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py
index a514179bbf..0e19ce1e73 100644
--- a/scripts/tst-elf-edit.py
+++ b/scripts/tst-elf-edit.py
@@ -43,9 +43,11 @@ EI_DATA=5
 ELFDATA2LSB=b'\x01'
 ELFDATA2MSB=b'\x02'
 
+ET_EXEC=2
 ET_DYN=3
 
 PT_LOAD=1
+PT_TLS=7
 
 def elf_types_fmts(e_ident):
     endian = '<' if e_ident[EI_DATA] == ELFDATA2LSB else '>'
@@ -146,8 +148,15 @@ def elf_edit_align(phdr, align):
     else:
         phdr.p_align = int(align)
 
+def elf_edit_maximize_tls_size(phdr, elfclass):
+    if elfclass == ELFCLASS32:
+        # It is possible that the kernel can allocate half of the
+        # address space, so use something larger.
+        phdr.p_memsz = 0xfff00000
+    else:
+        phdr.p_memsz = 1 << 63
 
-def elf_edit(f, align):
+def elf_edit(f, opts):
     ei_nident_fmt = 'c' * EI_NIDENT
     ei_nident_len = struct.calcsize(ei_nident_fmt)
 
@@ -172,24 +181,35 @@ def elf_edit(f, align):
 
     ehdr = Elf_Ehdr(e_ident)
     ehdr.read(f)
-    if ehdr.e_type != ET_DYN:
-       error('{}: not a shared library'.format(f.name))
+    if ehdr.e_type not in (ET_EXEC, ET_DYN):
+       error('{}: not an executable or shared library'.format(f.name))
 
     phdr = Elf_Phdr(e_ident)
+    maximize_tls_size_done = False
     for i in range(0, ehdr.e_phnum):
         f.seek(ehdr.e_phoff + i * phdr.len)
         phdr.read(f)
-        if phdr.p_type == PT_LOAD:
-            elf_edit_align(phdr, align)
+        if phdr.p_type == PT_LOAD and opts.align is not None:
+            elf_edit_align(phdr, opts.align)
+            f.seek(ehdr.e_phoff + i * phdr.len)
+            phdr.write(f)
+            break
+        if phdr.p_type == PT_TLS and opts.maximize_tls_size:
+            elf_edit_maximize_tls_size(phdr, e_ident[EI_CLASS])
             f.seek(ehdr.e_phoff + i * phdr.len)
             phdr.write(f)
+            maximize_tls_size_done = True
             break
 
+    if opts.maximize_tls_size and not maximize_tls_size_done:
+        error('{}: TLS maximum size was not updated'.format(f.name))
 
 def get_parser():
     parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument('-a', dest='align', required=True,
+    parser.add_argument('-a', dest='align',
                         help='How to set the LOAD alignment')
+    parser.add_argument('--maximize-tls-size', action='store_true',
+                        help='Set maximum PT_TLS size')
     parser.add_argument('output',
                         help='ELF file to edit')
     return parser
@@ -199,7 +219,7 @@ def main(argv):
     parser = get_parser()
     opts = parser.parse_args(argv)
     with open(opts.output, 'r+b') as fout:
-       elf_edit(fout, opts.align)
+       elf_edit(fout, opts)
 
 
 if __name__ == '__main__':
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 4a5e698db2..5d0369358d 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1211,6 +1211,11 @@ extern struct link_map * _dl_get_dl_main_map (void)
 # endif
 #endif
 
+/* Perform early memory allocation, avoding a TCB dependency.
+   Terminate the process if allocation fails.  May attempt to use
+   brk.  */
+void *_dl_early_allocate (size_t size) attribute_hidden;
+
 /* Initialize the DSO sort algorithm to use.  */
 #if !HAVE_TUNABLES
 static inline void
diff --git a/sysdeps/unix/sysv/linux/dl-early_allocate.c b/sysdeps/unix/sysv/linux/dl-early_allocate.c
new file mode 100644
index 0000000000..2c77b6e3ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-early_allocate.c
@@ -0,0 +1,81 @@
+/* Early memory allocation for the dynamic loader.  Generic version.
+   Copyright (C) 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/>.  */
+
+/* Mark symbols hidden in static PIE for early self relocation to work.  */
+#if BUILD_PIE_DEFAULT
+# pragma GCC visibility push(hidden)
+#endif
+#include <startup.h>
+
+#include <ldsodefs.h>
+#include <stddef.h>
+#include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+
+#include <mmap_call.h>
+
+/* Defined in brk.c.  */
+extern void *__curbrk;
+
+void *
+_dl_early_allocate (size_t size)
+{
+  void *result;
+
+  if (__curbrk != NULL)
+    /* If the break has been initialized, brk must have run before,
+       so just call it once more.  */
+    {
+      result = __sbrk (size);
+      if (result == (void *) -1)
+        result = NULL;
+    }
+  else
+    {
+      /* If brk has not been invoked, there is no need to update
+         __curbrk.  The first call to brk will take care of that.  */
+      void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0);
+      result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size);
+      if (result == previous)
+        result = NULL;
+      else
+        result = previous;
+    }
+
+  /* If brk fails, fall back to mmap.  This can happen due to
+     unfortunate ASLR layout decisions and kernel bugs, particularly
+     for static PIE.  */
+  if (result == NULL)
+    {
+      long int ret;
+      int prot = PROT_READ | PROT_WRITE;
+      int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+#ifdef __NR_mmap2
+      ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0);
+#else
+      ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0);
+#endif
+      if (INTERNAL_SYSCALL_ERROR_P (ret))
+        result = NULL;
+      else
+        result = (void *) ret;
+    }
+
+  return result;
+}
-- 
2.35.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal
  2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
@ 2022-05-05 15:28   ` Andreas Schwab
  2022-05-05 15:43     ` Florian Weimer
  2022-05-05 17:29   ` Adhemerval Zanella
  1 sibling, 1 reply; 17+ messages in thread
From: Andreas Schwab @ 2022-05-05 15:28 UTC (permalink / raw)
  To: Florian Weimer via Libc-alpha; +Cc: Florian Weimer

On Mai 05 2022, Florian Weimer via Libc-alpha wrote:

> +/* 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 ();                               \
> +        }                                                               \

I think that could use _Static_assert.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal
  2022-05-05 15:28   ` Andreas Schwab
@ 2022-05-05 15:43     ` Florian Weimer
  0 siblings, 0 replies; 17+ messages in thread
From: Florian Weimer @ 2022-05-05 15:43 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Florian Weimer via Libc-alpha

* Andreas Schwab:

> On Mai 05 2022, Florian Weimer via Libc-alpha wrote:
>
>> +/* 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 ();                               \
>> +        }                                                               \
>
> I think that could use _Static_assert.

It only works for simple cases, not for arguments that require constant
progagation:

libc-tls.c: In function ‘__libc_setup_tls’:
../sysdeps/unix/sysv/linux/startup.h:29:23: error: expression in static assertion is not constant
   29 |       _Static_assert (__builtin_constant_p (__message_length),          \
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Thanks,
Florian


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro
  2022-05-05 15:06 [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Florian Weimer
  2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
  2022-05-05 15:08 ` [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup Florian Weimer
@ 2022-05-05 17:28 ` Adhemerval Zanella
  2 siblings, 0 replies; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-05 17:28 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 05/05/2022 12:06, Florian Weimer via Libc-alpha wrote:
> And keep the previous definition if it exists.  This allows
> disabling IA64_USE_NEW_STUB while keeping USE_DL_SYSINFO defined.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
> v4: Unchanged.
> v3: Fix “statup” typo.  Do not use libpthread and librt in conditional.
> 
>  sysdeps/unix/sysv/linux/ia64/brk.c    |  5 ++---
>  sysdeps/unix/sysv/linux/ia64/sysdep.h | 23 +++++++++++++----------
>  2 files changed, 15 insertions(+), 13 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/ia64/brk.c b/sysdeps/unix/sysv/linux/ia64/brk.c
> index 65142aeae9..d2135b74fc 100644
> --- a/sysdeps/unix/sysv/linux/ia64/brk.c
> +++ b/sysdeps/unix/sysv/linux/ia64/brk.c
> @@ -16,7 +16,6 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <dl-sysdep.h>
> -/* brk is used by statup before TCB is properly set.  */
> -#undef USE_DL_SYSINFO
> +/* brk is used by startup before TCB is properly set up.  */
> +#define IA64_USE_NEW_STUB 0
>  #include <sysdeps/unix/sysv/linux/brk.c>
> diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h
> index 193ecee023..14adbdf4ff 100644
> --- a/sysdeps/unix/sysv/linux/ia64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h
> @@ -44,12 +44,15 @@
>  #undef SYS_ify
>  #define SYS_ify(syscall_name)	__NR_##syscall_name
>  
> -#if defined USE_DL_SYSINFO \
> -	&& (IS_IN (libc) \
> -	    || IS_IN (libpthread) || IS_IN (librt))
> -# define IA64_USE_NEW_STUB
> -#else
> -# undef IA64_USE_NEW_STUB
> +#ifndef IA64_USE_NEW_STUB
> +# if defined USE_DL_SYSINFO && IS_IN (libc)
> +#  define IA64_USE_NEW_STUB 1
> +# else
> +#  define IA64_USE_NEW_STUB 0
> +# endif
> +#endif
> +#if IA64_USE_NEW_STUB && !USE_DL_SYSINFO
> +# error IA64_USE_NEW_STUB needs USE_DL_SYSINFO
>  #endif
>  
>  #ifdef __ASSEMBLER__
> @@ -101,7 +104,7 @@
>  	mov r15=num;				\
>  	break __IA64_BREAK_SYSCALL
>  
> -#ifdef IA64_USE_NEW_STUB
> +#if IA64_USE_NEW_STUB
>  # ifdef SHARED
>  #  define DO_CALL(num)				\
>  	.prologue;				\
> @@ -185,7 +188,7 @@
>     (non-negative) errno on error or the return value on success.
>   */
>  
> -#ifdef IA64_USE_NEW_STUB
> +#if IA64_USE_NEW_STUB
>  
>  # define INTERNAL_SYSCALL_NCS(name, nr, args...)			      \
>  ({									      \
> @@ -277,7 +280,7 @@
>  #define ASM_OUTARGS_5	ASM_OUTARGS_4, "=r" (_out4)
>  #define ASM_OUTARGS_6	ASM_OUTARGS_5, "=r" (_out5)
>  
> -#ifdef IA64_USE_NEW_STUB
> +#if IA64_USE_NEW_STUB
>  #define ASM_ARGS_0
>  #define ASM_ARGS_1	ASM_ARGS_0, "4" (_out0)
>  #define ASM_ARGS_2	ASM_ARGS_1, "5" (_out1)
> @@ -313,7 +316,7 @@
>    /* Branch registers.  */						\
>    "b6"
>  
> -#ifdef IA64_USE_NEW_STUB
> +#if IA64_USE_NEW_STUB
>  # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON
>  #else
>  # define ASM_CLOBBERS_6	ASM_CLOBBERS_6_COMMON , "b7"
> 
> base-commit: c1b68685d438373efe64e5f076f4215723004dfb

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal
  2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
  2022-05-05 15:28   ` Andreas Schwab
@ 2022-05-05 17:29   ` Adhemerval Zanella
  1 sibling, 0 replies; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-05 17:29 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 05/05/2022 12:07, Florian Weimer via Libc-alpha wrote:
> On i386 and ia64, the TCB is not available at this point.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
> v4: Unchanged.
> v3: Use 2022 copyright year.  Fix “statup” typo.  Use __message_length
>     local variable in _startup_fatal.
>  sysdeps/unix/sysv/linux/i386/startup.h | 23 +++------------
>  sysdeps/unix/sysv/linux/ia64/startup.h | 22 +++++++++++++++
>  sysdeps/unix/sysv/linux/startup.h      | 39 ++++++++++++++++++++++++++
>  3 files changed, 65 insertions(+), 19 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/ia64/startup.h
>  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..213805d7d2 100644
> --- a/sysdeps/unix/sysv/linux/i386/startup.h
> +++ b/sysdeps/unix/sysv/linux/i386/startup.h
> @@ -1,5 +1,5 @@
>  /* Linux/i386 definitions of functions used by static libc main startup.
> -   Copyright (C) 2017-2022 Free Software Foundation, Inc.
> +   Copyright (C) 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
> @@ -16,22 +16,7 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#if BUILD_PIE_DEFAULT
> -/* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE.  */
> -# define I386_USE_SYSENTER 0
> +/* Can't use "call *%gs:SYSINFO_OFFSET" during startup.  */
> +#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/ia64/startup.h b/sysdeps/unix/sysv/linux/ia64/startup.h
> new file mode 100644
> index 0000000000..77f29f15a2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/ia64/startup.h
> @@ -0,0 +1,22 @@
> +/* Linux/ia64 definitions of functions used by static libc main startup.
> +   Copyright (C) 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/>.  */
> +
> +/* This code is used before the TCB is set up.  */
> +#define IA64_USE_NEW_STUB 0
> +
> +#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..39859b404a
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/startup.h
> @@ -0,0 +1,39 @@
> +/* 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 */

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 15:08 ` [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup Florian Weimer
@ 2022-05-05 17:48   ` Adhemerval Zanella
  2022-05-05 18:03     ` Florian Weimer
  2022-05-06 13:19   ` Adhemerval Zanella
  1 sibling, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-05 17:48 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 05/05/2022 12:08, Florian Weimer via Libc-alpha wrote:
> This implements mmap fallback for a brk failure during TLS
> allocation.
> 
> scripts/tls-elf-edit.py is updated to support the new patching method.
> The script no longer requires that in the input object is of ET_DYN
> type.
> ---
> v4: Do not call __libc_fatal from generic _dl_early_allocate.
> v3: Remove spurious empty line change.
>  csu/libc-tls.c                              | 11 ++-
>  elf/Makefile                                | 19 +++++
>  elf/dl-early_allocate.c                     | 30 ++++++++
>  elf/tst-tls-allocation-failure-static.c     | 31 ++++++++
>  scripts/tst-elf-edit.py                     | 34 +++++++--
>  sysdeps/generic/ldsodefs.h                  |  5 ++
>  sysdeps/unix/sysv/linux/dl-early_allocate.c | 81 +++++++++++++++++++++
>  7 files changed, 201 insertions(+), 10 deletions(-)
>  create mode 100644 elf/dl-early_allocate.c
>  create mode 100644 elf/tst-tls-allocation-failure-static.c
>  create mode 100644 sysdeps/unix/sysv/linux/dl-early_allocate.c
> 
> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
> index bef92a7568..0a216c5502 100644
> --- a/csu/libc-tls.c
> +++ b/csu/libc-tls.c
> @@ -145,11 +145,16 @@ __libc_setup_tls (void)
>       _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
>       and dl_tls_static_align.  */
>    tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align);
> -  tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
> +  tlsblock = _dl_early_allocate (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
> +  if (tlsblock == NULL)
> +    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
>  #elif TLS_DTV_AT_TP
>    tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
> -  tlsblock = __sbrk (tcb_offset + memsz + max_align
> -		     + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus));
> +  tlsblock = _dl_early_allocate (tcb_offset + memsz + max_align
> +				 + TLS_PRE_TCB_SIZE
> +				 + GLRO(dl_tls_static_surplus));
> +  if (tlsblock == NULL)
> +    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
>    tlsblock += TLS_PRE_TCB_SIZE;
>  #else
>    /* In case a model with a different layout for the TCB and DTV

Ok.

> diff --git a/elf/Makefile b/elf/Makefile
> index fc9860edee..ce3345ed92 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -33,6 +33,7 @@ routines = \
>    $(all-dl-routines) \
>    dl-addr \
>    dl-addr-obj \
> +  dl-early_allocate \
>    dl-error \
>    dl-iteratephdr \
>    dl-libc \
> @@ -108,6 +109,7 @@ all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
>  # But they are absent from the shared libc, because that code is in ld.so.
>  elide-routines.os = \
>    $(all-dl-routines) \
> +  dl-early_allocate \
>    dl-exception \
>    dl-origin \
>    dl-reloc-static-pie \
> @@ -276,6 +278,7 @@ tests-static-normal := \
>    tst-linkall-static \
>    tst-single_threaded-pthread-static \
>    tst-single_threaded-static \
> +  tst-tls-allocation-failure-static \
>    tst-tlsalign-extern-static \
>    tst-tlsalign-static \
>    # tests-static-normal
> @@ -1213,6 +1216,10 @@ $(objpfx)tst-glibcelf.out: tst-glibcelf.py elf.h $(..)/scripts/glibcelf.py \
>            --cc="$(CC) $(patsubst -DMODULE_NAME=%,-DMODULE_NAME=testsuite,$(CPPFLAGS))" \
>  	  < /dev/null > $@ 2>&1; $(evaluate-test)
>  
> +ifeq ($(run-built-tests),yes)
> +tests-special += $(objpfx)tst-tls-allocation-failure-static-patched.out
> +endif
> +
>  # The test requires shared _and_ PIE because the executable
>  # unit test driver must be able to link with the shared object
>  # that is going to eventually go into an installed DSO.
> @@ -2937,3 +2944,15 @@ $(eval $(call tst-trace-skeleton,4,\
>  	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4))
>  $(eval $(call tst-trace-skeleton,5,\
>  	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4:$(objpfx)libtracemod5))
> +
> +$(objpfx)tst-tls-allocation-failure-static-patched: \
> +  $(objpfx)tst-tls-allocation-failure-static $(..)scripts/tst-elf-edit.py
> +	cp $< $@
> +	$(PYTHON) $(..)scripts/tst-elf-edit.py --maximize-tls-size $@
> +
> +$(objpfx)tst-tls-allocation-failure-static-patched.out: \
> +  $(objpfx)tst-tls-allocation-failure-static-patched
> +	$< > $@ 2>&1; echo "status: $$?" >> $@
> +	grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
> +	  && grep -q '^status: 127$$' $@; \
> +	  $(evaluate-test)

Ok.

> diff --git a/elf/dl-early_allocate.c b/elf/dl-early_allocate.c
> new file mode 100644
> index 0000000000..61677aaa03
> --- /dev/null
> +++ b/elf/dl-early_allocate.c
> @@ -0,0 +1,30 @@
> +/* Early memory allocation for the dynamic loader.  Generic version.
> +   Copyright (C) 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/>.  */
> +
> +#include <ldsodefs.h>
> +#include <stddef.h>
> +#include <unistd.h>
> +
> +void *
> +_dl_early_allocate (size_t size)
> +{
> +  void *result = __sbrk (size);
> +  if (result == (void *) -1)
> +    result = NULL;
> +  return result;
> +}

I still think there will be way simpler to just use mmap here, it will allow
to use a generic version without the need to fiddle with a Linux specific 
(it will be required just a wrapper to MMAP_CALL_INTERNAL, instead of an
implementation that need to know both sbrk and mmap internals).

I think you even clean up all the dl-brk.c and similar files required to
make brk/sbrk work on the loader with an allocator that only uses mmap.

> diff --git a/elf/tst-tls-allocation-failure-static.c b/elf/tst-tls-allocation-failure-static.c
> new file mode 100644
> index 0000000000..8de831b246
> --- /dev/null
> +++ b/elf/tst-tls-allocation-failure-static.c
> @@ -0,0 +1,31 @@
> +/* Base for test program with impossiblyh large PT_TLS segment.
> +   Copyright (C) 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/>.  */
> +
> +/* The test actual binary is patched using scripts/tst-elf-edit.py
> +   --maximize-tls-size, and this introduces the expected test
> +   allocation failure due to an excessive PT_LS p_memsz value.
> +
> +   Patching the binary is required because on some 64-bit targets, TLS
> +   relocations can only cover a 32-bit range, and glibc-internal TLS
> +   variables such as errno end up outside that range.  */
> +
> +int
> +main (void)
> +{
> +  return 0;
> +}
> diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py
> index a514179bbf..0e19ce1e73 100644
> --- a/scripts/tst-elf-edit.py
> +++ b/scripts/tst-elf-edit.py
> @@ -43,9 +43,11 @@ EI_DATA=5
>  ELFDATA2LSB=b'\x01'
>  ELFDATA2MSB=b'\x02'
>  
> +ET_EXEC=2
>  ET_DYN=3
>  
>  PT_LOAD=1
> +PT_TLS=7
>  
>  def elf_types_fmts(e_ident):
>      endian = '<' if e_ident[EI_DATA] == ELFDATA2LSB else '>'
> @@ -146,8 +148,15 @@ def elf_edit_align(phdr, align):
>      else:
>          phdr.p_align = int(align)
>  
> +def elf_edit_maximize_tls_size(phdr, elfclass):
> +    if elfclass == ELFCLASS32:
> +        # It is possible that the kernel can allocate half of the
> +        # address space, so use something larger.
> +        phdr.p_memsz = 0xfff00000
> +    else:
> +        phdr.p_memsz = 1 << 63
>  
> -def elf_edit(f, align):
> +def elf_edit(f, opts):
>      ei_nident_fmt = 'c' * EI_NIDENT
>      ei_nident_len = struct.calcsize(ei_nident_fmt)
>  
> @@ -172,24 +181,35 @@ def elf_edit(f, align):
>  
>      ehdr = Elf_Ehdr(e_ident)
>      ehdr.read(f)
> -    if ehdr.e_type != ET_DYN:
> -       error('{}: not a shared library'.format(f.name))
> +    if ehdr.e_type not in (ET_EXEC, ET_DYN):
> +       error('{}: not an executable or shared library'.format(f.name))
>  
>      phdr = Elf_Phdr(e_ident)
> +    maximize_tls_size_done = False
>      for i in range(0, ehdr.e_phnum):
>          f.seek(ehdr.e_phoff + i * phdr.len)
>          phdr.read(f)
> -        if phdr.p_type == PT_LOAD:
> -            elf_edit_align(phdr, align)
> +        if phdr.p_type == PT_LOAD and opts.align is not None:
> +            elf_edit_align(phdr, opts.align)
> +            f.seek(ehdr.e_phoff + i * phdr.len)
> +            phdr.write(f)
> +            break
> +        if phdr.p_type == PT_TLS and opts.maximize_tls_size:
> +            elf_edit_maximize_tls_size(phdr, e_ident[EI_CLASS])
>              f.seek(ehdr.e_phoff + i * phdr.len)
>              phdr.write(f)
> +            maximize_tls_size_done = True
>              break
>  
> +    if opts.maximize_tls_size and not maximize_tls_size_done:
> +        error('{}: TLS maximum size was not updated'.format(f.name))
>  
>  def get_parser():
>      parser = argparse.ArgumentParser(description=__doc__)
> -    parser.add_argument('-a', dest='align', required=True,
> +    parser.add_argument('-a', dest='align',
>                          help='How to set the LOAD alignment')
> +    parser.add_argument('--maximize-tls-size', action='store_true',
> +                        help='Set maximum PT_TLS size')
>      parser.add_argument('output',
>                          help='ELF file to edit')
>      return parser
> @@ -199,7 +219,7 @@ def main(argv):
>      parser = get_parser()
>      opts = parser.parse_args(argv)
>      with open(opts.output, 'r+b') as fout:
> -       elf_edit(fout, opts.align)
> +       elf_edit(fout, opts)
>  
>  
>  if __name__ == '__main__':
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 4a5e698db2..5d0369358d 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1211,6 +1211,11 @@ extern struct link_map * _dl_get_dl_main_map (void)
>  # endif
>  #endif
>  
> +/* Perform early memory allocation, avoding a TCB dependency.
> +   Terminate the process if allocation fails.  May attempt to use
> +   brk.  */
> +void *_dl_early_allocate (size_t size) attribute_hidden;
> +
>  /* Initialize the DSO sort algorithm to use.  */
>  #if !HAVE_TUNABLES
>  static inline void
> diff --git a/sysdeps/unix/sysv/linux/dl-early_allocate.c b/sysdeps/unix/sysv/linux/dl-early_allocate.c
> new file mode 100644
> index 0000000000..2c77b6e3ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/dl-early_allocate.c
> @@ -0,0 +1,81 @@
> +/* Early memory allocation for the dynamic loader.  Generic version.
> +   Copyright (C) 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/>.  */
> +
> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
> +#if BUILD_PIE_DEFAULT
> +# pragma GCC visibility push(hidden)
> +#endif
> +#include <startup.h>
> +
> +#include <ldsodefs.h>
> +#include <stddef.h>
> +#include <string.h>
> +#include <sysdep.h>
> +#include <unistd.h>
> +
> +#include <mmap_call.h>
> +
> +/* Defined in brk.c.  */
> +extern void *__curbrk;
> +
> +void *
> +_dl_early_allocate (size_t size)
> +{
> +  void *result;
> +
> +  if (__curbrk != NULL)
> +    /* If the break has been initialized, brk must have run before,
> +       so just call it once more.  */
> +    {
> +      result = __sbrk (size);
> +      if (result == (void *) -1)
> +        result = NULL;
> +    }
> +  else
> +    {
> +      /* If brk has not been invoked, there is no need to update
> +         __curbrk.  The first call to brk will take care of that.  */
> +      void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0);
> +      result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size);
> +      if (result == previous)
> +        result = NULL;
> +      else
> +        result = previous;
> +    }
> +
> +  /* If brk fails, fall back to mmap.  This can happen due to
> +     unfortunate ASLR layout decisions and kernel bugs, particularly
> +     for static PIE.  */
> +  if (result == NULL)
> +    {
> +      long int ret;
> +      int prot = PROT_READ | PROT_WRITE;
> +      int flags = MAP_PRIVATE | MAP_ANONYMOUS;
> +#ifdef __NR_mmap2
> +      ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0);
> +#else
> +      ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0);
> +#endif
> +      if (INTERNAL_SYSCALL_ERROR_P (ret))
> +        result = NULL;
> +      else
> +        result = (void *) ret;
> +    }
> +
> +  return result;
> +}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 17:48   ` Adhemerval Zanella
@ 2022-05-05 18:03     ` Florian Weimer
  2022-05-05 18:25       ` Adhemerval Zanella
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2022-05-05 18:03 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

* Adhemerval Zanella:

> I still think there will be way simpler to just use mmap here, it will allow
> to use a generic version without the need to fiddle with a Linux specific 
> (it will be required just a wrapper to MMAP_CALL_INTERNAL, instead of an
> implementation that need to know both sbrk and mmap internals).

We need to wrap the difference in error checking as well.

> I think you even clean up all the dl-brk.c and similar files required to
> make brk/sbrk work on the loader with an allocator that only uses mmap.

At the cost of additional VMAs, sure.  We won't be able to reuse the
unused tail of the allocation easily because we do not know the page
size yet.  __minimal_malloc does not yet work at this point.  We also
lose some ASLR.  I'm not convinced it's worth it.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 18:03     ` Florian Weimer
@ 2022-05-05 18:25       ` Adhemerval Zanella
  2022-05-06 10:00         ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-05 18:25 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha



On 05/05/2022 15:03, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> I still think there will be way simpler to just use mmap here, it will allow
>> to use a generic version without the need to fiddle with a Linux specific 
>> (it will be required just a wrapper to MMAP_CALL_INTERNAL, instead of an
>> implementation that need to know both sbrk and mmap internals).
> 
> We need to wrap the difference in error checking as well.
> 
>> I think you even clean up all the dl-brk.c and similar files required to
>> make brk/sbrk work on the loader with an allocator that only uses mmap.
> 
> At the cost of additional VMAs, sure.  We won't be able to reuse the
> unused tail of the allocation easily because we do not know the page
> size yet.  __minimal_malloc does not yet work at this point.  We also
> lose some ASLR.  I'm not convinced it's worth it.

It is another code that does something similar to __minimal_malloc to
a specific usage, so now we have another allocation scheme that is used
solely for static initialization.  And it does something different than
__minimal_malloc, so has different semantic.

I am not really against it, but initialization code is already 
quite complex with a lot of different paths for dynamic/static case,
so I think it would be good to have single loader/static allocation 
code.  

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 18:25       ` Adhemerval Zanella
@ 2022-05-06 10:00         ` Florian Weimer
  2022-05-06 13:04           ` Adhemerval Zanella
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2022-05-06 10:00 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

* Adhemerval Zanella:

> On 05/05/2022 15:03, Florian Weimer wrote:
>> * Adhemerval Zanella:
>> 
>>> I still think there will be way simpler to just use mmap here, it will allow
>>> to use a generic version without the need to fiddle with a Linux specific 
>>> (it will be required just a wrapper to MMAP_CALL_INTERNAL, instead of an
>>> implementation that need to know both sbrk and mmap internals).
>> 
>> We need to wrap the difference in error checking as well.
>> 
>>> I think you even clean up all the dl-brk.c and similar files required to
>>> make brk/sbrk work on the loader with an allocator that only uses mmap.
>> 
>> At the cost of additional VMAs, sure.  We won't be able to reuse the
>> unused tail of the allocation easily because we do not know the page
>> size yet.  __minimal_malloc does not yet work at this point.  We also
>> lose some ASLR.  I'm not convinced it's worth it.
>
> It is another code that does something similar to __minimal_malloc to
> a specific usage, so now we have another allocation scheme that is used
> solely for static initialization.  And it does something different than
> __minimal_malloc, so has different semantic.
>
> I am not really against it, but initialization code is already 
> quite complex with a lot of different paths for dynamic/static case,
> so I think it would be good to have single loader/static allocation 
> code.  

As I said, we don't have the page size yet at this point, and
__minimal_malloc needs to know that.  And there are likely other
obstacles to consolidation.

How can we move this forward?

Thanks,
Florian


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-06 10:00         ` Florian Weimer
@ 2022-05-06 13:04           ` Adhemerval Zanella
  0 siblings, 0 replies; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-06 13:04 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha



On 06/05/2022 07:00, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> On 05/05/2022 15:03, Florian Weimer wrote:
>>> * Adhemerval Zanella:
>>>
>>>> I still think there will be way simpler to just use mmap here, it will allow
>>>> to use a generic version without the need to fiddle with a Linux specific 
>>>> (it will be required just a wrapper to MMAP_CALL_INTERNAL, instead of an
>>>> implementation that need to know both sbrk and mmap internals).
>>>
>>> We need to wrap the difference in error checking as well.
>>>
>>>> I think you even clean up all the dl-brk.c and similar files required to
>>>> make brk/sbrk work on the loader with an allocator that only uses mmap.
>>>
>>> At the cost of additional VMAs, sure.  We won't be able to reuse the
>>> unused tail of the allocation easily because we do not know the page
>>> size yet.  __minimal_malloc does not yet work at this point.  We also
>>> lose some ASLR.  I'm not convinced it's worth it.
>>
>> It is another code that does something similar to __minimal_malloc to
>> a specific usage, so now we have another allocation scheme that is used
>> solely for static initialization.  And it does something different than
>> __minimal_malloc, so has different semantic.
>>
>> I am not really against it, but initialization code is already 
>> quite complex with a lot of different paths for dynamic/static case,
>> so I think it would be good to have single loader/static allocation 
>> code.  
> 
> As I said, we don't have the page size yet at this point, and
> __minimal_malloc needs to know that.  And there are likely other
> obstacles to consolidation.

But for !SHARED we do call _dl_aux_init before ARCH_SETUP_TLS, so
we can access GRLO(dl_pagesize).  

> How can we move this forward?

I am still not very found of bleeding misc/sbrk.c details to Linux
dl-early_allocate.c, but this is not a blocker for the patch.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-05 15:08 ` [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup Florian Weimer
  2022-05-05 17:48   ` Adhemerval Zanella
@ 2022-05-06 13:19   ` Adhemerval Zanella
  2022-05-09 16:10     ` Florian Weimer
  1 sibling, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-06 13:19 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 05/05/2022 12:08, Florian Weimer via Libc-alpha wrote:
> This implements mmap fallback for a brk failure during TLS
> allocation.
> 
> scripts/tls-elf-edit.py is updated to support the new patching method.
> The script no longer requires that in the input object is of ET_DYN
> type.
> ---
> v4: Do not call __libc_fatal from generic _dl_early_allocate.
> v3: Remove spurious empty line change.
>  csu/libc-tls.c                              | 11 ++-
>  elf/Makefile                                | 19 +++++
>  elf/dl-early_allocate.c                     | 30 ++++++++
>  elf/tst-tls-allocation-failure-static.c     | 31 ++++++++
>  scripts/tst-elf-edit.py                     | 34 +++++++--
>  sysdeps/generic/ldsodefs.h                  |  5 ++
>  sysdeps/unix/sysv/linux/dl-early_allocate.c | 81 +++++++++++++++++++++
>  7 files changed, 201 insertions(+), 10 deletions(-)
>  create mode 100644 elf/dl-early_allocate.c
>  create mode 100644 elf/tst-tls-allocation-failure-static.c
>  create mode 100644 sysdeps/unix/sysv/linux/dl-early_allocate.c
> 
> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
> index bef92a7568..0a216c5502 100644
> --- a/csu/libc-tls.c
> +++ b/csu/libc-tls.c
> @@ -145,11 +145,16 @@ __libc_setup_tls (void)
>       _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
>       and dl_tls_static_align.  */
>    tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align);
> -  tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
> +  tlsblock = _dl_early_allocate (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
> +  if (tlsblock == NULL)
> +    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
>  #elif TLS_DTV_AT_TP
>    tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
> -  tlsblock = __sbrk (tcb_offset + memsz + max_align
> -		     + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus));
> +  tlsblock = _dl_early_allocate (tcb_offset + memsz + max_align
> +				 + TLS_PRE_TCB_SIZE
> +				 + GLRO(dl_tls_static_surplus));
> +  if (tlsblock == NULL)
> +    _startup_fatal ("Fatal glibc error: Cannot allocate TLS block\n");
>    tlsblock += TLS_PRE_TCB_SIZE;
>  #else
>    /* In case a model with a different layout for the TCB and DTV
> diff --git a/elf/Makefile b/elf/Makefile
> index fc9860edee..ce3345ed92 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -33,6 +33,7 @@ routines = \
>    $(all-dl-routines) \
>    dl-addr \
>    dl-addr-obj \
> +  dl-early_allocate \
>    dl-error \
>    dl-iteratephdr \
>    dl-libc \
> @@ -108,6 +109,7 @@ all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
>  # But they are absent from the shared libc, because that code is in ld.so.
>  elide-routines.os = \
>    $(all-dl-routines) \
> +  dl-early_allocate \
>    dl-exception \
>    dl-origin \
>    dl-reloc-static-pie \
> @@ -276,6 +278,7 @@ tests-static-normal := \
>    tst-linkall-static \
>    tst-single_threaded-pthread-static \
>    tst-single_threaded-static \
> +  tst-tls-allocation-failure-static \
>    tst-tlsalign-extern-static \
>    tst-tlsalign-static \
>    # tests-static-normal
> @@ -1213,6 +1216,10 @@ $(objpfx)tst-glibcelf.out: tst-glibcelf.py elf.h $(..)/scripts/glibcelf.py \
>            --cc="$(CC) $(patsubst -DMODULE_NAME=%,-DMODULE_NAME=testsuite,$(CPPFLAGS))" \
>  	  < /dev/null > $@ 2>&1; $(evaluate-test)
>  
> +ifeq ($(run-built-tests),yes)
> +tests-special += $(objpfx)tst-tls-allocation-failure-static-patched.out
> +endif
> +
>  # The test requires shared _and_ PIE because the executable
>  # unit test driver must be able to link with the shared object
>  # that is going to eventually go into an installed DSO.
> @@ -2937,3 +2944,15 @@ $(eval $(call tst-trace-skeleton,4,\
>  	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4))
>  $(eval $(call tst-trace-skeleton,5,\
>  	$(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4:$(objpfx)libtracemod5))
> +
> +$(objpfx)tst-tls-allocation-failure-static-patched: \
> +  $(objpfx)tst-tls-allocation-failure-static $(..)scripts/tst-elf-edit.py
> +	cp $< $@
> +	$(PYTHON) $(..)scripts/tst-elf-edit.py --maximize-tls-size $@
> +
> +$(objpfx)tst-tls-allocation-failure-static-patched.out: \
> +  $(objpfx)tst-tls-allocation-failure-static-patched
> +	$< > $@ 2>&1; echo "status: $$?" >> $@
> +	grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
> +	  && grep -q '^status: 127$$' $@; \
> +	  $(evaluate-test)
> diff --git a/elf/dl-early_allocate.c b/elf/dl-early_allocate.c
> new file mode 100644
> index 0000000000..61677aaa03
> --- /dev/null
> +++ b/elf/dl-early_allocate.c
> @@ -0,0 +1,30 @@
> +/* Early memory allocation for the dynamic loader.  Generic version.
> +   Copyright (C) 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/>.  */
> +
> +#include <ldsodefs.h>
> +#include <stddef.h>
> +#include <unistd.h>
> +
> +void *
> +_dl_early_allocate (size_t size)
> +{
> +  void *result = __sbrk (size);
> +  if (result == (void *) -1)
> +    result = NULL;
> +  return result;
> +}

Ok.

> diff --git a/elf/tst-tls-allocation-failure-static.c b/elf/tst-tls-allocation-failure-static.c
> new file mode 100644
> index 0000000000..8de831b246
> --- /dev/null
> +++ b/elf/tst-tls-allocation-failure-static.c
> @@ -0,0 +1,31 @@
> +/* Base for test program with impossiblyh large PT_TLS segment.
> +   Copyright (C) 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/>.  */
> +
> +/* The test actual binary is patched using scripts/tst-elf-edit.py
> +   --maximize-tls-size, and this introduces the expected test
> +   allocation failure due to an excessive PT_LS p_memsz value.
> +
> +   Patching the binary is required because on some 64-bit targets, TLS
> +   relocations can only cover a 32-bit range, and glibc-internal TLS
> +   variables such as errno end up outside that range.  */
> +
> +int
> +main (void)
> +{
> +  return 0;
> +}
> diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py
> index a514179bbf..0e19ce1e73 100644
> --- a/scripts/tst-elf-edit.py
> +++ b/scripts/tst-elf-edit.py
> @@ -43,9 +43,11 @@ EI_DATA=5
>  ELFDATA2LSB=b'\x01'
>  ELFDATA2MSB=b'\x02'
>  
> +ET_EXEC=2
>  ET_DYN=3
>  
>  PT_LOAD=1
> +PT_TLS=7
>  
>  def elf_types_fmts(e_ident):
>      endian = '<' if e_ident[EI_DATA] == ELFDATA2LSB else '>'
> @@ -146,8 +148,15 @@ def elf_edit_align(phdr, align):
>      else:
>          phdr.p_align = int(align)
>  
> +def elf_edit_maximize_tls_size(phdr, elfclass):
> +    if elfclass == ELFCLASS32:
> +        # It is possible that the kernel can allocate half of the
> +        # address space, so use something larger.
> +        phdr.p_memsz = 0xfff00000
> +    else:
> +        phdr.p_memsz = 1 << 63
>  
> -def elf_edit(f, align):
> +def elf_edit(f, opts):
>      ei_nident_fmt = 'c' * EI_NIDENT
>      ei_nident_len = struct.calcsize(ei_nident_fmt)
>  
> @@ -172,24 +181,35 @@ def elf_edit(f, align):
>  
>      ehdr = Elf_Ehdr(e_ident)
>      ehdr.read(f)
> -    if ehdr.e_type != ET_DYN:
> -       error('{}: not a shared library'.format(f.name))
> +    if ehdr.e_type not in (ET_EXEC, ET_DYN):
> +       error('{}: not an executable or shared library'.format(f.name))
>  
>      phdr = Elf_Phdr(e_ident)
> +    maximize_tls_size_done = False
>      for i in range(0, ehdr.e_phnum):
>          f.seek(ehdr.e_phoff + i * phdr.len)
>          phdr.read(f)
> -        if phdr.p_type == PT_LOAD:
> -            elf_edit_align(phdr, align)
> +        if phdr.p_type == PT_LOAD and opts.align is not None:

I think you can omit the None check.

> +            elf_edit_align(phdr, opts.align)
> +            f.seek(ehdr.e_phoff + i * phdr.len)
> +            phdr.write(f)
> +            break
> +        if phdr.p_type == PT_TLS and opts.maximize_tls_size:
> +            elf_edit_maximize_tls_size(phdr, e_ident[EI_CLASS])
>              f.seek(ehdr.e_phoff + i * phdr.len)
>              phdr.write(f)
> +            maximize_tls_size_done = True
>              break
>  
> +    if opts.maximize_tls_size and not maximize_tls_size_done:
> +        error('{}: TLS maximum size was not updated'.format(f.name))
>  
>  def get_parser():
>      parser = argparse.ArgumentParser(description=__doc__)
> -    parser.add_argument('-a', dest='align', required=True,
> +    parser.add_argument('-a', dest='align',
>                          help='How to set the LOAD alignment')
> +    parser.add_argument('--maximize-tls-size', action='store_true',
> +                        help='Set maximum PT_TLS size')
>      parser.add_argument('output',
>                          help='ELF file to edit')
>      return parser
> @@ -199,7 +219,7 @@ def main(argv):
>      parser = get_parser()
>      opts = parser.parse_args(argv)
>      with open(opts.output, 'r+b') as fout:
> -       elf_edit(fout, opts.align)
> +       elf_edit(fout, opts)
>  
>  
>  if __name__ == '__main__':

Ok.

> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 4a5e698db2..5d0369358d 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1211,6 +1211,11 @@ extern struct link_map * _dl_get_dl_main_map (void)
>  # endif
>  #endif
>  
> +/* Perform early memory allocation, avoding a TCB dependency.
> +   Terminate the process if allocation fails.  May attempt to use
> +   brk.  */
> +void *_dl_early_allocate (size_t size) attribute_hidden;
> +
>  /* Initialize the DSO sort algorithm to use.  */
>  #if !HAVE_TUNABLES
>  static inline void
> diff --git a/sysdeps/unix/sysv/linux/dl-early_allocate.c b/sysdeps/unix/sysv/linux/dl-early_allocate.c
> new file mode 100644
> index 0000000000..2c77b6e3ff
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/dl-early_allocate.c
> @@ -0,0 +1,81 @@
> +/* Early memory allocation for the dynamic loader.  Generic version.
> +   Copyright (C) 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/>.  */
> +
> +/* Mark symbols hidden in static PIE for early self relocation to work.  */
> +#if BUILD_PIE_DEFAULT
> +# pragma GCC visibility push(hidden)
> +#endif
> +#include <startup.h>
> +
> +#include <ldsodefs.h>
> +#include <stddef.h>
> +#include <string.h>
> +#include <sysdep.h>
> +#include <unistd.h>
> +
> +#include <mmap_call.h>
> +
> +/* Defined in brk.c.  */
> +extern void *__curbrk;
> +
> +void *
> +_dl_early_allocate (size_t size)
> +{
> +  void *result;
> +
> +  if (__curbrk != NULL)
> +    /* If the break has been initialized, brk must have run before,
> +       so just call it once more.  */
> +    {
> +      result = __sbrk (size);
> +      if (result == (void *) -1)
> +        result = NULL;
> +    }
> +  else
> +    {
> +      /* If brk has not been invoked, there is no need to update
> +         __curbrk.  The first call to brk will take care of that.  */
> +      void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0);
> +      result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size);
> +      if (result == previous)
> +        result = NULL;
> +      else
> +        result = previous;

You will need to factor it be arch-specific since alpha return -ENOMEM
in case of failure and sparc has different calling convention (similar 
to what it does for clone).  Maybe add a

static inline void *
brk_call (void *addr)
{
  void *r = syscall;
  r = check_error (r) ? -1 : 0;
}

And then refactor Linux brk.c versions to use brk_call as well.

> +    }
> +
> +  /* If brk fails, fall back to mmap.  This can happen due to
> +     unfortunate ASLR layout decisions and kernel bugs, particularly
> +     for static PIE.  */
> +  if (result == NULL)
> +    {
> +      long int ret;
> +      int prot = PROT_READ | PROT_WRITE;
> +      int flags = MAP_PRIVATE | MAP_ANONYMOUS;
> +#ifdef __NR_mmap2
> +      ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0);
> +#else
> +      ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0);
> +#endif
> +      if (INTERNAL_SYSCALL_ERROR_P (ret))

Maybe move it to mmap_call.h and make it a static inline:

static inline void *
mmap64_call (void *addr, size_t len, int prot, int flags, int fd, 
	   off64_t offset)
{
  long int ret;
#ifdef __NR_mmap2
  ret = MMAP_CALL_INTERNAL (mmap2, addr, len, prot, flags, fd,
			    (off_t) (offset / MMAP2_PAGE_UNIT));
#else
  ret = MMAP_CALL_INTERNAL (mmap, addr, len, prot, flags, fd,
			    offset);
#endif
  return INTERNAL_SYSCALL_ERROR_P (ret) ? NULL : (void *) ret;
}

static inline void *
mmap_call_internal (size_t len)
{
  int prot = PROT_READ | PROT_WRITE;
  int flags = MAP_PRIVATE | MAP_ANONYMOUS;
  return mmap64_call (0, len, PROT_READ | PROT_WRITE,
		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}

> +        result = NULL;
> +      else
> +        result = (void *) ret;
> +    }
> +
> +  return result;
> +}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-06 13:19   ` Adhemerval Zanella
@ 2022-05-09 16:10     ` Florian Weimer
  2022-05-09 16:52       ` Adhemerval Zanella
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2022-05-09 16:10 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

* Adhemerval Zanella:

>> diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py
>> index a514179bbf..0e19ce1e73 100644
>> --- a/scripts/tst-elf-edit.py
>> +++ b/scripts/tst-elf-edit.py

>> @@ -172,24 +181,35 @@ def elf_edit(f, align):
>>  
>>      ehdr = Elf_Ehdr(e_ident)
>>      ehdr.read(f)
>> -    if ehdr.e_type != ET_DYN:
>> -       error('{}: not a shared library'.format(f.name))
>> +    if ehdr.e_type not in (ET_EXEC, ET_DYN):
>> +       error('{}: not an executable or shared library'.format(f.name))
>>  
>>      phdr = Elf_Phdr(e_ident)
>> +    maximize_tls_size_done = False
>>      for i in range(0, ehdr.e_phnum):
>>          f.seek(ehdr.e_phoff + i * phdr.len)
>>          phdr.read(f)
>> -        if phdr.p_type == PT_LOAD:
>> -            elf_edit_align(phdr, align)
>> +        if phdr.p_type == PT_LOAD and opts.align is not None:
>
> I think you can omit the None check.

I think this will raise an exception in elf_edit_align because the -a
argument is now optional.

>> +void *
>> +_dl_early_allocate (size_t size)
>> +{
>> +  void *result;
>> +
>> +  if (__curbrk != NULL)
>> +    /* If the break has been initialized, brk must have run before,
>> +       so just call it once more.  */
>> +    {
>> +      result = __sbrk (size);
>> +      if (result == (void *) -1)
>> +        result = NULL;
>> +    }
>> +  else
>> +    {
>> +      /* If brk has not been invoked, there is no need to update
>> +         __curbrk.  The first call to brk will take care of that.  */
>> +      void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0);
>> +      result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size);
>> +      if (result == previous)
>> +        result = NULL;
>> +      else
>> +        result = previous;
>
> You will need to factor it be arch-specific since alpha return -ENOMEM
> in case of failure and sparc has different calling convention (similar 
> to what it does for clone).  Maybe add a
>
> static inline void *
> brk_call (void *addr)
> {
>   void *r = syscall;
>   r = check_error (r) ? -1 : 0;
> }
>
> And then refactor Linux brk.c versions to use brk_call as well.

Thanks.  I'm testing a new version with this change.

>> +  /* If brk fails, fall back to mmap.  This can happen due to
>> +     unfortunate ASLR layout decisions and kernel bugs, particularly
>> +     for static PIE.  */
>> +  if (result == NULL)
>> +    {
>> +      long int ret;
>> +      int prot = PROT_READ | PROT_WRITE;
>> +      int flags = MAP_PRIVATE | MAP_ANONYMOUS;
>> +#ifdef __NR_mmap2
>> +      ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0);
>> +#else
>> +      ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0);
>> +#endif
>> +      if (INTERNAL_SYSCALL_ERROR_P (ret))
>
> Maybe move it to mmap_call.h and make it a static inline:
>
> static inline void *
> mmap64_call (void *addr, size_t len, int prot, int flags, int fd, 
> 	   off64_t offset)
> {
>   long int ret;
> #ifdef __NR_mmap2
>   ret = MMAP_CALL_INTERNAL (mmap2, addr, len, prot, flags, fd,
> 			    (off_t) (offset / MMAP2_PAGE_UNIT));
> #else
>   ret = MMAP_CALL_INTERNAL (mmap, addr, len, prot, flags, fd,
> 			    offset);
> #endif
>   return INTERNAL_SYSCALL_ERROR_P (ret) ? NULL : (void *) ret;
> }
>
> static inline void *
> mmap_call_internal (size_t len)
> {
>   int prot = PROT_READ | PROT_WRITE;
>   int flags = MAP_PRIVATE | MAP_ANONYMOUS;
>   return mmap64_call (0, len, PROT_READ | PROT_WRITE,
> 		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> }

We have several customization points for mmap and mmap2.
MMAP2_PAGE_UNIT can expand to a static global variable page_unit.  This
is difficult to encapsulate properly in an inline function.  Adding
__brk_call was simple enough, but this looks way more complex.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-09 16:10     ` Florian Weimer
@ 2022-05-09 16:52       ` Adhemerval Zanella
  2022-05-09 17:08         ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-09 16:52 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha



On 09/05/2022 13:10, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>> diff --git a/scripts/tst-elf-edit.py b/scripts/tst-elf-edit.py
>>> index a514179bbf..0e19ce1e73 100644
>>> --- a/scripts/tst-elf-edit.py
>>> +++ b/scripts/tst-elf-edit.py
> 
>>> @@ -172,24 +181,35 @@ def elf_edit(f, align):
>>>  
>>>      ehdr = Elf_Ehdr(e_ident)
>>>      ehdr.read(f)
>>> -    if ehdr.e_type != ET_DYN:
>>> -       error('{}: not a shared library'.format(f.name))
>>> +    if ehdr.e_type not in (ET_EXEC, ET_DYN):
>>> +       error('{}: not an executable or shared library'.format(f.name))
>>>  
>>>      phdr = Elf_Phdr(e_ident)
>>> +    maximize_tls_size_done = False
>>>      for i in range(0, ehdr.e_phnum):
>>>          f.seek(ehdr.e_phoff + i * phdr.len)
>>>          phdr.read(f)
>>> -        if phdr.p_type == PT_LOAD:
>>> -            elf_edit_align(phdr, align)
>>> +        if phdr.p_type == PT_LOAD and opts.align is not None:
>>
>> I think you can omit the None check.
> 
> I think this will raise an exception in elf_edit_align because the -a
> argument is now optional.
> 
>>> +void *
>>> +_dl_early_allocate (size_t size)
>>> +{
>>> +  void *result;
>>> +
>>> +  if (__curbrk != NULL)
>>> +    /* If the break has been initialized, brk must have run before,
>>> +       so just call it once more.  */
>>> +    {
>>> +      result = __sbrk (size);
>>> +      if (result == (void *) -1)
>>> +        result = NULL;
>>> +    }
>>> +  else
>>> +    {
>>> +      /* If brk has not been invoked, there is no need to update
>>> +         __curbrk.  The first call to brk will take care of that.  */
>>> +      void *previous = (void *) INTERNAL_SYSCALL_CALL (brk, 0);
>>> +      result = (void *) INTERNAL_SYSCALL_CALL (brk, previous + size);
>>> +      if (result == previous)
>>> +        result = NULL;
>>> +      else
>>> +        result = previous;
>>
>> You will need to factor it be arch-specific since alpha return -ENOMEM
>> in case of failure and sparc has different calling convention (similar 
>> to what it does for clone).  Maybe add a
>>
>> static inline void *
>> brk_call (void *addr)
>> {
>>   void *r = syscall;
>>   r = check_error (r) ? -1 : 0;
>> }
>>
>> And then refactor Linux brk.c versions to use brk_call as well.
> 
> Thanks.  I'm testing a new version with this change.
> 
>>> +  /* If brk fails, fall back to mmap.  This can happen due to
>>> +     unfortunate ASLR layout decisions and kernel bugs, particularly
>>> +     for static PIE.  */
>>> +  if (result == NULL)
>>> +    {
>>> +      long int ret;
>>> +      int prot = PROT_READ | PROT_WRITE;
>>> +      int flags = MAP_PRIVATE | MAP_ANONYMOUS;
>>> +#ifdef __NR_mmap2
>>> +      ret = MMAP_CALL_INTERNAL (mmap2, 0, size, prot, flags, -1, 0);
>>> +#else
>>> +      ret = MMAP_CALL_INTERNAL (mmap, 0, size, prot, flags, -1, 0);
>>> +#endif
>>> +      if (INTERNAL_SYSCALL_ERROR_P (ret))
>>
>> Maybe move it to mmap_call.h and make it a static inline:
>>
>> static inline void *
>> mmap64_call (void *addr, size_t len, int prot, int flags, int fd, 
>> 	   off64_t offset)
>> {
>>   long int ret;
>> #ifdef __NR_mmap2
>>   ret = MMAP_CALL_INTERNAL (mmap2, addr, len, prot, flags, fd,
>> 			    (off_t) (offset / MMAP2_PAGE_UNIT));
>> #else
>>   ret = MMAP_CALL_INTERNAL (mmap, addr, len, prot, flags, fd,
>> 			    offset);
>> #endif
>>   return INTERNAL_SYSCALL_ERROR_P (ret) ? NULL : (void *) ret;
>> }
>>
>> static inline void *
>> mmap_call_internal (size_t len)
>> {
>>   int prot = PROT_READ | PROT_WRITE;
>>   int flags = MAP_PRIVATE | MAP_ANONYMOUS;
>>   return mmap64_call (0, len, PROT_READ | PROT_WRITE,
>> 		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>> }
> 
> We have several customization points for mmap and mmap2.
> MMAP2_PAGE_UNIT can expand to a static global variable page_unit.  This
> is difficult to encapsulate properly in an inline function.  Adding
> __brk_call was simple enough, but this looks way more complex.

The idea is to allow __mmap64 use the mmap64_call and have the syscall
logic in one place.  Something like:

void *
__mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
{
  MMAP_CHECK_PAGE_UNIT ();

  if (offset & MMAP_OFF_MASK)
    return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

  MMAP_PREPARE (addr, len, prot, flags, fd, offset);
  return mmap64_call (addr, len, prot, flags, fd, offset);
}


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-09 16:52       ` Adhemerval Zanella
@ 2022-05-09 17:08         ` Florian Weimer
  2022-05-09 17:37           ` Adhemerval Zanella
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2022-05-09 17:08 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

* Adhemerval Zanella:

> The idea is to allow __mmap64 use the mmap64_call and have the syscall
> logic in one place.  Something like:
>
> void *
> __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
> {
>   MMAP_CHECK_PAGE_UNIT ();
>
>   if (offset & MMAP_OFF_MASK)
>     return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
>
>   MMAP_PREPARE (addr, len, prot, flags, fd, offset);
>   return mmap64_call (addr, len, prot, flags, fd, offset);
> }

With this, a definition of mmap64_call still needs a working definition
of MMAP2_PAGE_UNIT for mmap2 targets, I think.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup
  2022-05-09 17:08         ` Florian Weimer
@ 2022-05-09 17:37           ` Adhemerval Zanella
  0 siblings, 0 replies; 17+ messages in thread
From: Adhemerval Zanella @ 2022-05-09 17:37 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha



On 09/05/2022 14:08, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> The idea is to allow __mmap64 use the mmap64_call and have the syscall
>> logic in one place.  Something like:
>>
>> void *
>> __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
>> {
>>   MMAP_CHECK_PAGE_UNIT ();
>>
>>   if (offset & MMAP_OFF_MASK)
>>     return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
>>
>>   MMAP_PREPARE (addr, len, prot, flags, fd, offset);
>>   return mmap64_call (addr, len, prot, flags, fd, offset);
>> }
> 
> With this, a definition of mmap64_call still needs a working definition
> of MMAP2_PAGE_UNIT for mmap2 targets, I think.

We can add the MMAP2_PAGE_UNIT as an additional argument for mmap64_call
and use a valid but unused value, I think compiler would see than using 0
 as offset argument and optimize the division away.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-05-09 17:37 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-05 15:06 [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Florian Weimer
2022-05-05 15:07 ` [PATCH v4 2/3] Linux: Implement a useful version of _startup_fatal Florian Weimer
2022-05-05 15:28   ` Andreas Schwab
2022-05-05 15:43     ` Florian Weimer
2022-05-05 17:29   ` Adhemerval Zanella
2022-05-05 15:08 ` [PATCH v4 3/3] csu: Implement and use _dl_early_allocate during static startup Florian Weimer
2022-05-05 17:48   ` Adhemerval Zanella
2022-05-05 18:03     ` Florian Weimer
2022-05-05 18:25       ` Adhemerval Zanella
2022-05-06 10:00         ` Florian Weimer
2022-05-06 13:04           ` Adhemerval Zanella
2022-05-06 13:19   ` Adhemerval Zanella
2022-05-09 16:10     ` Florian Weimer
2022-05-09 16:52       ` Adhemerval Zanella
2022-05-09 17:08         ` Florian Weimer
2022-05-09 17:37           ` Adhemerval Zanella
2022-05-05 17:28 ` [PATCH v4 1/3] ia64: Always define IA64_USE_NEW_STUB as a flag macro Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).