public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH glibc 0/9] Restartable Sequences enablement
@ 2020-03-26 15:56 Mathieu Desnoyers
  2020-03-26 15:56 ` [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h> Mathieu Desnoyers
                   ` (10 more replies)
  0 siblings, 11 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers

Hi,

Please find the rseq-enablement patchset for comments in this series.

This patch series is based on glibc master branch at commit
1fabdb9908 x86: Remove ARCH_CET_LEGACY_BITMAP [BZ #25397]

Since the last post:

- Move elf/elf_machine_sym_no_match.h to sysdeps/generic (additional
  patch).
- Move NEWS entry under 2.32.
- Move new __rseq_abi symbol to GLIBC_2.32.

Please consider for merging into glibc.

Mathieu


Florian Weimer (3):
  Introduce <elf_machine_sym_no_match.h>
  Implement __libc_early_init
  nptl: Start new threads with all signals blocked [BZ #25098]

Mathieu Desnoyers (6):
  Move elf/elf_machine_sym_no_match.h to sysdeps/generic
  glibc: Perform rseq(2) registration at C startup and thread creation
    (v17)
  glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7)
  support record failure: allow use from constructor
  support: implement xpthread key create/delete (v4)
  rseq registration tests (v9)

 NEWS                                          |  12 +-
 csu/init-first.c                              |   4 -
 csu/libc-start.c                              |   5 +
 elf/Makefile                                  |   5 +-
 elf/Versions                                  |   1 +
 elf/dl-call-libc-early-init.c                 |  41 +++
 elf/dl-load.c                                 |   9 +
 elf/dl-lookup-direct.c                        | 116 ++++++
 elf/dl-lookup.c                               |  10 +-
 elf/dl-open.c                                 |  24 ++
 elf/libc-early-init.h                         |  35 ++
 elf/libc_early_init.c                         |  30 ++
 elf/rtld.c                                    |   4 +
 manual/threads.texi                           |  30 +-
 misc/rseq-internal.h                          |  33 ++
 nptl/descr.h                                  |  10 +-
 nptl/pthread_create.c                         |  56 ++-
 support/Makefile                              |   2 +
 support/check.h                               |   4 +
 support/support_record_failure.c              |  18 +-
 support/xpthread_key_create.c                 |  25 ++
 support/xpthread_key_delete.c                 |  24 ++
 support/xthread.h                             |   2 +
 sysdeps/generic/elf_machine_sym_no_match.h    |  34 ++
 sysdeps/generic/ldsodefs.h                    |  17 +
 sysdeps/mach/hurd/i386/init-first.c           |   4 -
 sysdeps/mips/dl-machine.h                     |  15 -
 sysdeps/mips/elf_machine_sym_no_match.h       |  43 +++
 sysdeps/unix/sysv/linux/Makefile              |  11 +-
 sysdeps/unix/sysv/linux/Versions              |   3 +
 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h   |  43 +++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/arm/bits/rseq.h       |  83 +++++
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/bits/rseq.h           |  29 ++
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
 .../sysv/linux/microblaze/be/libc.abilist     |   1 +
 .../sysv/linux/microblaze/le/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/mips/bits/rseq.h      |  62 ++++
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h   |  37 ++
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/rseq-internal.h       |  73 ++++
 sysdeps/unix/sysv/linux/rseq-sym.c            |  25 ++
 sysdeps/unix/sysv/linux/s390/bits/rseq.h      |  37 ++
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
 sysdeps/unix/sysv/linux/sched_getcpu.c        |  27 +-
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/sys/rseq.h            | 186 ++++++++++
 sysdeps/unix/sysv/linux/tst-rseq-nptl.c       | 347 ++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-rseq.c            | 108 ++++++
 sysdeps/unix/sysv/linux/x86/bits/rseq.h       |  30 ++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
 73 files changed, 1674 insertions(+), 70 deletions(-)
 create mode 100644 elf/dl-call-libc-early-init.c
 create mode 100644 elf/dl-lookup-direct.c
 create mode 100644 elf/libc-early-init.h
 create mode 100644 elf/libc_early_init.c
 create mode 100644 misc/rseq-internal.h
 create mode 100644 support/xpthread_key_create.c
 create mode 100644 support/xpthread_key_delete.c
 create mode 100644 sysdeps/generic/elf_machine_sym_no_match.h
 create mode 100644 sysdeps/mips/elf_machine_sym_no_match.h
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-sym.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c
 create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h

-- 
2.17.1


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

* [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h>
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-22 16:27   ` Carlos O'Donell
  2020-03-26 15:56 ` [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic Mathieu Desnoyers
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

From: Florian Weimer <fweimer@redhat.com>

MIPS needs to ignore certain existing symbols during symbol lookup.
The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
inline function, within its own header, with a sysdeps override for
MIPS.  This allows re-use of the function from another file (without
having to include <dl-machine.h> or providing the default definition
for ELF_MACHINE_SYM_NO_MATCH).

Built with build-many-glibcs.py, with manual verification that
sysdeps/mips/elf_machine_sym_no_match.h is picked up on MIPS.  Tested
on aarch64-linux-gnu, i686-linux-gnu, powerpc64-linux-gnu,
s390x-linux-gnu, x86_64-linux-gnu.
---
 elf/dl-lookup.c                         | 10 ++----
 elf/elf_machine_sym_no_match.h          | 34 +++++++++++++++++++
 sysdeps/mips/dl-machine.h               | 15 ---------
 sysdeps/mips/elf_machine_sym_no_match.h | 43 +++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 23 deletions(-)
 create mode 100644 elf/elf_machine_sym_no_match.h
 create mode 100644 sysdeps/mips/elf_machine_sym_no_match.h

diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 12a229f06c..807f3ea9b6 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -28,18 +28,12 @@
 #include <libc-lock.h>
 #include <tls.h>
 #include <atomic.h>
+#include <elf_machine_sym_no_match.h>
 
 #include <assert.h>
 
-/* Return nonzero if check_match should consider SYM to fail to match a
-   symbol reference for some machine-specific reason.  */
-#ifndef ELF_MACHINE_SYM_NO_MATCH
-# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
-#endif
-
 #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
 
-
 struct sym_val
   {
     const ElfW(Sym) *s;
@@ -78,7 +72,7 @@ check_match (const char *const undef_name,
   if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
 			 && sym->st_shndx != SHN_ABS
 			 && stt != STT_TLS)
-			|| ELF_MACHINE_SYM_NO_MATCH (sym)
+			|| elf_machine_sym_no_match (sym)
 			|| (type_class & (sym->st_shndx == SHN_UNDEF))))
     return NULL;
 
diff --git a/elf/elf_machine_sym_no_match.h b/elf/elf_machine_sym_no_match.h
new file mode 100644
index 0000000000..6e299e5ee8
--- /dev/null
+++ b/elf/elf_machine_sym_no_match.h
@@ -0,0 +1,34 @@
+/* Function to ignore certain symbol matches for machine-specific reasons.
+   Copyright (C) 2019 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/>.  */
+
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
+#define _ELF_MACHINE_SYM_NO_MATCH_H
+
+#include <link.h>
+#include <stdbool.h>
+
+/* This can be customized to ignore certain symbols during lookup in
+   case there are machine-specific rules to disregard some
+   symbols.  */
+static inline bool
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
+{
+  return false;
+}
+
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 06021ea9ab..e3b11a4f21 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
   return value;
 }
 
-/* The semantics of zero/non-zero values of undefined symbols differs
-   depending on whether the non-PIC ABI is in use.  Under the non-PIC
-   ABI, a non-zero value indicates that there is an address reference
-   to the symbol and thus it must always be resolved (except when
-   resolving a jump slot relocation) to the PLT entry whose address is
-   provided as the symbol's value; a zero value indicates that this
-   canonical-address behaviour is not required.  Yet under the classic
-   MIPS psABI, a zero value indicates that there is an address
-   reference to the function and the dynamic linker must resolve the
-   symbol immediately upon loading.  To avoid conflict, symbols for
-   which the dynamic linker must assume the non-PIC ABI semantics are
-   marked with the STO_MIPS_PLT flag.  */
-#define ELF_MACHINE_SYM_NO_MATCH(sym) \
-  ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
-
 #endif /* !dl_machine_h */
 
 #ifdef RESOLVE_MAP
diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h
new file mode 100644
index 0000000000..f2be74caaf
--- /dev/null
+++ b/sysdeps/mips/elf_machine_sym_no_match.h
@@ -0,0 +1,43 @@
+/* MIPS-specific handling of undefined symbols.
+   Copyright (C) 2008-2019 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/>.  */
+
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
+#define _ELF_MACHINE_SYM_NO_MATCH_H
+
+#include <link.h>
+#include <stdbool.h>
+
+/* The semantics of zero/non-zero values of undefined symbols differs
+   depending on whether the non-PIC ABI is in use.  Under the non-PIC
+   ABI, a non-zero value indicates that there is an address reference
+   to the symbol and thus it must always be resolved (except when
+   resolving a jump slot relocation) to the PLT entry whose address is
+   provided as the symbol's value; a zero value indicates that this
+   canonical-address behaviour is not required.  Yet under the classic
+   MIPS psABI, a zero value indicates that there is an address
+   reference to the function and the dynamic linker must resolve the
+   symbol immediately upon loading.  To avoid conflict, symbols for
+   which the dynamic linker must assume the non-PIC ABI semantics are
+   marked with the STO_MIPS_PLT flag.  */
+static inline bool
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
+{
+  return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT);
+}
+
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
-- 
2.17.1


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

* [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
  2020-03-26 15:56 ` [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h> Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-22 16:27   ` Carlos O'Donell
  2020-03-26 15:56 ` [PATCH glibc 3/9] Implement __libc_early_init Mathieu Desnoyers
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers

sysdeps/generic/elf_machine_sym_no_match.h matches
sysdeps/mips/elf_machine_sym_no_match.h better.

Suggested-by: H.J. Lu <hjl.tools@gmail.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Florian Weimer <fweimer@redhat.com>
---
 {elf => sysdeps/generic}/elf_machine_sym_no_match.h | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename {elf => sysdeps/generic}/elf_machine_sym_no_match.h (100%)

diff --git a/elf/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h
similarity index 100%
rename from elf/elf_machine_sym_no_match.h
rename to sysdeps/generic/elf_machine_sym_no_match.h
-- 
2.17.1


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

* [PATCH glibc 3/9] Implement __libc_early_init
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
  2020-03-26 15:56 ` [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h> Mathieu Desnoyers
  2020-03-26 15:56 ` [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-22 16:28   ` Carlos O'Donell
  2020-03-26 15:56 ` [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098] Mathieu Desnoyers
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

From: Florian Weimer <fweimer@redhat.com>

This function is defined in libc.so, and the dynamic loader calls
right after relocation has been finished, before any ELF constructors
or the preinit function is invoked.  It is also used in the static
build for initializing parts of the static libc.

To locate __libc_early_init, a direct symbol lookup function is used,
_dl_lookup_direct.  It does not search the entire symbol scope and
consults merely a single link map.  This function could also be used
to implement lookups in the vDSO (as an optimization).

A per-namespace variable (libc_map) is added for locating libc.so,
to avoid repeated traversals of the search scope.  It is similar to
GL(dl_initfirst).  An alternative would have been to thread a context
argument from _dl_open down to _dl_map_object_from_fd (where libc.so
is identified).  This could have avoided the global variable, but
the change would be larger as a result.  It would not have been
possible to use this to replace GL(dl_initfirst) because that global
variable is used to pass the function pointer past the stack switch
from dl_main to the main program.  Replacing that requires adding
a new argument to _dl_init, which in turn needs changes to the
architecture-specific libc.so startup code written in assembler.

__libc_early_init should not be used to replace _dl_var_init (as
it exists today on some architectures).  Instead, _dl_lookup_direct
should be used to look up a new variable symbol in libc.so, and
that should then be initialized from the dynamic loader, immediately
after the object has been loaded in _dl_map_object_from_fd (before
relocation is run).  This way, more IFUNC resolvers which depend on
these variables will work.

This version was tested on x86_64-linux-gnu.
---
 csu/init-first.c                    |   4 -
 csu/libc-start.c                    |   5 ++
 elf/Makefile                        |   5 +-
 elf/Versions                        |   1 +
 elf/dl-call-libc-early-init.c       |  41 ++++++++++
 elf/dl-load.c                       |   9 +++
 elf/dl-lookup-direct.c              | 116 ++++++++++++++++++++++++++++
 elf/dl-open.c                       |  24 ++++++
 elf/libc-early-init.h               |  35 +++++++++
 elf/libc_early_init.c               |  27 +++++++
 elf/rtld.c                          |   4 +
 sysdeps/generic/ldsodefs.h          |  17 ++++
 sysdeps/mach/hurd/i386/init-first.c |   4 -
 13 files changed, 282 insertions(+), 10 deletions(-)
 create mode 100644 elf/dl-call-libc-early-init.c
 create mode 100644 elf/dl-lookup-direct.c
 create mode 100644 elf/libc-early-init.h
 create mode 100644 elf/libc_early_init.c

diff --git a/csu/init-first.c b/csu/init-first.c
index 264e6f348d..d214af7116 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -16,7 +16,6 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -75,9 +74,6 @@ _init_first (int argc, char **argv, char **envp)
 
   __init_misc (argc, argv, envp);
 
-  /* Initialize ctype data.  */
-  __ctype_init ();
-
 #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
   __libc_global_ctors ();
 #endif
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 12468c5a89..ccc743c9d1 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -22,6 +22,7 @@
 #include <ldsodefs.h>
 #include <exit-thread.h>
 #include <libc-internal.h>
+#include <elf/libc-early-init.h>
 
 #include <elf/dl-tunables.h>
 
@@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
 
 #ifndef SHARED
+  /* Perform early initialization.  In the shared case, this function
+     is called from the dynamic loader as early as possible.  */
+  __libc_early_init ();
+
   /* Call the initializer of the libc.  This is only needed here if we
      are compiling for the static library in which case we haven't
      run the constructors in `_dl_start_user'.  */
diff --git a/elf/Makefile b/elf/Makefile
index da689a2c7b..23b6043cdb 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -25,7 +25,7 @@ headers		= elf.h bits/elfclass.h link.h bits/link.h
 routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 		  dl-addr dl-addr-obj enbl-secure dl-profstub \
 		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
-		  dl-reloc-static-pie
+		  dl-reloc-static-pie libc_early_init
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -33,7 +33,8 @@ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
 				  runtime init fini debug misc \
 				  version profile tls origin scope \
 				  execstack open close trampoline \
-				  exception sort-maps)
+				  exception sort-maps lookup-direct \
+				  call-libc-early-init)
 ifeq (yes,$(use-ldconfig))
 dl-routines += dl-cache
 endif
diff --git a/elf/Versions b/elf/Versions
index 705489fc51..3be879c4ad 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -26,6 +26,7 @@ libc {
     _dl_open_hook; _dl_open_hook2;
     _dl_sym; _dl_vsym;
     __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
+    __libc_early_init;
 
     # Internal error handling support.  Interposes the functions in ld.so.
     _dl_signal_exception; _dl_catch_exception;
diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
new file mode 100644
index 0000000000..6c3ac5bfe7
--- /dev/null
+++ b/elf/dl-call-libc-early-init.c
@@ -0,0 +1,41 @@
+/* Invoke the early initialization function in libc.so.
+   Copyright (C) 2019 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 <assert.h>
+#include <ldsodefs.h>
+#include <libc-early-init.h>
+#include <link.h>
+#include <stddef.h>
+
+void
+_dl_call_libc_early_init (struct link_map *libc_map)
+{
+  /* There is nothing to do if we did not actually load libc.so.  */
+  if (libc_map == NULL)
+    return;
+
+  const ElfW(Sym) *sym
+    = _dl_lookup_direct (libc_map, "__libc_early_init",
+                         0x69682ac, /* dl_new_hash output.  */
+                         "GLIBC_PRIVATE",
+                         0x0963cf85); /* _dl_elf_hash output.  */
+  assert (sym != NULL);
+  __typeof (__libc_early_init) *early_init
+    = DL_SYMBOL_ADDRESS (libc_map, sym);
+  early_init ();
+}
diff --git a/elf/dl-load.c b/elf/dl-load.c
index a6b80f9395..06f2ba7264 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -30,6 +30,7 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <gnu/lib-names.h>
 
 /* Type for the buffer we put the ELF header and hopefully the program
    header.  This buffer does not really have to be too large.  In most
@@ -1374,6 +1375,14 @@ cannot enable executable stack as shared object requires");
     add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
 			    + l->l_info[DT_SONAME]->d_un.d_val));
 
+  /* If we have newly loaded libc.so, update the namespace
+     description.  */
+  if (GL(dl_ns)[nsid].libc_map == NULL
+      && l->l_info[DT_SONAME] != NULL
+      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
+		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
+    GL(dl_ns)[nsid].libc_map = l;
+
   /* _dl_close can only eventually undo the module ID assignment (via
      remove_slotinfo) if this function returns a pointer to a link
      map.  Therefore, delay this step until all possibilities for
diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
new file mode 100644
index 0000000000..190b826e1e
--- /dev/null
+++ b/elf/dl-lookup-direct.c
@@ -0,0 +1,116 @@
+/* Look up a symbol in a single specified object.
+   Copyright (C) 1995-2019 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 <string.h>
+#include <elf_machine_sym_no_match.h>
+#include <dl-hash.h>
+
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
+   variant here is simplified because it requires symbol
+   versioning. */
+static const ElfW(Sym) *
+check_match (const struct link_map *const map, const char *const undef_name,
+             const char *version, uint32_t version_hash,
+             const Elf_Symndx symidx)
+{
+  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  const ElfW(Sym) *sym = &symtab[symidx];
+
+  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
+  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
+                         && sym->st_shndx != SHN_ABS
+                         && stt != STT_TLS)
+                        || elf_machine_sym_no_match (sym)))
+    return NULL;
+
+  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
+     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
+     code/data definitions.  */
+#define ALLOWED_STT \
+  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
+   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
+  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
+    return NULL;
+
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+  if (strcmp (strtab + sym->st_name, undef_name) != 0)
+    /* Not the symbol we are looking for.  */
+    return NULL;
+
+  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
+  if (map->l_versions[ndx].hash != version_hash
+      || strcmp (map->l_versions[ndx].name, version) != 0)
+    /* It's not the version we want.  */
+    return NULL;
+
+  return sym;
+}
+
+
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
+   variant here is simplified because it does not search object
+   dependencies.  It is optimized for a successful lookup.  */
+const ElfW(Sym) *
+_dl_lookup_direct (struct link_map *map,
+                   const char *undef_name, uint32_t new_hash,
+                   const char *version, uint32_t version_hash)
+{
+  const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
+  if (__glibc_likely (bitmask != NULL))
+    {
+      Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
+      if (bucket != 0)
+        {
+          const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
+
+          do
+            if (((*hasharr ^ new_hash) >> 1) == 0)
+              {
+                Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
+                const ElfW(Sym) *sym = check_match (map, undef_name,
+                                                    version, version_hash,
+                                                    symidx);
+                if (sym != NULL)
+                  return sym;
+              }
+          while ((*hasharr++ & 1u) == 0);
+        }
+    }
+  else
+    {
+      /* Fallback code for lack of GNU_HASH support.  */
+      uint32_t old_hash = _dl_elf_hash (undef_name);
+
+      /* Use the old SysV-style hash table.  Search the appropriate
+         hash bucket in this object's symbol table for a definition
+         for the same symbol name.  */
+      for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
+           symidx != STN_UNDEF;
+           symidx = map->l_chain[symidx])
+        {
+          const ElfW(Sym) *sym = check_match (map, undef_name,
+                                              version, version_hash, symidx);
+          if (sym != NULL)
+            return sym;
+        }
+    }
+
+  return NULL;
+}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 7b3b177aa6..6ff6b64b46 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -34,6 +34,7 @@
 #include <atomic.h>
 #include <libc-internal.h>
 #include <array_length.h>
+#include <libc-early-init.h>
 
 #include <dl-dst.h>
 #include <dl-prop.h>
@@ -57,6 +58,13 @@ struct dl_open_args
      (non-negative).  */
   unsigned int original_global_scope_pending_adds;
 
+  /* Set to true if libc.so was already loaded into the namespace at
+     the time dl_open_worker was called.  This is used to determine
+     whether libc.so early initialization needs to before, and whether
+     to roll back the cached libc_map value in the namespace in case
+     of a dlopen failure.  */
+  bool libc_already_loaded;
+
   /* Original parameters to the program and the current environment.  */
   int argc;
   char **argv;
@@ -500,6 +508,11 @@ dl_open_worker (void *a)
 	args->nsid = call_map->l_ns;
     }
 
+  /* The namespace ID is now known.  Keep track of whether libc.so was
+     already loaded, to determine whether it is necessary to call the
+     early initialization routine (or clear libc_map on error).  */
+  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
+
   /* Retain the old value, so that it can be restored.  */
   args->original_global_scope_pending_adds
     = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
@@ -734,6 +747,11 @@ dl_open_worker (void *a)
   if (relocation_in_progress)
     LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
 
+  /* If libc.so was not there before, attempt to call its early
+     initialization routine.  */
+  if (!args->libc_already_loaded)
+    _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);
+
 #ifndef SHARED
   DL_STATIC_INIT (new);
 #endif
@@ -828,6 +846,7 @@ no more namespaces available for dlmopen()"));
   args.caller_dlopen = caller_dlopen;
   args.map = NULL;
   args.nsid = nsid;
+  args.libc_already_loaded = true; /* No reset below with early failure.  */
   args.argc = argc;
   args.argv = argv;
   args.env = env;
@@ -856,6 +875,11 @@ no more namespaces available for dlmopen()"));
   /* See if an error occurred during loading.  */
   if (__glibc_unlikely (exception.errstring != NULL))
     {
+      /* Avoid keeping around a dangling reference to the libc.so link
+	 map in case it has been cached in libc_map.  */
+      if (!args.libc_already_loaded)
+	GL(dl_ns)[nsid].libc_map = NULL;
+
       /* Remove the object from memory.  It may be in an inconsistent
 	 state if relocation failed, for example.  */
       if (args.map)
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
new file mode 100644
index 0000000000..02b855754e
--- /dev/null
+++ b/elf/libc-early-init.h
@@ -0,0 +1,35 @@
+/* Early initialization of libc.so.
+   Copyright (C) 2019 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/>.  */
+
+#ifndef _LIBC_EARLY_INIT_H
+#define _LIBC_EARLY_INIT_H
+
+struct link_map;
+
+/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
+   and call this function.  */
+void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
+
+/* In the shared case, this function is defined in libc.so and invoked
+   from ld.so (or on the fist static dlopen) after complete relocation
+   of a new loaded libc.so, but before user-defined ELF constructors
+   run.  In the static case, this function is called directly from the
+   startup code.  */
+void __libc_early_init (void);
+
+#endif /* _LIBC_EARLY_INIT_H */
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
new file mode 100644
index 0000000000..1ac66d895d
--- /dev/null
+++ b/elf/libc_early_init.c
@@ -0,0 +1,27 @@
+/* Early initialization of libc.so, libc.so side.
+   Copyright (C) 2019 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 <ctype.h>
+#include <libc-early-init.h>
+
+void
+__libc_early_init (void)
+{
+  /* Initialize ctype data.  */
+  __ctype_init ();
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index 51dfaf966a..912dddd5cd 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -45,6 +45,7 @@
 #include <stap-probe.h>
 #include <stackinfo.h>
 #include <not-cancel.h>
+#include <libc-early-init.h>
 
 #include <assert.h>
 
@@ -2332,6 +2333,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
       rtld_timer_accum (&relocate_time, start);
     }
 
+  /* Relocation is complete.  Perform early libc initialization.  */
+  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);
+
   /* Do any necessary cleanups for the startup OS interface code.
      We do these now so that no calls are made after rtld re-relocation
      which might be resolved to different functions than we expect.
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 497938ffa2..5ff4a2831b 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -336,6 +336,10 @@ struct rtld_global
        recursive dlopen calls from ELF constructors.  */
     unsigned int _ns_global_scope_pending_adds;
 
+    /* Once libc.so has been loaded into the namespace, this points to
+       its link map.  */
+    struct link_map *libc_map;
+
     /* Search table for unique objects.  */
     struct unique_sym_table
     {
@@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
      attribute_hidden;
 
 
+/* Restricted version of _dl_lookup_symbol_x.  Searches MAP (and only
+   MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
+   with dl_new_hash), symbol version VERSION, and symbol version hash
+   VERSION_HASH (computed with _dl_elf_hash).  Returns a pointer to
+   the symbol table entry in MAP on success, or NULL on failure.  MAP
+   must have symbol versioning information, or otherwise the result is
+   undefined.  */
+const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
+				    const char *undef_name,
+				    uint32_t new_hash,
+				    const char *version,
+				    uint32_t version_hash) attribute_hidden;
+
 /* Add the new link_map NEW to the end of the namespace list.  */
 extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
      attribute_hidden;
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 92bf45223f..a7dd4895d9 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -17,7 +17,6 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
-#include <ctype.h>
 #include <hurd.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -85,9 +84,6 @@ posixland_init (int argc, char **argv, char **envp)
 #endif
   __init_misc (argc, argv, envp);
 
-  /* Initialize ctype data.  */
-  __ctype_init ();
-
 #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
   __libc_global_ctors ();
 #endif
-- 
2.17.1


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

* [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098]
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (2 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 3/9] Implement __libc_early_init Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-22 17:04   ` Carlos O'Donell
  2020-03-26 15:56 ` [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17) Mathieu Desnoyers
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

From: Florian Weimer <fweimer@redhat.com>

New threads inherit the signal mask from the current thread.  This
means that signal handlers can run on the newly created thread
immediately after the kernel has created the userspace thread, even
before glibc has initialized the TCB.  Consequently, new threads can
observe uninitialized ctype data, among other things.

To address this, block all signals before starting the thread, and
pass the original signal mask to the start routine wrapper.  On the
new thread, first perform all thread initialization, and then unblock
signals.

The cost of doing this is two rt_sigprocmask system calls on the old
thread, and one rt_sigprocmask system call on the new thread.  (If
there was a way to clone a new thread with a signals disabled, this
could be brought down to one system call each.)  The thread descriptor
increases in size, too, and sigset_t is fairly large.  This increase
could be brought down by reusing space the in the descriptor which is
not needed before running user code, or by switching to an internal
sigset_t definition which only covers the signals supported by the
kernel definition.  (Part of the thread descriptor size increase is
already offset by reduced stack usage in the thread start wrapper
routine after this commit.)
---
 nptl/descr.h          | 10 +++++++---
 nptl/pthread_create.c | 46 +++++++++++++++++++++++--------------------
 2 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/nptl/descr.h b/nptl/descr.h
index 9dcf480bdf..e1c7db5473 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -332,9 +332,8 @@ struct pthread
   /* True if thread must stop at startup time.  */
   bool stopped_start;
 
-  /* The parent's cancel handling at the time of the pthread_create
-     call.  This might be needed to undo the effects of a cancellation.  */
-  int parent_cancelhandling;
+  /* Formerly used for dealing with cancellation.  */
+  int parent_cancelhandling_unsed;
 
   /* Lock to synchronize access to the descriptor.  */
   int lock;
@@ -391,6 +390,11 @@ struct pthread
   /* Resolver state.  */
   struct __res_state res;
 
+  /* Signal mask for the new thread.  Used during thread startup to
+     restore the signal mask.  (Threads are launched with all signals
+     masked.)  */
+  sigset_t sigmask;
+
   /* Indicates whether is a C11 thread created by thrd_creat.  */
   bool c11;
 
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 7c752d0f99..afd379e89a 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -369,7 +369,6 @@ __free_tcb (struct pthread *pd)
     }
 }
 
-
 /* Local function to start thread and handle cleanup.
    createthread.c defines the macro START_THREAD_DEFN to the
    declaration that its create_thread function will refer to, and
@@ -385,10 +384,6 @@ START_THREAD_DEFN
   /* Initialize pointers to locale data.  */
   __ctype_init ();
 
-  /* Allow setxid from now onwards.  */
-  if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
-    futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
-
 #ifndef __ASSUME_SET_ROBUST_LIST
   if (__set_robust_list_avail >= 0)
 #endif
@@ -399,18 +394,6 @@ START_THREAD_DEFN
 			     sizeof (struct robust_list_head));
     }
 
-  /* If the parent was running cancellation handlers while creating
-     the thread the new thread inherited the signal mask.  Reset the
-     cancellation signal mask.  */
-  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
-    {
-      sigset_t mask;
-      __sigemptyset (&mask);
-      __sigaddset (&mask, SIGCANCEL);
-      INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &mask,
-			     NULL, _NSIG / 8);
-    }
-
   /* This is where the try/finally block should be created.  For
      compilers without that support we do use setjmp.  */
   struct pthread_unwind_buf unwind_buf;
@@ -432,6 +415,12 @@ START_THREAD_DEFN
   unwind_buf.priv.data.prev = NULL;
   unwind_buf.priv.data.cleanup = NULL;
 
+  __libc_signal_restore_set (&pd->sigmask);
+
+  /* Allow setxid from now onwards.  */
+  if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
+    futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
+
   if (__glibc_likely (! not_first_call))
     {
       /* Store the new cleanup handler info.  */
@@ -722,10 +711,6 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
   CHECK_THREAD_SYSINFO (pd);
 #endif
 
-  /* Inform start_thread (above) about cancellation state that might
-     translate into inherited signal state.  */
-  pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling);
-
   /* Determine scheduling parameters for the thread.  */
   if (__builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
       && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0)
@@ -771,6 +756,21 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
      ownership of PD (see CONCURRENCY NOTES above).  */
   bool stopped_start = false; bool thread_ran = false;
 
+  /* Block all signals, so that the new thread starts out with
+     signals disabled.  This avoids race conditions in the thread
+     startup.  */
+  sigset_t original_sigmask;
+  __libc_signal_block_all (&original_sigmask);
+
+  /* Conceptually, the new thread needs to inherit the signal mask of
+     this thread.  Therefore, it needs to restore the saved signal
+     mask of this thread, so save it in the startup information.  */
+  pd->sigmask = original_sigmask;
+
+  /* Reset the cancellation signal mask in case this thread is running
+     cancellation.  */
+  __sigdelset (&pd->sigmask, SIGCANCEL);
+
   /* Start the thread.  */
   if (__glibc_unlikely (report_thread_creation (pd)))
     {
@@ -813,6 +813,10 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
     retval = create_thread (pd, iattr, &stopped_start,
 			    STACK_VARIABLES_ARGS, &thread_ran);
 
+  /* Return to the previous signal mask, after creating the new
+     thread.  */
+  __libc_signal_restore_set (&original_sigmask);
+
   if (__glibc_unlikely (retval != 0))
     {
       if (thread_ran)
-- 
2.17.1


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

* [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (3 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098] Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-27  9:11   ` Florian Weimer
  2020-04-27 11:59   ` Florian Weimer
  2020-03-26 15:56 ` [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7) Mathieu Desnoyers
                   ` (5 subsequent siblings)
  10 siblings, 2 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers, Thomas Gleixner, Ben Maurer, Peter Zijlstra,
	Paul E. McKenney, Boqun Feng, Will Deacon, Dave Watson,
	Paul Turner, Rich Felker, linux-kernel, linux-api

Register rseq(2) TLS for each thread (including main), and unregister
for each thread (excluding main). "rseq" stands for Restartable
Sequences.

See the rseq(2) man page proposed here:
  https://lkml.org/lkml/2018/9/19/647

This patch depends on three patches from Florian Weimer:

- Introduce <elf_machine_sym_no_match.h>
- Implement __libc_early_init
- nptl: Start new threads with all signals blocked [BZ #25098]

those are based on glibc master branch commit 1fabdb99084df004f7f4cdc7068d1be209a258be.
The rseq(2) system call was merged into Linux 4.18.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Maurer <bmaurer@fb.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Dave Watson <davejwatson@fb.com>
CC: Paul Turner <pjt@google.com>
CC: Rich Felker <dalias@libc.org>
CC: libc-alpha@sourceware.org
CC: linux-kernel@vger.kernel.org
CC: linux-api@vger.kernel.org
---
Changes since v1:
- Move __rseq_refcount to an extra field at the end of __rseq_abi to
  eliminate one symbol.

  All libraries/programs which try to register rseq (glibc,
  early-adopter applications, early-adopter libraries) should use the
  rseq refcount. It becomes part of the ABI within a user-space
  process, but it's not part of the ABI shared with the kernel per se.

- Restructure how this code is organized so glibc keeps building on
  non-Linux targets.

- Use non-weak symbol for __rseq_abi.

- Move rseq registration/unregistration implementation into its own
  nptl/rseq.c compile unit.

- Move __rseq_abi symbol under GLIBC_2.29.

Changes since v2:
- Move __rseq_refcount to its own symbol, which is less ugly than
  trying to play tricks with the rseq uapi.
- Move __rseq_abi from nptl to csu (C start up), so it can be used
  across glibc, including memory allocator and sched_getcpu(). The
  __rseq_refcount symbol is kept in nptl, because there is no reason
  to use it elsewhere in glibc.

Changes since v3:
- Set __rseq_refcount TLS to 1 on register/set to 0 on unregister
  because glibc is the first/last user.
- Unconditionally register/unregister rseq at thread start/exit, because
  glibc is the first/last user.
- Add missing abilist items.
- Rebase on glibc master commit a502c5294.
- Add NEWS entry.

Changes since v4:
- Do not use "weak" symbols for __rseq_abi and __rseq_refcount. Based on
  "System V Application Binary Interface", weak only affects the link
  editor, not the dynamic linker.
- Install a new sys/rseq.h system header on Linux, which contains the
  RSEQ_SIG definition, __rseq_abi declaration and __rseq_refcount
  declaration. Move those definition/declarations from rseq-internal.h
  to the installed sys/rseq.h header.
- Considering that rseq is only available on Linux, move csu/rseq.c to
  sysdeps/unix/sysv/linux/rseq-sym.c.
- Move __rseq_refcount from nptl/rseq.c to
  sysdeps/unix/sysv/linux/rseq-sym.c, so it is only defined on Linux.
- Move both ABI definitions for __rseq_abi and __rseq_refcount to
  sysdeps/unix/sysv/linux/Versions, so they only appear on Linux.
- Document __rseq_abi and __rseq_refcount volatile.
- Document the RSEQ_SIG signature define.
- Move registration functions from rseq.c to rseq-internal.h static
  inline functions. Introduce empty stubs in misc/rseq-internal.h,
  which can be overridden by architecture code in
  sysdeps/unix/sysv/linux/rseq-internal.h.
- Rename __rseq_register_current_thread and __rseq_unregister_current_thread
  to rseq_register_current_thread and rseq_unregister_current_thread,
  now that those are only visible as internal static inline functions.
- Invoke rseq_register_current_thread() from libc-start.c LIBC_START_MAIN
  rather than nptl init, so applications not linked against
  libpthread.so have rseq registered for their main() thread. Note that
  it is invoked separately for SHARED and !SHARED builds.

Changes since v5:
- Replace __rseq_refcount by __rseq_lib_abi, which contains two
  uint32_t: register_state and refcount. The "register_state" field
  allows inhibiting rseq registration from signal handlers nested on top
  of glibc registration and occuring after rseq unregistration by glibc.
- Introduce enum rseq_register_state, which contains the states allowed
  for the struct rseq_lib_abi register_state field.

Changes since v6:
- Introduce bits/rseq.h to define RSEQ_SIG for each architecture.
  The generic bits/rseq.h does not define RSEQ_SIG, meaning that each
  architecture implementing rseq needs to implement bits/rseq.h.
- Rename enum item RSEQ_REGISTER_NESTED to RSEQ_REGISTER_ONGOING.
- Port to glibc-2.29.

Changes since v7:
- Remove __rseq_lib_abi symbol, including refcount and register_state
  fields.
- Remove reference counting and nested signals handling from
  registration/unregistration functions.
- Introduce new __rseq_handled exported symbol, which is set to 1
  by glibc on C startup when it handles restartable sequences.
  This allows glibc to coexist with early adopter libraries and
  applications wishing to register restartable sequences when it
  is not handled by glibc.
- Introduce rseq_init (), which sets __rseq_handled to 1 from
  C startup.
- Update NEWS entry.
- Update comments at the beginning of new files.
- Registration depends on both __NR_rseq and RSEQ_SIG.
- Remove ARM, powerpc, MIPS RSEQ_SIG until we agree with maintainers
  on the signature choice.
- Update x86, s390 RSEQ_SIG based on discussion with arch maintainers.
- Remove rseq-internal.h from headers list of misc/Makefile, so it
  it not installed by make install.

Changes since v8:
- Introduce RSEQ_SIG_CODE and RSEQ_SIG_DATA on aarch64 to handle
  compiling with -mbig-endian.

Changes since v9:
- Update Changelog.
- Remove unneeded new file comment header newlines.

Changes since v10:
- Remove volatile from __rseq_abi declaration.
- Document that __rseq_handled is about library managing rseq
  registration, independently of whether rseq is available or not.
- Move __rseq_handled symbol to ld.so, initialize this symbol within
  the dynamic linker initialization for both shared (rtld.c) and static
  (dl-support.c) builds.
- Only register the rseq TLS on initialization once in multiple-libc
  scenarios. Use rtld_active () for this purpose.
- In the static libc case, register the rseq TLS after LD_PRELOAD
  constructors are run, so it matches the order of this initialization
  vs LD_PRELOAD contructors execution for the shared libc.
- Agreed on signature choice with powerpc and MIPS maintainers,
  re-adding those signatures,
- The main architecture still left out signature-wise is ARM32.

Changes since v11:
- Rebase on glibc 2.30.
- Re-introduce ARM RSEQ_SIG following feedback from Will Deacon.

Changes since v12:
- Remove __rseq_handled,
- Rely on OS implicit rseq unregistration on thread teardown,
- Register main thread in __libc_early_init ().
- Add Restartable Sequences entry to threads manual.

Changes since v13:
- Update following be/le abilist split for arm, microblaze, and sh.
- Update manual to add the __rseq_abi variable and RSEQ_SIG macro to
  generate manual index entries, and add missing "Restartable Sequences"
  menu entry to the threads chapter.

Changes since v14:
- Update copyright range to include 2020.
- Introduce __ASSUME_RSEQ defined for --enable-kernel=4.18.0 and higher.
- Use ifdef __ASSUME_RSEQ rather than ifdef __NR_rseq to discover rseq
  availability. This is necessary now that the system call numbers are
  integrated within glibc.

Changes since v15:
- Remove __ASSUME_RSEQ from kernel features.
- rseq internal: remove assume rseq
- remove assume rseq and struct rseq def from sysdeps/unix/sysv/linux/rseq-sym.c
- sys/rseq.h: detect rseq header, implement fallback
- sysdeps/unix/sysv/linux/sys/rseq.h include cdefs.h, add _Static_assert
  to validate struct rseq and struct rseq_cs alignment.
- sys/rseq.h: document that posix_memalign should be used rather than
  malloc if allocating struct rseq or struct rseq_cs on the heap. This
  is required to guarantee 32-byte alignement.

Changes since v16:
- Move rseq NEWS entry under 2.32.
- Move new __rseq_abi symbol to GLIBC_2.32.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Maurer <bmaurer@fb.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Paul Turner <pjt@google.com>
CC: Rich Felker <dalias@libc.org>
CC: libc-alpha@sourceware.org
CC: linux-kernel@vger.kernel.org
CC: linux-api@vger.kernel.org
---
 NEWS                                          |  12 +-
 elf/libc_early_init.c                         |   3 +
 manual/threads.texi                           |  30 ++-
 misc/rseq-internal.h                          |  33 ++++
 nptl/pthread_create.c                         |  12 ++
 sysdeps/unix/sysv/linux/Makefile              |   5 +-
 sysdeps/unix/sysv/linux/Versions              |   3 +
 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h   |  43 ++++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/arm/bits/rseq.h       |  83 ++++++++
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/bits/rseq.h           |  29 +++
 sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |   1 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
 .../sysv/linux/microblaze/be/libc.abilist     |   1 +
 .../sysv/linux/microblaze/le/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/mips/bits/rseq.h      |  62 ++++++
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |   1 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h   |  37 ++++
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |   1 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
 sysdeps/unix/sysv/linux/rseq-internal.h       |  73 +++++++
 sysdeps/unix/sysv/linux/rseq-sym.c            |  25 +++
 sysdeps/unix/sysv/linux/s390/bits/rseq.h      |  37 ++++
 .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   1 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   1 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
 sysdeps/unix/sysv/linux/sys/rseq.h            | 186 ++++++++++++++++++
 sysdeps/unix/sysv/linux/x86/bits/rseq.h       |  30 +++
 .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
 47 files changed, 728 insertions(+), 5 deletions(-)
 create mode 100644 misc/rseq-internal.h
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h
 create mode 100644 sysdeps/unix/sysv/linux/rseq-sym.c
 create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h
 create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h

diff --git a/NEWS b/NEWS
index e0379fc53c..cf3e05d5f9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,17 @@ Version 2.32
 
 Major new features:
 
-  * New locale added: ckb_IQ (Kurdish/Sorani spoken in Iraq)
+* New locale added: ckb_IQ (Kurdish/Sorani spoken in Iraq)
+
+* Support for automatically registering threads with the Linux rseq(2)
+  system call has been added.  This system call is implemented starting
+  from Linux 4.18.  The Restartable Sequences ABI accelerates user-space
+  operations on per-cpu data.  It allows user-space to perform updates
+  on per-cpu data without requiring heavy-weight atomic operations.
+  Automatically registering threads allows all libraries, including libc,
+  to make immediate use of the rseq(2) support by using the documented ABI.
+  See 'man 2 rseq' for the details of the ABI shared between libc and the
+  kernel.
 
 Deprecated and removed features, and other changes affecting compatibility:
 
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
index 1ac66d895d..30466afea0 100644
--- a/elf/libc_early_init.c
+++ b/elf/libc_early_init.c
@@ -18,10 +18,13 @@
 
 #include <ctype.h>
 #include <libc-early-init.h>
+#include <rseq-internal.h>
 
 void
 __libc_early_init (void)
 {
   /* Initialize ctype data.  */
   __ctype_init ();
+  /* Register rseq ABI to the kernel.   */
+  (void) rseq_register_current_thread ();
 }
diff --git a/manual/threads.texi b/manual/threads.texi
index 0858ef8f92..59f634e432 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -9,8 +9,10 @@ This chapter describes functions used for managing threads.
 POSIX threads.
 
 @menu
-* ISO C Threads::	Threads based on the ISO C specification.
-* POSIX Threads::	Threads based on the POSIX specification.
+* ISO C Threads::		Threads based on the ISO C specification.
+* POSIX Threads::		Threads based on the POSIX specification.
+* Restartable Sequences::	Linux-specific Restartable Sequences
+				integration.
 @end menu
 
 
@@ -881,3 +883,27 @@ Behaves like @code{pthread_timedjoin_np} except that the absolute time in
 @c pthread_spin_unlock
 @c pthread_testcancel
 @c pthread_yield
+
+@node Restartable Sequences
+@section Restartable Sequences
+@cindex rseq
+
+This section describes @theglibc{} Restartable Sequences integration.
+
+@deftypevar {struct rseq} __rseq_abi
+@standards{GNU, sys/rseq.h}
+@Theglibc{} implements a @code{__rseq_abi} TLS symbol to interact with the
+Restartable Sequences system call (Linux-specific).  The layout of this
+structure is defined by the Linux kernel @file{linux/rseq.h} UAPI.
+Registration of each thread's @code{__rseq_abi} is performed by
+@theglibc{} at libc initialization and pthread creation.
+@end deftypevar
+
+@deftypevr Macro int RSEQ_SIG
+@standards{GNU, sys/rseq.h}
+Each supported architecture provide a @code{RSEQ_SIG} macro in
+@file{sys/rseq.h} which contains a signature.  That signature is expected to be
+present in the code before each Restartable Sequences abort handler.  Failure
+to provide the expected signature may terminate the process with a Segmentation
+fault.
+@end deftypevr
diff --git a/misc/rseq-internal.h b/misc/rseq-internal.h
new file mode 100644
index 0000000000..d564cf1bc3
--- /dev/null
+++ b/misc/rseq-internal.h
@@ -0,0 +1,33 @@
+/* Restartable Sequences internal API. Stub version.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef RSEQ_INTERNAL_H
+#define RSEQ_INTERNAL_H
+
+static inline int
+rseq_register_current_thread (void)
+{
+  return -1;
+}
+
+static inline int
+rseq_unregister_current_thread (void)
+{
+  return -1;
+}
+
+#endif /* rseq-internal.h */
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index afd379e89a..1ff248042e 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -33,6 +33,7 @@
 #include <default-sched.h>
 #include <futex-internal.h>
 #include <tls-setup.h>
+#include <rseq-internal.h>
 #include "libioP.h"
 
 #include <shlib-compat.h>
@@ -384,6 +385,9 @@ START_THREAD_DEFN
   /* Initialize pointers to locale data.  */
   __ctype_init ();
 
+  /* Register rseq TLS to the kernel. */
+  (void) rseq_register_current_thread ();
+
 #ifndef __ASSUME_SET_ROBUST_LIST
   if (__set_robust_list_avail >= 0)
 #endif
@@ -578,6 +582,14 @@ START_THREAD_DEFN
      process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
      flag.  The 'tid' field in the TCB will be set to zero.
 
+     rseq TLS is still registered at this point. Rely on implicit unregistration
+     performed by the kernel on thread teardown. This is not a problem because the
+     rseq TLS lives on the stack, and the stack outlives the thread. If TCB
+     allocation is ever changed, additional steps may be required, such as
+     performing explicit rseq unregistration before reclaiming the rseq TLS area
+     memory. It is NOT sufficient to block signals because the kernel may write
+     to the rseq area even without signals.
+
      The exit code is zero since in case all threads exit by calling
      'pthread_exit' the exit status must be 0 (zero).  */
   __exit_thread ();
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 60dc5cf9e5..6c6f669d21 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -41,7 +41,7 @@ update-syscall-lists: arch-syscall.h
 endif
 
 ifeq ($(subdir),csu)
-sysdep_routines += errno-loc
+sysdep_routines += errno-loc rseq-sym
 endif
 
 ifeq ($(subdir),assert)
@@ -92,7 +92,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
 		  bits/termios-baud.h bits/termios-c_cflag.h \
 		  bits/termios-c_lflag.h bits/termios-tcflow.h \
 		  bits/termios-misc.h \
-		  bits/ipc-perm.h
+		  bits/ipc-perm.h \
+		  sys/rseq.h bits/rseq.h
 
 tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index d385085c61..52ca223ab2 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -177,6 +177,9 @@ libc {
   GLIBC_2.30 {
     getdents64; gettid; tgkill;
   }
+  GLIBC_2.32 {
+    __rseq_abi;
+  }
   GLIBC_PRIVATE {
     # functions used in other libraries
     __syscall_rt_sigqueueinfo;
diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
new file mode 100644
index 0000000000..e272c30446
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
@@ -0,0 +1,43 @@
+/* Restartable Sequences Linux aarch64 architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.
+
+   aarch64 -mbig-endian generates mixed endianness code vs data:
+   little-endian code and big-endian data. Ensure the RSEQ_SIG signature
+   matches code endianness.  */
+
+#define RSEQ_SIG_CODE	0xd428bc00	/* BRK #0x45E0.  */
+
+#ifdef __AARCH64EB__
+#define RSEQ_SIG_DATA	0x00bc28d4	/* BRK #0x45E0.  */
+#else
+#define RSEQ_SIG_DATA	RSEQ_SIG_CODE
+#endif
+
+#define RSEQ_SIG	RSEQ_SIG_DATA
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index a4c31932cb..fa0702d4ac 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2145,3 +2145,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index e7f2174ac2..482c486272 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2225,6 +2225,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index b152c0e24a..753f643c3b 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -133,6 +133,7 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/arm/bits/rseq.h b/sysdeps/unix/sysv/linux/arm/bits/rseq.h
new file mode 100644
index 0000000000..45a2118dbc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/arm/bits/rseq.h
@@ -0,0 +1,83 @@
+/* Restartable Sequences Linux arm architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/*
+   RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.
+
+   - ARM little endian
+
+   RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand
+   value 0x5de3. This traps if user-space reaches this instruction by mistake,
+   and the uncommon operand ensures the kernel does not move the instruction
+   pointer to attacker-controlled code on rseq abort.
+
+   The instruction pattern in the A32 instruction set is:
+
+   e7f5def3    udf    #24035    ; 0x5de3
+
+   This translates to the following instruction pattern in the T16 instruction
+   set:
+
+   little endian:
+   def3        udf    #243      ; 0xf3
+   e7f5        b.n    <7f5>
+
+   - ARMv6+ big endian (BE8):
+
+   ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian
+   code and big-endian data. The data value of the signature needs to have its
+   byte order reversed to generate the trap instruction:
+
+   Data: 0xf3def5e7
+
+   Translates to this A32 instruction pattern:
+
+   e7f5def3    udf    #24035    ; 0x5de3
+
+   Translates to this T16 instruction pattern:
+
+   def3        udf    #243      ; 0xf3
+   e7f5        b.n    <7f5>
+
+   - Prior to ARMv6 big endian (BE32):
+
+   Prior to ARMv6, -mbig-endian generates big-endian code and data
+   (which match), so the endianness of the data representation of the
+   signature should not be reversed. However, the choice between BE32
+   and BE8 is done by the linker, so we cannot know whether code and
+   data endianness will be mixed before the linker is invoked. So rather
+   than try to play tricks with the linker, the rseq signature is simply
+   data (not a trap instruction) prior to ARMv6 on big endian. This is
+   why the signature is expressed as data (.word) rather than as
+   instruction (.inst) in assembler.  */
+
+#ifdef __ARMEB__
+#define RSEQ_SIG    0xf3def5e7      /* udf    #24035    ; 0x5de3 (ARMv6+) */
+#else
+#define RSEQ_SIG    0xe7f5def3      /* udf    #24035    ; 0x5de3 */
+#endif
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index 9371927927..97b1081fa5 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -130,6 +130,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/bits/rseq.h b/sysdeps/unix/sysv/linux/bits/rseq.h
new file mode 100644
index 0000000000..b8a63ed26d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/rseq.h
@@ -0,0 +1,29 @@
+/* Restartable Sequences architecture header. Stub version.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.  */
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 9b3cee65bb..ed94510f23 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2089,3 +2089,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index df6d96fbae..3d60443799 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2046,6 +2046,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index fcb625b6bf..15f0baa54f 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2212,6 +2212,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index cb556c5998..8944cb2cc8 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2078,6 +2078,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 5e3cdea246..ae100260b9 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -134,6 +134,7 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index ea5e7a41af..c2b3f91d17 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2158,6 +2158,7 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index ac55b0acd7..ba9ebeae22 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2140,3 +2140,4 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index f7ced487f7..a1f4f9a1c2 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2137,3 +2137,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/mips/bits/rseq.h b/sysdeps/unix/sysv/linux/mips/bits/rseq.h
new file mode 100644
index 0000000000..4eee59265a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/bits/rseq.h
@@ -0,0 +1,62 @@
+/* Restartable Sequences Linux mips architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.
+
+   RSEQ_SIG uses the break instruction. The instruction pattern is:
+
+   On MIPS:
+        0350000d        break     0x350
+
+   On nanoMIPS:
+        00100350        break     0x350
+
+   On microMIPS:
+        0000d407        break     0x350
+
+   For nanoMIPS32 and microMIPS, the instruction stream is encoded as
+   16-bit halfwords, so the signature halfwords need to be swapped
+   accordingly for little-endian.  */
+
+#if defined(__nanomips__)
+# ifdef __MIPSEL__
+#  define RSEQ_SIG	0x03500010
+# else
+#  define RSEQ_SIG	0x00100350
+# endif
+#elif defined(__mips_micromips)
+# ifdef __MIPSEL__
+#  define RSEQ_SIG	0xd4070000
+# else
+#  define RSEQ_SIG	0x0000d407
+# endif
+#elif defined(__mips__)
+# define RSEQ_SIG	0x0350000d
+#else
+/* Unknown MIPS architecture. */
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 06c2e64edd..333229c27a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2129,6 +2129,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index bdfd073b86..17772e9a40 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2127,6 +2127,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 3d61d4974a..497203cd44 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2135,6 +2135,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 675acca5db..f5f48ce5c6 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2129,6 +2129,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 7fec0c9670..4152f4f734 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2178,3 +2178,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
new file mode 100644
index 0000000000..9d10000a6e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
@@ -0,0 +1,37 @@
+/* Restartable Sequences Linux powerpc architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.
+
+   RSEQ_SIG uses the following trap instruction:
+
+   powerpc-be:    0f e5 00 0b           twui   r5,11
+   powerpc64-le:  0b 00 e5 0f           twui   r5,11
+   powerpc64-be:  0f e5 00 0b           twui   r5,11  */
+
+#define RSEQ_SIG	0x0fe5000b
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 1e8ff6f83e..210d1795c1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2185,6 +2185,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index b5a0751d90..6a3cde5fb6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2218,6 +2218,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 0c86217fc6..4f243acb2a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2048,6 +2048,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 2229a1dcc0..99d836bc11 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2247,3 +2247,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 31010e6cf7..7694392cd5 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2107,3 +2107,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
new file mode 100644
index 0000000000..5f7f02f1ec
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -0,0 +1,73 @@
+/* Restartable Sequences internal API. Linux implementation.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef RSEQ_INTERNAL_H
+#define RSEQ_INTERNAL_H
+
+#include <sysdep.h>
+#include <errno.h>
+#include <kernel-features.h>
+#include <sys/rseq.h>
+
+#ifdef RSEQ_SIG
+
+static inline int
+rseq_register_current_thread (void)
+{
+  int rc, ret = 0;
+
+  if (__rseq_abi.cpu_id == RSEQ_CPU_ID_REGISTRATION_FAILED)
+    return -1;
+  rc = INTERNAL_SYSCALL_CALL (rseq, &__rseq_abi, sizeof (struct rseq),
+                              0, RSEQ_SIG);
+  if (!rc)
+    goto end;
+  if (INTERNAL_SYSCALL_ERRNO (rc) != EBUSY)
+    __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
+  ret = -1;
+end:
+  return ret;
+}
+
+static inline int
+rseq_unregister_current_thread (void)
+{
+  int rc, ret = 0;
+
+  rc = INTERNAL_SYSCALL_CALL (rseq, &__rseq_abi, sizeof (struct rseq),
+                              RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
+  if (!rc)
+    goto end;
+  ret = -1;
+end:
+  return ret;
+}
+#else
+static inline int
+rseq_register_current_thread (void)
+{
+  return -1;
+}
+
+static inline int
+rseq_unregister_current_thread (void)
+{
+  return -1;
+}
+#endif
+
+#endif /* rseq-internal.h */
diff --git a/sysdeps/unix/sysv/linux/rseq-sym.c b/sysdeps/unix/sysv/linux/rseq-sym.c
new file mode 100644
index 0000000000..0e33fab278
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/rseq-sym.c
@@ -0,0 +1,25 @@
+/* Restartable Sequences exported symbols. Linux Implementation.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/syscall.h>
+#include <stdint.h>
+#include <kernel-features.h>
+#include <sys/rseq.h>
+
+__thread struct rseq __rseq_abi = {
+  .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
+};
diff --git a/sysdeps/unix/sysv/linux/s390/bits/rseq.h b/sysdeps/unix/sysv/linux/s390/bits/rseq.h
new file mode 100644
index 0000000000..c25ee67ee7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/bits/rseq.h
@@ -0,0 +1,37 @@
+/* Restartable Sequences Linux s390 architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   It is a 32-bit value that maps to actual architecture code compiled
+   into applications and libraries. It needs to be defined for each
+   architecture. When choosing this value, it needs to be taken into
+   account that generating invalid instructions may have ill effects on
+   tools like objdump, and may also have impact on the CPU speculative
+   execution efficiency in some cases.
+
+   RSEQ_SIG uses the trap4 instruction. As Linux does not make use of the
+   access-register mode nor the linkage stack this instruction will always
+   cause a special-operation exception (the trap-enabled bit in the DUCT
+   is and will stay 0). The instruction pattern is
+       b2 ff 0f ff        trap4   4095(%r0)  */
+
+#define RSEQ_SIG	0xB2FF0FFF
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 4feca641b0..eb49d11cd1 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2183,6 +2183,7 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index efe588a072..442f7e33a8 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2084,6 +2084,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 6bfc2b7439..f47ec14735 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2053,6 +2053,7 @@ GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 4b057bf4a2..8b4557d325 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2050,6 +2050,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 49cd597fd6..52f951c4fe 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2174,6 +2174,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 95e68e0ba1..2b59f52de0 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2101,6 +2101,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
new file mode 100644
index 0000000000..503dce4cac
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h
@@ -0,0 +1,186 @@
+/* Restartable Sequences exported symbols. Linux header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+#define _SYS_RSEQ_H	1
+
+/* Architecture-specific rseq signature.  */
+#include <bits/rseq.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#ifdef __has_include
+# if __has_include ("linux/rseq.h")
+#   define __GLIBC_HAVE_KERNEL_RSEQ
+# endif
+#else
+# include <linux/version.h>
+# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
+#   define __GLIBC_HAVE_KERNEL_RSEQ
+# endif
+#endif
+
+#ifdef __GLIBC_HAVE_KERNEL_RSEQ
+/* We use the structures declarations from the kernel headers.  */
+# include <linux/rseq.h>
+#else
+/* We use a copy of the include/uapi/linux/rseq.h kernel header.  */
+
+#include <asm/byteorder.h>
+
+enum rseq_cpu_id_state
+  {
+    RSEQ_CPU_ID_UNINITIALIZED = -1,
+    RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
+  };
+
+enum rseq_flags
+  {
+    RSEQ_FLAG_UNREGISTER = (1 << 0),
+  };
+
+enum rseq_cs_flags_bit
+  {
+    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
+    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
+    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
+  };
+
+enum rseq_cs_flags
+  {
+    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
+      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
+    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
+      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
+    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
+      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
+  };
+
+/* struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
+   contained within a single cache-line. It is usually declared as
+   link-time constant data.  */
+struct rseq_cs
+  {
+    /* Version of this structure.  */
+    uint32_t version;
+    /* enum rseq_cs_flags.  */
+    uint32_t flags;
+    uint64_t start_ip;
+    /* Offset from start_ip.  */
+    uint64_t post_commit_offset;
+    uint64_t abort_ip;
+} __attribute__((aligned(4 * sizeof(uint64_t))));
+
+/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
+   contained within a single cache-line.
+
+   A single struct rseq per thread is allowed.  */
+struct rseq
+  {
+    /* Restartable sequences cpu_id_start field. Updated by the
+       kernel. Read by user-space with single-copy atomicity
+       semantics. This field should only be read by the thread which
+       registered this data structure. Aligned on 32-bit. Always
+       contains a value in the range of possible CPUs, although the
+       value may not be the actual current CPU (e.g. if rseq is not
+       initialized). This CPU number value should always be compared
+       against the value of the cpu_id field before performing a rseq
+       commit or returning a value read from a data structure indexed
+       using the cpu_id_start value.  */
+    uint32_t cpu_id_start;
+    /* Restartable sequences cpu_id field. Updated by the kernel.
+       Read by user-space with single-copy atomicity semantics. This
+       field should only be read by the thread which registered this
+       data structure. Aligned on 32-bit. Values
+       RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
+       have a special semantic: the former means "rseq uninitialized",
+       and latter means "rseq initialization failed". This value is
+       meant to be read within rseq critical sections and compared
+       with the cpu_id_start value previously read, before performing
+       the commit instruction, or read and compared with the
+       cpu_id_start value before returning a value loaded from a data
+       structure indexed using the cpu_id_start value.  */
+    uint32_t cpu_id;
+    /* Restartable sequences rseq_cs field.
+
+       Contains NULL when no critical section is active for the current
+       thread, or holds a pointer to the currently active struct rseq_cs.
+
+       Updated by user-space, which sets the address of the currently
+       active rseq_cs at the beginning of assembly instruction sequence
+       block, and set to NULL by the kernel when it restarts an assembly
+       instruction sequence block, as well as when the kernel detects that
+       it is preempting or delivering a signal outside of the range
+       targeted by the rseq_cs. Also needs to be set to NULL by user-space
+       before reclaiming memory that contains the targeted struct rseq_cs.
+
+       Read and set by the kernel. Set by user-space with single-copy
+       atomicity semantics. This field should only be updated by the
+       thread which registered this data structure. Aligned on 64-bit.  */
+    union {
+      uint64_t ptr64;
+#ifdef __LP64__
+      uint64_t ptr;
+#else
+      struct {
+#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN)
+        uint32_t padding; /* Initialized to zero.  */
+        uint32_t ptr32;
+#else /* LITTLE */
+        uint32_t ptr32;
+        uint32_t padding; /* Initialized to zero.  */
+#endif /* ENDIAN */
+      } ptr;
+#endif
+    } rseq_cs;
+
+    /* Restartable sequences flags field.
+
+       This field should only be updated by the thread which
+       registered this data structure. Read by the kernel.
+       Mainly used for single-stepping through rseq critical sections
+       with debuggers.
+
+       - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
+           Inhibit instruction sequence block restart on preemption
+           for this thread.
+       - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
+           Inhibit instruction sequence block restart on signal
+           delivery for this thread.
+       - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
+           Inhibit instruction sequence block restart on migration for
+           this thread.  */
+    uint32_t flags;
+  } __attribute__((aligned(4 * sizeof(uint64_t))));
+
+#endif
+
+/* Ensure the compiler supports __attribute__ ((aligned)).  */
+_Static_assert (__alignof__ (struct rseq_cs) >= 4 * sizeof(uint64_t),
+                "alignment");
+_Static_assert (__alignof__ (struct rseq) >= 4 * sizeof(uint64_t),
+                "alignment");
+
+/* Allocations of struct rseq and struct rseq_cs on the heap need to
+   be aligned on 32 bytes. Therefore, use of malloc is discouraged
+   because it does not guarantee alignment. posix_memalign should be
+   used instead.  */
+
+extern __thread struct rseq __rseq_abi
+__attribute__ ((tls_model ("initial-exec")));
+
+#endif /* sys/rseq.h */
diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
new file mode 100644
index 0000000000..75f52d9788
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
@@ -0,0 +1,30 @@
+/* Restartable Sequences Linux x86 architecture header.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_RSEQ_H
+# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
+#endif
+
+/* RSEQ_SIG is a signature required before each abort handler code.
+
+   RSEQ_SIG is used with the following reserved undefined instructions, which
+   trap in user-space:
+
+   x86-32:    0f b9 3d 53 30 05 53      ud1    0x53053053,%edi
+   x86-64:    0f b9 3d 53 30 05 53      ud1    0x53053053(%rip),%edi  */
+
+#define RSEQ_SIG	0x53053053
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 1f2dbd1451..dfa3fe85ef 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2059,6 +2059,7 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 59da85a5d8..6ff082ee4e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2158,3 +2158,4 @@ GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 __rseq_abi T 0x20
-- 
2.17.1


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

* [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7)
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (4 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17) Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-27  9:13   ` Florian Weimer
  2020-03-26 15:56 ` [PATCH glibc 7/9] support record failure: allow use from constructor Mathieu Desnoyers
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers, Thomas Gleixner, Ben Maurer, Peter Zijlstra,
	Paul E. McKenney, Boqun Feng, Will Deacon, Paul Turner,
	linux-kernel, linux-api

When available, use the cpu_id field from __rseq_abi on Linux to
implement sched_getcpu(). Fall-back on the vgetcpu vDSO if unavailable.

Benchmarks:

x86-64: Intel E5-2630 v3@2.40GHz, 16-core, hyperthreading

glibc sched_getcpu():                     13.7 ns (baseline)
glibc sched_getcpu() using rseq:           2.5 ns (speedup:  5.5x)
inline load cpuid from __rseq_abi TLS:     0.8 ns (speedup: 17.1x)

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Maurer <bmaurer@fb.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Paul Turner <pjt@google.com>
CC: libc-alpha@sourceware.org
CC: linux-kernel@vger.kernel.org
CC: linux-api@vger.kernel.org
---
Changes since v1:
- rseq is only used if both __NR_rseq and RSEQ_SIG are defined.

Changes since v2:
- remove duplicated __rseq_abi extern declaration.

Changes since v3:
- update ChangeLog.

Changes since v4:
- Use atomic_load_relaxed to load the __rseq_abi.cpu_id field, a
  consequence of the fact that __rseq_abi is not volatile anymore.
- Include atomic.h which provides atomic_load_relaxed.

Changes since v5:
- Use __ASSUME_RSEQ to detect rseq availability.

Changes since v6:
- Remove use of __ASSUME_RSEQ.
---
 sysdeps/unix/sysv/linux/sched_getcpu.c | 27 ++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c
index c019cfb3cf..2269c4f2bd 100644
--- a/sysdeps/unix/sysv/linux/sched_getcpu.c
+++ b/sysdeps/unix/sysv/linux/sched_getcpu.c
@@ -18,10 +18,15 @@
 #include <errno.h>
 #include <sched.h>
 #include <sysdep.h>
+#include <atomic.h>
 #include <sysdep-vdso.h>
 
-int
-sched_getcpu (void)
+#ifdef HAVE_GETCPU_VSYSCALL
+# define HAVE_VSYSCALL
+#endif
+
+static int
+vsyscall_sched_getcpu (void)
 {
   unsigned int cpu;
   int r = -1;
@@ -32,3 +37,21 @@ sched_getcpu (void)
 #endif
   return r == -1 ? r : cpu;
 }
+
+#include <sys/rseq.h>
+
+#ifdef RSEQ_SIG
+int
+sched_getcpu (void)
+{
+  int cpu_id = atomic_load_relaxed (&__rseq_abi.cpu_id);
+
+  return cpu_id >= 0 ? cpu_id : vsyscall_sched_getcpu ();
+}
+#else
+int
+sched_getcpu (void)
+{
+  return vsyscall_sched_getcpu ();
+}
+#endif
-- 
2.17.1


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

* [PATCH glibc 7/9] support record failure: allow use from constructor
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (5 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7) Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-27 16:58   ` Florian Weimer
  2020-03-26 15:56 ` [PATCH glibc 8/9] support: implement xpthread key create/delete (v4) Mathieu Desnoyers
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers

Expose support_record_failure_init () so constructors can explicitly
initialize the record failure API.

This is preferred to lazy initialization at first use, because
lazy initialization does not cover use in constructors within
forked children processes (forked from parent constructor).

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: libc-alpha@sourceware.org
---
 support/check.h                  |  4 ++++
 support/support_record_failure.c | 18 +++++++++++++-----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/support/check.h b/support/check.h
index 77d1d1e14d..902cea6878 100644
--- a/support/check.h
+++ b/support/check.h
@@ -88,6 +88,10 @@ void support_test_verify_exit_impl (int status, const char *file, int line,
    does not support reporting failures from a DSO.  */
 void support_record_failure (void);
 
+/* Initialize record failure.  Calling this is only needed when
+   recording failures from constructors.  */
+void support_record_failure_init (void);
+
 /* Static assertion, under a common name for both C++ and C11.  */
 #ifdef __cplusplus
 # define support_static_assert static_assert
diff --git a/support/support_record_failure.c b/support/support_record_failure.c
index f766c06236..957572f487 100644
--- a/support/support_record_failure.c
+++ b/support/support_record_failure.c
@@ -32,8 +32,12 @@
    zero, the failure of a test can be detected.
 
    The init constructor function below puts *state on a shared
-   annonymous mapping, so that failure reports from subprocesses
-   propagate to the parent process.  */
+   anonymous mapping, so that failure reports from subprocesses
+   propagate to the parent process.
+
+   support_record_failure_init is exposed so it can be called explicitly
+   in case this API needs to be used from a constructor.  */
+
 struct test_failures
 {
   unsigned int counter;
@@ -41,10 +45,14 @@ struct test_failures
 };
 static struct test_failures *state;
 
-static __attribute__ ((constructor)) void
-init (void)
+__attribute__ ((constructor)) void
+support_record_failure_init (void)
 {
-  void *ptr = mmap (NULL, sizeof (*state), PROT_READ | PROT_WRITE,
+  void *ptr;
+
+  if (state != NULL)
+    return;
+  ptr = mmap (NULL, sizeof (*state), PROT_READ | PROT_WRITE,
                     MAP_ANONYMOUS | MAP_SHARED, -1, 0);
   if (ptr == MAP_FAILED)
     {
-- 
2.17.1


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

* [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (6 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 7/9] support record failure: allow use from constructor Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-27  9:17   ` Florian Weimer
  2020-03-26 15:56 ` [PATCH glibc 9/9] rseq registration tests (v9) Mathieu Desnoyers
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers

Expose xpthread_key_create () and xpthread_key_delete () wrappers
for tests.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: libc-alpha@sourceware.org
---
Changes since v1:
- Update ChangeLog.
- Wrap long line in xpthread_key_create.

Changes since v2:
- Rebase on glibc 2.30.

Changes since v3:
- Update copyright range to include 2020.
---
 support/Makefile              |  2 ++
 support/xpthread_key_create.c | 25 +++++++++++++++++++++++++
 support/xpthread_key_delete.c | 24 ++++++++++++++++++++++++
 support/xthread.h             |  2 ++
 4 files changed, 53 insertions(+)
 create mode 100644 support/xpthread_key_create.c
 create mode 100644 support/xpthread_key_delete.c

diff --git a/support/Makefile b/support/Makefile
index 6e38b87ebe..4498192a0a 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -130,6 +130,8 @@ libsupport-routines = \
   xpthread_create \
   xpthread_detach \
   xpthread_join \
+  xpthread_key_create \
+  xpthread_key_delete \
   xpthread_mutex_consistent \
   xpthread_mutex_destroy \
   xpthread_mutex_init \
diff --git a/support/xpthread_key_create.c b/support/xpthread_key_create.c
new file mode 100644
index 0000000000..1988dee138
--- /dev/null
+++ b/support/xpthread_key_create.c
@@ -0,0 +1,25 @@
+/* pthread_key_create with error checking.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/xthread.h>
+
+void
+xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *))
+{
+  xpthread_check_return ("pthread_key_create",
+                         pthread_key_create (key, destr_function));
+}
diff --git a/support/xpthread_key_delete.c b/support/xpthread_key_delete.c
new file mode 100644
index 0000000000..99144512d4
--- /dev/null
+++ b/support/xpthread_key_delete.c
@@ -0,0 +1,24 @@
+/* pthread_key_delete with error checking.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/xthread.h>
+
+void
+xpthread_key_delete (pthread_key_t key)
+{
+  xpthread_check_return ("pthread_key_delete", pthread_key_delete (key));
+}
diff --git a/support/xthread.h b/support/xthread.h
index d350d1506d..2a519874bf 100644
--- a/support/xthread.h
+++ b/support/xthread.h
@@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
 void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
 void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
 void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
+void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
+void xpthread_key_delete (pthread_key_t key);
 
 __END_DECLS
 
-- 
2.17.1


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

* [PATCH glibc 9/9] rseq registration tests (v9)
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (7 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 8/9] support: implement xpthread key create/delete (v4) Mathieu Desnoyers
@ 2020-03-26 15:56 ` Mathieu Desnoyers
  2020-04-27 16:55   ` Florian Weimer
  2020-04-15 20:45 ` [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
  2020-04-22 16:27 ` Carlos O'Donell
  10 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-03-26 15:56 UTC (permalink / raw)
  To: Carlos O'Donell
  Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha,
	Mathieu Desnoyers, Thomas Gleixner, Ben Maurer, Peter Zijlstra,
	Paul E. McKenney, Boqun Feng, Will Deacon, Paul Turner

These tests validate that rseq is registered from various execution
contexts (main thread, constructor, destructor, other threads, other
threads created from constructor and destructor, forked process
(without exec), pthread_atfork handlers, pthread setspecific
destructors, C++ thread and process destructors, signal handlers,
atexit handlers).

tst-rseq.c only links against libc.so, testing registration of rseq in
a non-multithreaded environment.

tst-rseq-nptl.c also links against libpthread.so, testing registration
of rseq in a multithreaded environment.

See the Linux kernel selftests for extensive rseq stress-tests.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Joseph Myers <joseph@codesourcery.com>
CC: Szabolcs Nagy <szabolcs.nagy@arm.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Maurer <bmaurer@fb.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Paul Turner <pjt@google.com>
CC: libc-alpha@sourceware.org
---
Changes since v1:
- Rename tst-rseq.c to tst-rseq-nptl.c.
- Introduce tst-rseq.c testing rseq registration in a non-multithreaded
  environment.

Chances since v2:
- Update file headers.
- use xpthread key create/delete.
- remove set stacksize.
- Tests depend on both __NR_rseq and RSEQ_SIG being defined.

Changes since v3:
- Update ChangeLog.

Changes since v4:
- Remove volatile from sys_rseq() rseq_abi parameter.
- Use atomic_load_relaxed to load __rseq_abi.cpu_id, consequence of the
  fact that __rseq_abi is not volatile anymore.
- Include atomic.h from tst-rseq.c for use of atomic_load_relaxed.
  Move tst-rseq.c to internal tests within Makefile due to its use of
  atomic.h.
- Test __rseq_handled initialization by glibc.

Changes since v5:
- Rebase on glibc 2.30.

Changes since v6:
- Remove __rseq_handled.

Changes since v7:
- Update copyright range to include 2020.
- Use __ASSUME_RSEQ to detect rseq availability.

Changes since v8:
- Remove use of __ASSUME_RSEQ.
---
 sysdeps/unix/sysv/linux/Makefile        |   6 +-
 sysdeps/unix/sysv/linux/tst-rseq-nptl.c | 347 ++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/tst-rseq.c      | 108 ++++++++
 3 files changed, 459 insertions(+), 2 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 6c6f669d21..b8f13e6d70 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -100,7 +100,9 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
 	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
 	 tst-tgkill
-tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
+
+tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc \
+		  tst-ofdlocks-compat tst-rseq
 
 CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables
 
@@ -303,5 +305,5 @@ ifeq ($(subdir),nptl)
 tests += tst-align-clone tst-getpid1 \
 	tst-thread-affinity-pthread tst-thread-affinity-pthread2 \
 	tst-thread-affinity-sched
-tests-internal += tst-setgetname
+tests-internal += tst-setgetname tst-rseq-nptl
 endif
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
new file mode 100644
index 0000000000..0af2589c14
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
@@ -0,0 +1,347 @@
+/* Restartable Sequences NPTL test.
+
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+/* These tests validate that rseq is registered from various execution
+   contexts (main thread, constructor, destructor, other threads, other
+   threads created from constructor and destructor, forked process
+   (without exec), pthread_atfork handlers, pthread setspecific
+   destructors, C++ thread and process destructors, signal handlers,
+   atexit handlers).
+
+   See the Linux kernel selftests for extensive rseq stress-tests.  */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xthread.h>
+#include <sys/rseq.h>
+
+#ifdef RSEQ_SIG
+#include <pthread.h>
+#include <syscall.h>
+#include <stdlib.h>
+#include <error.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <atomic.h>
+
+static pthread_key_t rseq_test_key;
+
+static int
+rseq_thread_registered (void)
+{
+  return (int32_t) atomic_load_relaxed (&__rseq_abi.cpu_id) >= 0;
+}
+
+static int
+do_rseq_main_test (void)
+{
+  if (raise (SIGUSR1))
+    FAIL_EXIT1 ("error raising signal");
+  if (pthread_setspecific (rseq_test_key, (void *) 1l))
+    FAIL_EXIT1 ("error in pthread_setspecific");
+  if (!rseq_thread_registered ())
+    {
+      FAIL_RET ("rseq not registered in main thread");
+    }
+  return 0;
+}
+
+static void
+cancel_routine (void *arg)
+{
+  if (!rseq_thread_registered ())
+    {
+      printf ("rseq not registered in cancel routine\n");
+      support_record_failure ();
+    }
+}
+
+static int cancel_thread_ready;
+
+static void
+test_cancel_thread (void)
+{
+  pthread_cleanup_push (cancel_routine, NULL);
+  atomic_store_release (&cancel_thread_ready, 1);
+  for (;;)
+    usleep (100);
+  pthread_cleanup_pop (0);
+}
+
+static void *
+thread_function (void * arg)
+{
+  int i = (int) (intptr_t) arg;
+
+  if (raise (SIGUSR1))
+    FAIL_EXIT1 ("error raising signal");
+  if (i == 0)
+    test_cancel_thread ();
+  if (pthread_setspecific (rseq_test_key, (void *) 1l))
+    FAIL_EXIT1 ("error in pthread_setspecific");
+  return rseq_thread_registered () ? NULL : (void *) 1l;
+}
+
+static void
+sighandler (int sig)
+{
+  if (!rseq_thread_registered ())
+    {
+      printf ("rseq not registered in signal handler\n");
+      support_record_failure ();
+    }
+}
+
+static void
+setup_signals (void)
+{
+  struct sigaction sa;
+
+  sigemptyset (&sa.sa_mask);
+  sigaddset (&sa.sa_mask, SIGUSR1);
+  sa.sa_flags = 0;
+  sa.sa_handler = sighandler;
+  if (sigaction (SIGUSR1, &sa, NULL) != 0)
+    {
+      FAIL_EXIT1 ("sigaction failure: %s", strerror (errno));
+    }
+}
+
+#define N 7
+static const int t[N] = { 1, 2, 6, 5, 4, 3, 50 };
+
+static int
+do_rseq_threads_test (int nr_threads)
+{
+  pthread_t th[nr_threads];
+  int i;
+  int result = 0;
+
+  cancel_thread_ready = 0;
+  for (i = 0; i < nr_threads; ++i)
+    if (pthread_create (&th[i], NULL, thread_function,
+                        (void *) (intptr_t) i) != 0)
+      {
+        FAIL_EXIT1 ("creation of thread %d failed", i);
+      }
+
+  while (!atomic_load_acquire (&cancel_thread_ready))
+    usleep (100);
+
+  if (pthread_cancel (th[0]))
+    FAIL_EXIT1 ("error in pthread_cancel");
+
+  for (i = 0; i < nr_threads; ++i)
+    {
+      void *v;
+      if (pthread_join (th[i], &v) != 0)
+        {
+          printf ("join of thread %d failed\n", i);
+          result = 1;
+        }
+      else if (i != 0 && v != NULL)
+        {
+          printf ("join %d successful, but child failed\n", i);
+          result = 1;
+        }
+      else if (i == 0 && v == NULL)
+        {
+          printf ("join %d successful, child did not fail as expected\n", i);
+          result = 1;
+        }
+    }
+  return result;
+}
+
+static int
+sys_rseq (struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
+{
+  return syscall (__NR_rseq, rseq_abi, rseq_len, flags, sig);
+}
+
+static int
+rseq_available (void)
+{
+  int rc;
+
+  rc = sys_rseq (NULL, 0, 0, 0);
+  if (rc != -1)
+    FAIL_EXIT1 ("Unexpected rseq return value %d", rc);
+  switch (errno)
+    {
+    case ENOSYS:
+      return 0;
+    case EINVAL:
+      return 1;
+    default:
+      FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno));
+    }
+}
+
+static int
+do_rseq_fork_test (void)
+{
+  int status;
+  pid_t pid, retpid;
+
+  pid = fork ();
+  switch (pid)
+    {
+      case 0:
+        exit (do_rseq_main_test ());
+      case -1:
+        FAIL_EXIT1 ("Unexpected fork error %s", strerror (errno));
+    }
+  retpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+  if (retpid != pid)
+    {
+      FAIL_EXIT1 ("waitpid returned %ld, expected %ld",
+                  (long int) retpid, (long int) pid);
+    }
+  if (WEXITSTATUS (status))
+    {
+      printf ("rseq not registered in child\n");
+      return 1;
+    }
+  return 0;
+}
+
+static int
+do_rseq_test (void)
+{
+  int i, result = 0;
+
+  if (!rseq_available ())
+    {
+      FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
+    }
+  setup_signals ();
+  if (raise (SIGUSR1))
+    FAIL_EXIT1 ("error raising signal");
+  if (do_rseq_main_test ())
+    result = 1;
+  for (i = 0; i < N; i++)
+    {
+      if (do_rseq_threads_test (t[i]))
+        result = 1;
+    }
+  if (do_rseq_fork_test ())
+    result = 1;
+  return result;
+}
+
+static void
+atfork_prepare (void)
+{
+  if (!rseq_thread_registered ())
+    {
+      printf ("rseq not registered in pthread atfork prepare\n");
+      support_record_failure ();
+    }
+}
+
+static void
+atfork_parent (void)
+{
+  if (!rseq_thread_registered ())
+    {
+      printf ("rseq not registered in pthread atfork parent\n");
+      support_record_failure ();
+    }
+}
+
+static void
+atfork_child (void)
+{
+  if (!rseq_thread_registered ())
+    {
+      printf ("rseq not registered in pthread atfork child\n");
+      support_record_failure ();
+    }
+}
+
+static void
+rseq_key_destructor (void *arg)
+{
+  /* Cannot use deferred failure reporting after main () returns.  */
+  if (!rseq_thread_registered ())
+    FAIL_EXIT1 ("rseq not registered in pthread key destructor");
+}
+
+static void
+atexit_handler (void)
+{
+  /* Cannot use deferred failure reporting after main () returns.  */
+  if (!rseq_thread_registered ())
+    FAIL_EXIT1 ("rseq not registered in atexit handler");
+}
+
+static void __attribute__ ((constructor))
+do_rseq_constructor_test (void)
+{
+  support_record_failure_init ();
+  if (atexit (atexit_handler))
+    FAIL_EXIT1 ("error calling atexit");
+  xpthread_key_create (&rseq_test_key, rseq_key_destructor);
+  if (pthread_atfork (atfork_prepare, atfork_parent, atfork_child))
+    FAIL_EXIT1 ("error calling pthread_atfork");
+  if (do_rseq_test ())
+    FAIL_EXIT1 ("rseq not registered within constructor");
+}
+
+static void __attribute__ ((destructor))
+do_rseq_destructor_test (void)
+{
+  /* Cannot use deferred failure reporting after main () returns.  */
+  if (do_rseq_test ())
+    FAIL_EXIT1 ("rseq not registered within destructor");
+  xpthread_key_delete (rseq_test_key);
+}
+
+/* Test C++ destructor called at thread and process exit.  */
+void
+__call_tls_dtors (void)
+{
+  /* Cannot use deferred failure reporting after main () returns.  */
+  if (!rseq_thread_registered ())
+    FAIL_EXIT1 ("rseq not registered in C++ thread/process exit destructor");
+}
+#else
+static int
+do_rseq_test (void)
+{
+#ifndef RSEQ_SIG
+  FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
+#endif
+  return 0;
+}
+#endif
+
+static int
+do_test (void)
+{
+  return do_rseq_test ();
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
new file mode 100644
index 0000000000..18bc9d4e21
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
@@ -0,0 +1,108 @@
+/* Restartable Sequences single-threaded tests.
+
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+/* These tests validate that rseq is registered from main in an executable
+   not linked against libpthread.  */
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <sys/rseq.h>
+
+#ifdef RSEQ_SIG
+#include <syscall.h>
+#include <stdlib.h>
+#include <error.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <atomic.h>
+
+static int
+rseq_thread_registered (void)
+{
+  return (int32_t) atomic_load_relaxed (&__rseq_abi.cpu_id) >= 0;
+}
+
+static int
+do_rseq_main_test (void)
+{
+  if (!rseq_thread_registered ())
+    {
+      FAIL_RET ("rseq not registered in main thread");
+    }
+  return 0;
+}
+
+static int
+sys_rseq (struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
+{
+  return syscall (__NR_rseq, rseq_abi, rseq_len, flags, sig);
+}
+
+static int
+rseq_available (void)
+{
+  int rc;
+
+  rc = sys_rseq (NULL, 0, 0, 0);
+  if (rc != -1)
+    FAIL_EXIT1 ("Unexpected rseq return value %d", rc);
+  switch (errno)
+    {
+    case ENOSYS:
+      return 0;
+    case EINVAL:
+      return 1;
+    default:
+      FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno));
+    }
+}
+
+static int
+do_rseq_test (void)
+{
+  int result = 0;
+
+  if (!rseq_available ())
+    {
+      FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
+    }
+  if (do_rseq_main_test ())
+    result = 1;
+  return result;
+}
+#else
+static int
+do_rseq_test (void)
+{
+#ifndef RSEQ_SIG
+  FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
+#endif
+  return 0;
+}
+#endif
+
+static int
+do_test (void)
+{
+  return do_rseq_test ();
+}
+
+#include <support/test-driver.c>
-- 
2.17.1


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

* Re: [PATCH glibc 0/9] Restartable Sequences enablement
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (8 preceding siblings ...)
  2020-03-26 15:56 ` [PATCH glibc 9/9] rseq registration tests (v9) Mathieu Desnoyers
@ 2020-04-15 20:45 ` Mathieu Desnoyers
  2020-04-22 16:27 ` Carlos O'Donell
  10 siblings, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-15 20:45 UTC (permalink / raw)
  To: carlos; +Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

----- On Mar 26, 2020, at 11:56 AM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:

> Hi,
> 
> Please find the rseq-enablement patchset for comments in this series.
> 
> This patch series is based on glibc master branch at commit
> 1fabdb9908 x86: Remove ARCH_CET_LEGACY_BITMAP [BZ #25397]
> 
> Since the last post:
> 
> - Move elf/elf_machine_sym_no_match.h to sysdeps/generic (additional
>  patch).
> - Move NEWS entry under 2.32.
> - Move new __rseq_abi symbol to GLIBC_2.32.
> 
> Please consider for merging into glibc.

Hi,

Is there any feedback on the proposed patches ?

Thanks,

Mathieu

> 
> Mathieu
> 
> 
> Florian Weimer (3):
>  Introduce <elf_machine_sym_no_match.h>
>  Implement __libc_early_init
>  nptl: Start new threads with all signals blocked [BZ #25098]
> 
> Mathieu Desnoyers (6):
>  Move elf/elf_machine_sym_no_match.h to sysdeps/generic
>  glibc: Perform rseq(2) registration at C startup and thread creation
>    (v17)
>  glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7)
>  support record failure: allow use from constructor
>  support: implement xpthread key create/delete (v4)
>  rseq registration tests (v9)
> 
> NEWS                                          |  12 +-
> csu/init-first.c                              |   4 -
> csu/libc-start.c                              |   5 +
> elf/Makefile                                  |   5 +-
> elf/Versions                                  |   1 +
> elf/dl-call-libc-early-init.c                 |  41 +++
> elf/dl-load.c                                 |   9 +
> elf/dl-lookup-direct.c                        | 116 ++++++
> elf/dl-lookup.c                               |  10 +-
> elf/dl-open.c                                 |  24 ++
> elf/libc-early-init.h                         |  35 ++
> elf/libc_early_init.c                         |  30 ++
> elf/rtld.c                                    |   4 +
> manual/threads.texi                           |  30 +-
> misc/rseq-internal.h                          |  33 ++
> nptl/descr.h                                  |  10 +-
> nptl/pthread_create.c                         |  56 ++-
> support/Makefile                              |   2 +
> support/check.h                               |   4 +
> support/support_record_failure.c              |  18 +-
> support/xpthread_key_create.c                 |  25 ++
> support/xpthread_key_delete.c                 |  24 ++
> support/xthread.h                             |   2 +
> sysdeps/generic/elf_machine_sym_no_match.h    |  34 ++
> sysdeps/generic/ldsodefs.h                    |  17 +
> sysdeps/mach/hurd/i386/init-first.c           |   4 -
> sysdeps/mips/dl-machine.h                     |  15 -
> sysdeps/mips/elf_machine_sym_no_match.h       |  43 +++
> sysdeps/unix/sysv/linux/Makefile              |  11 +-
> sysdeps/unix/sysv/linux/Versions              |   3 +
> sysdeps/unix/sysv/linux/aarch64/bits/rseq.h   |  43 +++
> sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
> sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
> sysdeps/unix/sysv/linux/arm/be/libc.abilist   |   1 +
> sysdeps/unix/sysv/linux/arm/bits/rseq.h       |  83 +++++
> sysdeps/unix/sysv/linux/arm/le/libc.abilist   |   1 +
> sysdeps/unix/sysv/linux/bits/rseq.h           |  29 ++
> sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
> sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
> sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
> sysdeps/unix/sysv/linux/ia64/libc.abilist     |   1 +
> .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
> .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
> .../sysv/linux/microblaze/be/libc.abilist     |   1 +
> .../sysv/linux/microblaze/le/libc.abilist     |   1 +
> sysdeps/unix/sysv/linux/mips/bits/rseq.h      |  62 ++++
> .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
> .../sysv/linux/mips/mips32/nofpu/libc.abilist |   1 +
> .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
> .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
> sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
> sysdeps/unix/sysv/linux/powerpc/bits/rseq.h   |  37 ++
> .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
> .../powerpc/powerpc32/nofpu/libc.abilist      |   1 +
> .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
> .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
> .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
> sysdeps/unix/sysv/linux/rseq-internal.h       |  73 ++++
> sysdeps/unix/sysv/linux/rseq-sym.c            |  25 ++
> sysdeps/unix/sysv/linux/s390/bits/rseq.h      |  37 ++
> .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
> .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
> sysdeps/unix/sysv/linux/sched_getcpu.c        |  27 +-
> sysdeps/unix/sysv/linux/sh/be/libc.abilist    |   1 +
> sysdeps/unix/sysv/linux/sh/le/libc.abilist    |   1 +
> .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
> .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
> sysdeps/unix/sysv/linux/sys/rseq.h            | 186 ++++++++++
> sysdeps/unix/sysv/linux/tst-rseq-nptl.c       | 347 ++++++++++++++++++
> sysdeps/unix/sysv/linux/tst-rseq.c            | 108 ++++++
> sysdeps/unix/sysv/linux/x86/bits/rseq.h       |  30 ++
> .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
> .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
> 73 files changed, 1674 insertions(+), 70 deletions(-)
> create mode 100644 elf/dl-call-libc-early-init.c
> create mode 100644 elf/dl-lookup-direct.c
> create mode 100644 elf/libc-early-init.h
> create mode 100644 elf/libc_early_init.c
> create mode 100644 misc/rseq-internal.h
> create mode 100644 support/xpthread_key_create.c
> create mode 100644 support/xpthread_key_delete.c
> create mode 100644 sysdeps/generic/elf_machine_sym_no_match.h
> create mode 100644 sysdeps/mips/elf_machine_sym_no_match.h
> create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h
> create mode 100644 sysdeps/unix/sysv/linux/rseq-sym.c
> create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h
> create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c
> create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c
> create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h
> 
> --
> 2.17.1

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 0/9] Restartable Sequences enablement
  2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
                   ` (9 preceding siblings ...)
  2020-04-15 20:45 ` [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
@ 2020-04-22 16:27 ` Carlos O'Donell
  10 siblings, 0 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-22 16:27 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
> Hi,
> 
> Please find the rseq-enablement patchset for comments in this series.
> 
> This patch series is based on glibc master branch at commit
> 1fabdb9908 x86: Remove ARCH_CET_LEGACY_BITMAP [BZ #25397]
> 
> Since the last post:
> 
> - Move elf/elf_machine_sym_no_match.h to sysdeps/generic (additional
>   patch).
> - Move NEWS entry under 2.32.
> - Move new __rseq_abi symbol to GLIBC_2.32.
> 
> Please consider for merging into glibc.
> 
> Mathieu
> 
> 
> Florian Weimer (3):
>   Introduce <elf_machine_sym_no_match.h>
>   Implement __libc_early_init
>   nptl: Start new threads with all signals blocked [BZ #25098]

I'm going to focus on these patches and review them first.

I would like to see these pushed first, since they are overall
good refactoring for the dynamic loader.

-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h>
  2020-03-26 15:56 ` [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h> Mathieu Desnoyers
@ 2020-04-22 16:27   ` Carlos O'Donell
  2020-04-24 18:20     ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-22 16:27 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
> From: Florian Weimer <fweimer@redhat.com>
> 
> MIPS needs to ignore certain existing symbols during symbol lookup.
> The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
> inline function, within its own header, with a sysdeps override for
> MIPS.  This allows re-use of the function from another file (without
> having to include <dl-machine.h> or providing the default definition
> for ELF_MACHINE_SYM_NO_MATCH).
> 
> Built with build-many-glibcs.py, with manual verification that
> sysdeps/mips/elf_machine_sym_no_match.h is picked up on MIPS.  Tested
> on aarch64-linux-gnu, i686-linux-gnu, powerpc64-linux-gnu,
> s390x-linux-gnu, x86_64-linux-gnu.

The refactoring from a macro to a static inline function looks good to
me. There isn't anything that changes.

This patch needs squashing with the second patch in the series.

Technically speaking it's ready to be committed, but I want to see the
squashed patch before ACK'ing it.

> ---
>  elf/dl-lookup.c                         | 10 ++----
>  elf/elf_machine_sym_no_match.h          | 34 +++++++++++++++++++
>  sysdeps/mips/dl-machine.h               | 15 ---------
>  sysdeps/mips/elf_machine_sym_no_match.h | 43 +++++++++++++++++++++++++
>  4 files changed, 79 insertions(+), 23 deletions(-)
>  create mode 100644 elf/elf_machine_sym_no_match.h
>  create mode 100644 sysdeps/mips/elf_machine_sym_no_match.h
> 
> diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
> index 12a229f06c..807f3ea9b6 100644
> --- a/elf/dl-lookup.c
> +++ b/elf/dl-lookup.c
> @@ -28,18 +28,12 @@
>  #include <libc-lock.h>
>  #include <tls.h>
>  #include <atomic.h>
> +#include <elf_machine_sym_no_match.h>

OK.

>  
>  #include <assert.h>
>  
> -/* Return nonzero if check_match should consider SYM to fail to match a
> -   symbol reference for some machine-specific reason.  */
> -#ifndef ELF_MACHINE_SYM_NO_MATCH
> -# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
> -#endif
> -
>  #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
>  
> -
>  struct sym_val
>    {
>      const ElfW(Sym) *s;
> @@ -78,7 +72,7 @@ check_match (const char *const undef_name,
>    if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
>  			 && sym->st_shndx != SHN_ABS
>  			 && stt != STT_TLS)
> -			|| ELF_MACHINE_SYM_NO_MATCH (sym)
> +			|| elf_machine_sym_no_match (sym)

OK. You are my hero every time you kill a macro and make an static inline function.

>  			|| (type_class & (sym->st_shndx == SHN_UNDEF))))
>      return NULL;
>  
> diff --git a/elf/elf_machine_sym_no_match.h b/elf/elf_machine_sym_no_match.h
> new file mode 100644
> index 0000000000..6e299e5ee8
> --- /dev/null
> +++ b/elf/elf_machine_sym_no_match.h
> @@ -0,0 +1,34 @@
> +/* Function to ignore certain symbol matches for machine-specific reasons.
> +   Copyright (C) 2019 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/>.  */
> +
> +#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
> +#define _ELF_MACHINE_SYM_NO_MATCH_H
> +
> +#include <link.h>
> +#include <stdbool.h>
> +
> +/* This can be customized to ignore certain symbols during lookup in
> +   case there are machine-specific rules to disregard some
> +   symbols.  */
> +static inline bool
> +elf_machine_sym_no_match (const ElfW(Sym) *sym)
> +{
> +  return false;
> +}


OK.

> +
> +#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
> diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
> index 06021ea9ab..e3b11a4f21 100644
> --- a/sysdeps/mips/dl-machine.h
> +++ b/sysdeps/mips/dl-machine.h
> @@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
>    return value;
>  }
>  
> -/* The semantics of zero/non-zero values of undefined symbols differs
> -   depending on whether the non-PIC ABI is in use.  Under the non-PIC
> -   ABI, a non-zero value indicates that there is an address reference
> -   to the symbol and thus it must always be resolved (except when
> -   resolving a jump slot relocation) to the PLT entry whose address is
> -   provided as the symbol's value; a zero value indicates that this
> -   canonical-address behaviour is not required.  Yet under the classic
> -   MIPS psABI, a zero value indicates that there is an address
> -   reference to the function and the dynamic linker must resolve the
> -   symbol immediately upon loading.  To avoid conflict, symbols for
> -   which the dynamic linker must assume the non-PIC ABI semantics are
> -   marked with the STO_MIPS_PLT flag.  */
> -#define ELF_MACHINE_SYM_NO_MATCH(sym) \
> -  ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
> -

OK.

>  #endif /* !dl_machine_h */
>  
>  #ifdef RESOLVE_MAP
> diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h
> new file mode 100644
> index 0000000000..f2be74caaf
> --- /dev/null
> +++ b/sysdeps/mips/elf_machine_sym_no_match.h
> @@ -0,0 +1,43 @@
> +/* MIPS-specific handling of undefined symbols.
> +   Copyright (C) 2008-2019 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/>.  */
> +
> +#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
> +#define _ELF_MACHINE_SYM_NO_MATCH_H
> +
> +#include <link.h>
> +#include <stdbool.h>
> +
> +/* The semantics of zero/non-zero values of undefined symbols differs
> +   depending on whether the non-PIC ABI is in use.  Under the non-PIC
> +   ABI, a non-zero value indicates that there is an address reference
> +   to the symbol and thus it must always be resolved (except when
> +   resolving a jump slot relocation) to the PLT entry whose address is
> +   provided as the symbol's value; a zero value indicates that this
> +   canonical-address behaviour is not required.  Yet under the classic
> +   MIPS psABI, a zero value indicates that there is an address
> +   reference to the function and the dynamic linker must resolve the
> +   symbol immediately upon loading.  To avoid conflict, symbols for
> +   which the dynamic linker must assume the non-PIC ABI semantics are
> +   marked with the STO_MIPS_PLT flag.  */
> +static inline bool
> +elf_machine_sym_no_match (const ElfW(Sym) *sym)
> +{
> +  return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT);
> +}
> +
> +#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
> 

OK. Conditional matches original code.

-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic
  2020-03-26 15:56 ` [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic Mathieu Desnoyers
@ 2020-04-22 16:27   ` Carlos O'Donell
  0 siblings, 0 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-22 16:27 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
> sysdeps/generic/elf_machine_sym_no_match.h matches
> sysdeps/mips/elf_machine_sym_no_match.h better.
> 
> Suggested-by: H.J. Lu <hjl.tools@gmail.com>
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> CC: Florian Weimer <fweimer@redhat.com>
> ---
>  {elf => sysdeps/generic}/elf_machine_sym_no_match.h | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename {elf => sysdeps/generic}/elf_machine_sym_no_match.h (100%)
> 
> diff --git a/elf/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h
> similarity index 100%
> rename from elf/elf_machine_sym_no_match.h
> rename to sysdeps/generic/elf_machine_sym_no_match.h
> 

Moving the file to sysdeps/generic is fine, it has
nothing to do with a machine, and it does cleanup
the generic elf/ directory a bit. It also allows
sysdep/ override to be a bit clearer in intent.

This needs to be squashed with the original commit
which creates elf_machine_sym_no_match.h.

This patch incorporates HJs feedback.

This patch on its own is not OK.

-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-03-26 15:56 ` [PATCH glibc 3/9] Implement __libc_early_init Mathieu Desnoyers
@ 2020-04-22 16:28   ` Carlos O'Donell
  2020-04-24 18:22     ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-22 16:28 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Mathieu Desnoyers, Joseph Myers, Szabolcs Nagy, libc-alpha

On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
> From: Florian Weimer <fweimer@redhat.com>
> 
> This function is defined in libc.so, and the dynamic loader calls
> right after relocation has been finished, before any ELF constructors
> or the preinit function is invoked.  It is also used in the static
> build for initializing parts of the static libc.
> 
> To locate __libc_early_init, a direct symbol lookup function is used,
> _dl_lookup_direct.  It does not search the entire symbol scope and
> consults merely a single link map.  This function could also be used
> to implement lookups in the vDSO (as an optimization).
> 
> A per-namespace variable (libc_map) is added for locating libc.so,
> to avoid repeated traversals of the search scope.  It is similar to
> GL(dl_initfirst).  An alternative would have been to thread a context
> argument from _dl_open down to _dl_map_object_from_fd (where libc.so
> is identified).  This could have avoided the global variable, but
> the change would be larger as a result.  It would not have been
> possible to use this to replace GL(dl_initfirst) because that global
> variable is used to pass the function pointer past the stack switch
> from dl_main to the main program.  Replacing that requires adding
> a new argument to _dl_init, which in turn needs changes to the
> architecture-specific libc.so startup code written in assembler.

Good rationale.

> __libc_early_init should not be used to replace _dl_var_init (as
> it exists today on some architectures).  Instead, _dl_lookup_direct
> should be used to look up a new variable symbol in libc.so, and
> that should then be initialized from the dynamic loader, immediately
> after the object has been loaded in _dl_map_object_from_fd (before
> relocation is run).  This way, more IFUNC resolvers which depend on
> these variables will work.
> 

I haven't seen any other review of this patch, so I have no other
comments to integrate.

Outstanding review items for Florian:

Please clarify or remove the comment related to libc_already_loaded.

I want to make sure I have a bullet-proof understanding of the scenarios
under which this might fail.

> This version was tested on x86_64-linux-gnu.
> ---
>  csu/init-first.c                    |   4 -
>  csu/libc-start.c                    |   5 ++
>  elf/Makefile                        |   5 +-
>  elf/Versions                        |   1 +
>  elf/dl-call-libc-early-init.c       |  41 ++++++++++
>  elf/dl-load.c                       |   9 +++
>  elf/dl-lookup-direct.c              | 116 ++++++++++++++++++++++++++++
>  elf/dl-open.c                       |  24 ++++++
>  elf/libc-early-init.h               |  35 +++++++++
>  elf/libc_early_init.c               |  27 +++++++
>  elf/rtld.c                          |   4 +
>  sysdeps/generic/ldsodefs.h          |  17 ++++
>  sysdeps/mach/hurd/i386/init-first.c |   4 -
>  13 files changed, 282 insertions(+), 10 deletions(-)
>  create mode 100644 elf/dl-call-libc-early-init.c
>  create mode 100644 elf/dl-lookup-direct.c
>  create mode 100644 elf/libc-early-init.h
>  create mode 100644 elf/libc_early_init.c
> 
> diff --git a/csu/init-first.c b/csu/init-first.c
> index 264e6f348d..d214af7116 100644
> --- a/csu/init-first.c
> +++ b/csu/init-first.c
> @@ -16,7 +16,6 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <ctype.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <fcntl.h>
> @@ -75,9 +74,6 @@ _init_first (int argc, char **argv, char **envp)
>  
>    __init_misc (argc, argv, envp);
>  
> -  /* Initialize ctype data.  */
> -  __ctype_init ();

OK.

> -
>  #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>    __libc_global_ctors ();
>  #endif
> diff --git a/csu/libc-start.c b/csu/libc-start.c
> index 12468c5a89..ccc743c9d1 100644
> --- a/csu/libc-start.c
> +++ b/csu/libc-start.c
> @@ -22,6 +22,7 @@
>  #include <ldsodefs.h>
>  #include <exit-thread.h>
>  #include <libc-internal.h>
> +#include <elf/libc-early-init.h>
>  
>  #include <elf/dl-tunables.h>
>  
> @@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
>      __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
>  
>  #ifndef SHARED
> +  /* Perform early initialization.  In the shared case, this function
> +     is called from the dynamic loader as early as possible.  */
> +  __libc_early_init ();

OK.

> +
>    /* Call the initializer of the libc.  This is only needed here if we
>       are compiling for the static library in which case we haven't
>       run the constructors in `_dl_start_user'.  */
> diff --git a/elf/Makefile b/elf/Makefile
> index da689a2c7b..23b6043cdb 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -25,7 +25,7 @@ headers		= elf.h bits/elfclass.h link.h bits/link.h
>  routines	= $(all-dl-routines) dl-support dl-iteratephdr \
>  		  dl-addr dl-addr-obj enbl-secure dl-profstub \
>  		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
> -		  dl-reloc-static-pie
> +		  dl-reloc-static-pie libc_early_init

OK.

>  
>  # The core dynamic linking functions are in libc for the static and
>  # profiled libraries.
> @@ -33,7 +33,8 @@ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
>  				  runtime init fini debug misc \
>  				  version profile tls origin scope \
>  				  execstack open close trampoline \
> -				  exception sort-maps)
> +				  exception sort-maps lookup-direct \
> +				  call-libc-early-init)

OK.

>  ifeq (yes,$(use-ldconfig))
>  dl-routines += dl-cache
>  endif
> diff --git a/elf/Versions b/elf/Versions
> index 705489fc51..3be879c4ad 100644
> --- a/elf/Versions
> +++ b/elf/Versions
> @@ -26,6 +26,7 @@ libc {
>      _dl_open_hook; _dl_open_hook2;
>      _dl_sym; _dl_vsym;
>      __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
> +    __libc_early_init;

OK. Added to GLIBC_PRIVATE.

>  
>      # Internal error handling support.  Interposes the functions in ld.so.
>      _dl_signal_exception; _dl_catch_exception;
> diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
> new file mode 100644
> index 0000000000..6c3ac5bfe7
> --- /dev/null
> +++ b/elf/dl-call-libc-early-init.c
> @@ -0,0 +1,41 @@
> +/* Invoke the early initialization function in libc.so.

OK.

> +   Copyright (C) 2019 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 <assert.h>
> +#include <ldsodefs.h>
> +#include <libc-early-init.h>
> +#include <link.h>
> +#include <stddef.h>
> +
> +void
> +_dl_call_libc_early_init (struct link_map *libc_map)
> +{
> +  /* There is nothing to do if we did not actually load libc.so.  */
> +  if (libc_map == NULL)
> +    return;
> +
> +  const ElfW(Sym) *sym
> +    = _dl_lookup_direct (libc_map, "__libc_early_init",
> +                         0x69682ac, /* dl_new_hash output.  */
> +                         "GLIBC_PRIVATE",
> +                         0x0963cf85); /* _dl_elf_hash output.  */
> +  assert (sym != NULL);

OK.

> +  __typeof (__libc_early_init) *early_init
> +    = DL_SYMBOL_ADDRESS (libc_map, sym);
> +  early_init ();
> +}

OK. Verify map is non-null. Lookup symbol in map directly. Assert symbol
is non-null, then convert the symbol to a callable address (required for
OPDs), and then call it.

> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index a6b80f9395..06f2ba7264 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -30,6 +30,7 @@
>  #include <sys/param.h>
>  #include <sys/stat.h>
>  #include <sys/types.h>
> +#include <gnu/lib-names.h>

OK.

>  
>  /* Type for the buffer we put the ELF header and hopefully the program
>     header.  This buffer does not really have to be too large.  In most
> @@ -1374,6 +1375,14 @@ cannot enable executable stack as shared object requires");

We are in _dl_map_object_from_fd...

>      add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
>  			    + l->l_info[DT_SONAME]->d_un.d_val));
>  
> +  /* If we have newly loaded libc.so, update the namespace
> +     description.  */
> +  if (GL(dl_ns)[nsid].libc_map == NULL
> +      && l->l_info[DT_SONAME] != NULL
> +      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
> +		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
> +    GL(dl_ns)[nsid].libc_map = l;

OK. Usingthe SONAME is a reasonable thing to do here. There can only
be one loaded per namespace.

> +
>    /* _dl_close can only eventually undo the module ID assignment (via
>       remove_slotinfo) if this function returns a pointer to a link
>       map.  Therefore, delay this step until all possibilities for
> diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
> new file mode 100644
> index 0000000000..190b826e1e
> --- /dev/null
> +++ b/elf/dl-lookup-direct.c
> @@ -0,0 +1,116 @@
> +/* Look up a symbol in a single specified object.

OK.

> +   Copyright (C) 1995-2019 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 <string.h>
> +#include <elf_machine_sym_no_match.h>
> +#include <dl-hash.h>
> +
> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
> +   variant here is simplified because it requires symbol
> +   versioning. */
> +static const ElfW(Sym) *
> +check_match (const struct link_map *const map, const char *const undef_name,
> +             const char *version, uint32_t version_hash,
> +             const Elf_Symndx symidx)
> +{
> +  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
> +  const ElfW(Sym) *sym = &symtab[symidx];

OK.

> +
> +  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
> +  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
> +                         && sym->st_shndx != SHN_ABS
> +                         && stt != STT_TLS)
> +                        || elf_machine_sym_no_match (sym)))
> +    return NULL;

OK.

> +
> +  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
> +     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
> +     code/data definitions.  */
> +#define ALLOWED_STT \
> +  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
> +   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
> +  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
> +    return NULL;

OK.

> +
> +  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
> +
> +  if (strcmp (strtab + sym->st_name, undef_name) != 0)
> +    /* Not the symbol we are looking for.  */
> +    return NULL;
> +
> +  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
> +  if (map->l_versions[ndx].hash != version_hash
> +      || strcmp (map->l_versions[ndx].name, version) != 0)
> +    /* It's not the version we want.  */
> +    return NULL;

OK.

> +
> +  return sym;
> +}
> +
> +
> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
> +   variant here is simplified because it does not search object
> +   dependencies.  It is optimized for a successful lookup.  */
> +const ElfW(Sym) *
> +_dl_lookup_direct (struct link_map *map,
> +                   const char *undef_name, uint32_t new_hash,
> +                   const char *version, uint32_t version_hash)
> +{
> +  const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
> +  if (__glibc_likely (bitmask != NULL))
> +    {
> +      Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
> +      if (bucket != 0)
> +        {
> +          const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
> +
> +          do
> +            if (((*hasharr ^ new_hash) >> 1) == 0)
> +              {
> +                Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
> +                const ElfW(Sym) *sym = check_match (map, undef_name,
> +                                                    version, version_hash,
> +                                                    symidx);
> +                if (sym != NULL)
> +                  return sym;

OK.

> +              }
> +          while ((*hasharr++ & 1u) == 0);
> +        }
> +    }
> +  else
> +    {
> +      /* Fallback code for lack of GNU_HASH support.  */
> +      uint32_t old_hash = _dl_elf_hash (undef_name);
> +
> +      /* Use the old SysV-style hash table.  Search the appropriate
> +         hash bucket in this object's symbol table for a definition
> +         for the same symbol name.  */
> +      for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
> +           symidx != STN_UNDEF;
> +           symidx = map->l_chain[symidx])
> +        {
> +          const ElfW(Sym) *sym = check_match (map, undef_name,
> +                                              version, version_hash, symidx);
> +          if (sym != NULL)
> +            return sym;

OK.

> +        }
> +    }
> +
> +  return NULL;
> +}
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index 7b3b177aa6..6ff6b64b46 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -34,6 +34,7 @@
>  #include <atomic.h>
>  #include <libc-internal.h>
>  #include <array_length.h>
> +#include <libc-early-init.h>

OK.

>  
>  #include <dl-dst.h>
>  #include <dl-prop.h>
> @@ -57,6 +58,13 @@ struct dl_open_args
>       (non-negative).  */
>    unsigned int original_global_scope_pending_adds;
>  
> +  /* Set to true if libc.so was already loaded into the namespace at
> +     the time dl_open_worker was called.  This is used to determine
> +     whether libc.so early initialization needs to before, and whether
> +     to roll back the cached libc_map value in the namespace in case
> +     of a dlopen failure.  */
> +  bool libc_already_loaded;

OK. Part of struct dl_open_args, not the link map. This is temporary data
that is used.

> +
>    /* Original parameters to the program and the current environment.  */
>    int argc;
>    char **argv;
> @@ -500,6 +508,11 @@ dl_open_worker (void *a)
>  	args->nsid = call_map->l_ns;
>      }
>  
> +  /* The namespace ID is now known.  Keep track of whether libc.so was
> +     already loaded, to determine whether it is necessary to call the
> +     early initialization routine (or clear libc_map on error).  */
> +  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;

OK. May set to true/false, with libc_already_loaded defaulting to true.

> +
>    /* Retain the old value, so that it can be restored.  */
>    args->original_global_scope_pending_adds
>      = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
> @@ -734,6 +747,11 @@ dl_open_worker (void *a)
>    if (relocation_in_progress)
>      LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
>  
> +  /* If libc.so was not there before, attempt to call its early
> +     initialization routine.  */
> +  if (!args->libc_already_loaded)
> +    _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);

OK. libc was loaded, but it wasn't before, call init.

> +
>  #ifndef SHARED
>    DL_STATIC_INIT (new);
>  #endif
> @@ -828,6 +846,7 @@ no more namespaces available for dlmopen()"));
>    args.caller_dlopen = caller_dlopen;
>    args.map = NULL;
>    args.nsid = nsid;
> +  args.libc_already_loaded = true; /* No reset below with early failure.  */

Is this comment correct?

I want to be really precise here.

If libc is already loaded then libc_already_loaded is true, and this default
is correct, and we don't have any recovery to worry about.

The case we want to avoid is this:
libc_already_loaded = true;
libc_map = <dangling pointer>;

The failure must come *before* we set libc_already_loaded to false when we
detect libc_map is NULL in dl_open_worker, because after this point the
reset code will execute on failure to clear libc_map.

Even then we must set libc_map to a non-NULL pointer and then fail *before*
we manage to set libc_already_loaded to NULL, and that sequence doesn't exist.

We have this covering sequence:

- Set libc_already_loaded to true.
- Call dl_open_worker
- Set libc_already_loaded correctly based on existing libc_map.

At this point if we fail the load we will clear libc_map.

If we succeed at the load we will set libc_map and trigger no unloads,
and subsequent dlopen calls will have nothing to undo, and so no reset
required.

>    args.argc = argc;
>    args.argv = argv;
>    args.env = env;
> @@ -856,6 +875,11 @@ no more namespaces available for dlmopen()"));
>    /* See if an error occurred during loading.  */
>    if (__glibc_unlikely (exception.errstring != NULL))
>      {
> +      /* Avoid keeping around a dangling reference to the libc.so link
> +	 map in case it has been cached in libc_map.  */
> +      if (!args.libc_already_loaded)
> +	GL(dl_ns)[nsid].libc_map = NULL;

OK. Reset on failure.

> +
>        /* Remove the object from memory.  It may be in an inconsistent
>  	 state if relocation failed, for example.  */
>        if (args.map)
> diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
> new file mode 100644
> index 0000000000..02b855754e
> --- /dev/null
> +++ b/elf/libc-early-init.h
> @@ -0,0 +1,35 @@
> +/* Early initialization of libc.so.
> +   Copyright (C) 2019 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/>.  */
> +
> +#ifndef _LIBC_EARLY_INIT_H
> +#define _LIBC_EARLY_INIT_H
> +
> +struct link_map;
> +
> +/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
> +   and call this function.  */
> +void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
> +
> +/* In the shared case, this function is defined in libc.so and invoked
> +   from ld.so (or on the fist static dlopen) after complete relocation
> +   of a new loaded libc.so, but before user-defined ELF constructors
> +   run.  In the static case, this function is called directly from the
> +   startup code.  */
> +void __libc_early_init (void);

OK.

> +
> +#endif /* _LIBC_EARLY_INIT_H */
> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
> new file mode 100644
> index 0000000000..1ac66d895d
> --- /dev/null
> +++ b/elf/libc_early_init.c
> @@ -0,0 +1,27 @@
> +/* Early initialization of libc.so, libc.so side.
> +   Copyright (C) 2019 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 <ctype.h>
> +#include <libc-early-init.h>
> +
> +void
> +__libc_early_init (void)
> +{
> +  /* Initialize ctype data.  */
> +  __ctype_init ();
> +}

OK.

> diff --git a/elf/rtld.c b/elf/rtld.c
> index 51dfaf966a..912dddd5cd 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -45,6 +45,7 @@
>  #include <stap-probe.h>
>  #include <stackinfo.h>
>  #include <not-cancel.h>
> +#include <libc-early-init.h>
>  
>  #include <assert.h>
>  
> @@ -2332,6 +2333,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
>        rtld_timer_accum (&relocate_time, start);
>      }
>  
> +  /* Relocation is complete.  Perform early libc initialization.  */
> +  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);

OK.

> +
>    /* Do any necessary cleanups for the startup OS interface code.
>       We do these now so that no calls are made after rtld re-relocation
>       which might be resolved to different functions than we expect.
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 497938ffa2..5ff4a2831b 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -336,6 +336,10 @@ struct rtld_global
>         recursive dlopen calls from ELF constructors.  */
>      unsigned int _ns_global_scope_pending_adds;
>  
> +    /* Once libc.so has been loaded into the namespace, this points to
> +       its link map.  */
> +    struct link_map *libc_map;

OK.

> +
>      /* Search table for unique objects.  */
>      struct unique_sym_table
>      {
> @@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
>       attribute_hidden;
>  
>  
> +/* Restricted version of _dl_lookup_symbol_x.  Searches MAP (and only
> +   MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
> +   with dl_new_hash), symbol version VERSION, and symbol version hash
> +   VERSION_HASH (computed with _dl_elf_hash).  Returns a pointer to
> +   the symbol table entry in MAP on success, or NULL on failure.  MAP
> +   must have symbol versioning information, or otherwise the result is
> +   undefined.  */
> +const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
> +				    const char *undef_name,
> +				    uint32_t new_hash,
> +				    const char *version,
> +				    uint32_t version_hash) attribute_hidden;

OK.

> +
>  /* Add the new link_map NEW to the end of the namespace list.  */
>  extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
>       attribute_hidden;
> diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
> index 92bf45223f..a7dd4895d9 100644
> --- a/sysdeps/mach/hurd/i386/init-first.c
> +++ b/sysdeps/mach/hurd/i386/init-first.c
> @@ -17,7 +17,6 @@
>     <https://www.gnu.org/licenses/>.  */
>  
>  #include <assert.h>
> -#include <ctype.h>

OK.

>  #include <hurd.h>
>  #include <stdio.h>
>  #include <unistd.h>
> @@ -85,9 +84,6 @@ posixland_init (int argc, char **argv, char **envp)
>  #endif
>    __init_misc (argc, argv, envp);
>  
> -  /* Initialize ctype data.  */
> -  __ctype_init ();
> -

OK.

>  #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>    __libc_global_ctors ();
>  #endif
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098]
  2020-03-26 15:56 ` [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098] Mathieu Desnoyers
@ 2020-04-22 17:04   ` Carlos O'Donell
  2020-04-24 20:35     ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-22 17:04 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Florian Weimer, Joseph Myers, Szabolcs Nagy, libc-alpha

On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
> From: Florian Weimer <fweimer@redhat.com>
> 
> New threads inherit the signal mask from the current thread.  This
> means that signal handlers can run on the newly created thread
> immediately after the kernel has created the userspace thread, even
> before glibc has initialized the TCB.  Consequently, new threads can
> observe uninitialized ctype data, among other things.
> 
> To address this, block all signals before starting the thread, and
> pass the original signal mask to the start routine wrapper.  On the
> new thread, first perform all thread initialization, and then unblock
> signals.
> 
> The cost of doing this is two rt_sigprocmask system calls on the old
> thread, and one rt_sigprocmask system call on the new thread.  (If
> there was a way to clone a new thread with a signals disabled, this
> could be brought down to one system call each.)  The thread descriptor
> increases in size, too, and sigset_t is fairly large.  This increase
> could be brought down by reusing space the in the descriptor which is
> not needed before running user code, or by switching to an internal
> sigset_t definition which only covers the signals supported by the
> kernel definition.  (Part of the thread descriptor size increase is
> already offset by reduced stack usage in the thread start wrapper
> routine after this commit.)

I see no other reviews of this patch so I'm not integrating other
comments.

I do not think the cost of starting up the thread is too much to pay.
You should not be restarting threads that frequently i.e. use thread
pools.

Outstanding items for Florian:

Why don't we remove parent_cancelhandling?

Technically the patch looks correct, but I'd like to know about the
removal of this variable. This descriptor is internal to glibc and
opaque, and the length is not ABI, so we should be able to just remove
it. What am I missing?

> ---
>  nptl/descr.h          | 10 +++++++---
>  nptl/pthread_create.c | 46 +++++++++++++++++++++++--------------------
>  2 files changed, 32 insertions(+), 24 deletions(-)
> 
> diff --git a/nptl/descr.h b/nptl/descr.h
> index 9dcf480bdf..e1c7db5473 100644
> --- a/nptl/descr.h
> +++ b/nptl/descr.h
> @@ -332,9 +332,8 @@ struct pthread
>    /* True if thread must stop at startup time.  */
>    bool stopped_start;
>  
> -  /* The parent's cancel handling at the time of the pthread_create
> -     call.  This might be needed to undo the effects of a cancellation.  */
> -  int parent_cancelhandling;
> +  /* Formerly used for dealing with cancellation.  */
> +  int parent_cancelhandling_unsed;

Why don't we remove this?

Likewise for pid_ununsed [sic].

What am I missing?

>  
>    /* Lock to synchronize access to the descriptor.  */
>    int lock;
> @@ -391,6 +390,11 @@ struct pthread
>    /* Resolver state.  */
>    struct __res_state res;
>  
> +  /* Signal mask for the new thread.  Used during thread startup to
> +     restore the signal mask.  (Threads are launched with all signals
> +     masked.)  */
> +  sigset_t sigmask;

OK.

> +
>    /* Indicates whether is a C11 thread created by thrd_creat.  */
>    bool c11;
>  
> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index 7c752d0f99..afd379e89a 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -369,7 +369,6 @@ __free_tcb (struct pthread *pd)
>      }
>  }
>  
> -
>  /* Local function to start thread and handle cleanup.
>     createthread.c defines the macro START_THREAD_DEFN to the
>     declaration that its create_thread function will refer to, and
> @@ -385,10 +384,6 @@ START_THREAD_DEFN
>    /* Initialize pointers to locale data.  */
>    __ctype_init ();
>  
> -  /* Allow setxid from now onwards.  */
> -  if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
> -    futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);

OK.

> -
>  #ifndef __ASSUME_SET_ROBUST_LIST
>    if (__set_robust_list_avail >= 0)
>  #endif
> @@ -399,18 +394,6 @@ START_THREAD_DEFN
>  			     sizeof (struct robust_list_head));
>      }
>  
> -  /* If the parent was running cancellation handlers while creating
> -     the thread the new thread inherited the signal mask.  Reset the
> -     cancellation signal mask.  */
> -  if (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
> -    {
> -      sigset_t mask;
> -      __sigemptyset (&mask);
> -      __sigaddset (&mask, SIGCANCEL);
> -      INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &mask,
> -			     NULL, _NSIG / 8);
> -    }

OK. Remove the ability to get cancelled during state initialization.

> -
>    /* This is where the try/finally block should be created.  For
>       compilers without that support we do use setjmp.  */
>    struct pthread_unwind_buf unwind_buf;
> @@ -432,6 +415,12 @@ START_THREAD_DEFN
>    unwind_buf.priv.data.prev = NULL;
>    unwind_buf.priv.data.cleanup = NULL;
>  

OK.

> +  __libc_signal_restore_set (&pd->sigmask);

OK. We restore the mask after doing all the other work, and *then* we enable
setxid from there onwards. Again a little more latency in handling these
requests but it removes the race conditions. We are just about to call the
user start function so this is reasonable place to start accepting
cancellation.

> +
> +  /* Allow setxid from now onwards.  */
> +  if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
> +    futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);

OK.

> +
>    if (__glibc_likely (! not_first_call))
>      {
>        /* Store the new cleanup handler info.  */
> @@ -722,10 +711,6 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
>    CHECK_THREAD_SYSINFO (pd);
>  #endif
>  
> -  /* Inform start_thread (above) about cancellation state that might
> -     translate into inherited signal state.  */
> -  pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling);

OK.

> -
>    /* Determine scheduling parameters for the thread.  */
>    if (__builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
>        && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0)
> @@ -771,6 +756,21 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
>       ownership of PD (see CONCURRENCY NOTES above).  */
>    bool stopped_start = false; bool thread_ran = false;
>  
> +  /* Block all signals, so that the new thread starts out with
> +     signals disabled.  This avoids race conditions in the thread
> +     startup.  */
> +  sigset_t original_sigmask;
> +  __libc_signal_block_all (&original_sigmask);

OK. Allows us to block everything.

> +
> +  /* Conceptually, the new thread needs to inherit the signal mask of
> +     this thread.  Therefore, it needs to restore the saved signal
> +     mask of this thread, so save it in the startup information.  */
> +  pd->sigmask = original_sigmask;

OK.

> +
> +  /* Reset the cancellation signal mask in case this thread is running
> +     cancellation.  */
> +  __sigdelset (&pd->sigmask, SIGCANCEL);

OK. Safe to do.

> +
>    /* Start the thread.  */
>    if (__glibc_unlikely (report_thread_creation (pd)))
>      {
> @@ -813,6 +813,10 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
>      retval = create_thread (pd, iattr, &stopped_start,
>  			    STACK_VARIABLES_ARGS, &thread_ran);
>  
> +  /* Return to the previous signal mask, after creating the new
> +     thread.  */
> +  __libc_signal_restore_set (&original_sigmask);

OK. We increase signal latency here for the duration of the the thread creation.

> +
>    if (__glibc_unlikely (retval != 0))
>      {
>        if (thread_ran)
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h>
  2020-04-22 16:27   ` Carlos O'Donell
@ 2020-04-24 18:20     ` Florian Weimer
  2020-04-24 20:11       ` Carlos O'Donell
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-24 18:20 UTC (permalink / raw)
  To: Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Carlos O'Donell, Joseph Myers

* Carlos O'Donell via Libc-alpha:

> On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
>> From: Florian Weimer <fweimer@redhat.com>
>> 
>> MIPS needs to ignore certain existing symbols during symbol lookup.
>> The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
>> inline function, within its own header, with a sysdeps override for
>> MIPS.  This allows re-use of the function from another file (without
>> having to include <dl-machine.h> or providing the default definition
>> for ELF_MACHINE_SYM_NO_MATCH).
>> 
>> Built with build-many-glibcs.py, with manual verification that
>> sysdeps/mips/elf_machine_sym_no_match.h is picked up on MIPS.  Tested
>> on aarch64-linux-gnu, i686-linux-gnu, powerpc64-linux-gnu,
>> s390x-linux-gnu, x86_64-linux-gnu.
>
> The refactoring from a macro to a static inline function looks good to
> me. There isn't anything that changes.
>
> This patch needs squashing with the second patch in the series.
>
> Technically speaking it's ready to be committed, but I want to see the
> squashed patch before ACK'ing it.

Merged and updated patch below.  I've fixed the copyright years.

I did a mips-linux-gnu build, and the sysdeps override still appears
to be effective:

…/bmg/default/src/glibc/elf/dl-lookup-direct.c:36
  64:   11200031        beqz    t1,12c <check_match+0x12c>
  68:   3043000f        andi    v1,v0,0xf
  6c:   9206000d        lbu     a2,13(s0)
elf_machine_sym_no_match():
…/bmg/default/src/glibc/elf/../sysdeps/mips/elf_machine_sym_no_match.h:40
  70:   15000003        bnez    t0,80 <check_match+0x80>
  74:   30c60008        andi    a2,a2,0x8
  78:   10c00021        beqz    a2,100 <check_match+0x100>
  7c:   00000000        nop
check_match():
…/bmg/default/src/glibc/elf/dl-lookup-direct.c:48
  80:   24020467        li      v0,1127
  84:   00621007        srav    v0,v0,v1

8<------------------------------------------------------------------8<
Subject: [PATCH] elf: Introduce <elf_machine_sym_no_match.h>

MIPS needs to ignore certain existing symbols during symbol lookup.
The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
inline function, within its own header, with a sysdeps override for
MIPS.  This allows re-use of the function from another file (without
having to include <dl-machine.h> or providing the default definition
for ELF_MACHINE_SYM_NO_MATCH).

-----
 elf/dl-lookup.c                            | 10 ++-----
 sysdeps/generic/elf_machine_sym_no_match.h | 34 +++++++++++++++++++++++
 sysdeps/mips/dl-machine.h                  | 15 -----------
 sysdeps/mips/elf_machine_sym_no_match.h    | 43 ++++++++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 23 deletions(-)

diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 12a229f06c..807f3ea9b6 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -28,18 +28,12 @@
 #include <libc-lock.h>
 #include <tls.h>
 #include <atomic.h>
+#include <elf_machine_sym_no_match.h>
 
 #include <assert.h>
 
-/* Return nonzero if check_match should consider SYM to fail to match a
-   symbol reference for some machine-specific reason.  */
-#ifndef ELF_MACHINE_SYM_NO_MATCH
-# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
-#endif
-
 #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
 
-
 struct sym_val
   {
     const ElfW(Sym) *s;
@@ -78,7 +72,7 @@ check_match (const char *const undef_name,
   if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
 			 && sym->st_shndx != SHN_ABS
 			 && stt != STT_TLS)
-			|| ELF_MACHINE_SYM_NO_MATCH (sym)
+			|| elf_machine_sym_no_match (sym)
 			|| (type_class & (sym->st_shndx == SHN_UNDEF))))
     return NULL;
 
diff --git a/sysdeps/generic/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h
new file mode 100644
index 0000000000..27155de4c0
--- /dev/null
+++ b/sysdeps/generic/elf_machine_sym_no_match.h
@@ -0,0 +1,34 @@
+/* Function to ignore certain symbol matches for machine-specific reasons.
+   Copyright (C) 2020 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/>.  */
+
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
+#define _ELF_MACHINE_SYM_NO_MATCH_H
+
+#include <link.h>
+#include <stdbool.h>
+
+/* This can be customized to ignore certain symbols during lookup in
+   case there are machine-specific rules to disregard some
+   symbols.  */
+static inline bool
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
+{
+  return false;
+}
+
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 06021ea9ab..e3b11a4f21 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
   return value;
 }
 
-/* The semantics of zero/non-zero values of undefined symbols differs
-   depending on whether the non-PIC ABI is in use.  Under the non-PIC
-   ABI, a non-zero value indicates that there is an address reference
-   to the symbol and thus it must always be resolved (except when
-   resolving a jump slot relocation) to the PLT entry whose address is
-   provided as the symbol's value; a zero value indicates that this
-   canonical-address behaviour is not required.  Yet under the classic
-   MIPS psABI, a zero value indicates that there is an address
-   reference to the function and the dynamic linker must resolve the
-   symbol immediately upon loading.  To avoid conflict, symbols for
-   which the dynamic linker must assume the non-PIC ABI semantics are
-   marked with the STO_MIPS_PLT flag.  */
-#define ELF_MACHINE_SYM_NO_MATCH(sym) \
-  ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
-
 #endif /* !dl_machine_h */
 
 #ifdef RESOLVE_MAP
diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h
new file mode 100644
index 0000000000..9d09e5fa2d
--- /dev/null
+++ b/sysdeps/mips/elf_machine_sym_no_match.h
@@ -0,0 +1,43 @@
+/* MIPS-specific handling of undefined symbols.
+   Copyright (C) 2008-2020 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/>.  */
+
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
+#define _ELF_MACHINE_SYM_NO_MATCH_H
+
+#include <link.h>
+#include <stdbool.h>
+
+/* The semantics of zero/non-zero values of undefined symbols differs
+   depending on whether the non-PIC ABI is in use.  Under the non-PIC
+   ABI, a non-zero value indicates that there is an address reference
+   to the symbol and thus it must always be resolved (except when
+   resolving a jump slot relocation) to the PLT entry whose address is
+   provided as the symbol's value; a zero value indicates that this
+   canonical-address behaviour is not required.  Yet under the classic
+   MIPS psABI, a zero value indicates that there is an address
+   reference to the function and the dynamic linker must resolve the
+   symbol immediately upon loading.  To avoid conflict, symbols for
+   which the dynamic linker must assume the non-PIC ABI semantics are
+   marked with the STO_MIPS_PLT flag.  */
+static inline bool
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
+{
+  return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT);
+}
+
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */

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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-22 16:28   ` Carlos O'Donell
@ 2020-04-24 18:22     ` Florian Weimer
  2020-04-24 20:18       ` Carlos O'Donell
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-24 18:22 UTC (permalink / raw)
  To: Carlos O'Donell via Libc-alpha
  Cc: Florian Weimer, Carlos O'Donell, Mathieu Desnoyers, Joseph Myers

* Carlos O'Donell via Libc-alpha:

> Please clarify or remove the comment related to libc_already_loaded.

I have removed the initialization.  It is no longer relevant in the
current patch.  It may have been obsoleted by other dl_open_worker
changes earlier.

I fixed a few copyright years and one or two style issues.

Tested on i686-linux-gnu and x86_64-linux-gnu.

8<------------------------------------------------------------------8<
Subject: [PATCH] elf: Implement __libc_early_init

This function is defined in libc.so, and the dynamic loader calls
right after relocation has been finished, before any ELF constructors
or the preinit function is invoked.  It is also used in the static
build for initializing parts of the static libc.

To locate __libc_early_init, a direct symbol lookup function is used,
_dl_lookup_direct.  It does not search the entire symbol scope and
consults merely a single link map.  This function could also be used
to implement lookups in the vDSO (as an optimization).

A per-namespace variable (libc_map) is added for locating libc.so,
to avoid repeated traversals of the search scope.  It is similar to
GL(dl_initfirst).  An alternative would have been to thread a context
argument from _dl_open down to _dl_map_object_from_fd (where libc.so
is identified).  This could have avoided the global variable, but
the change would be larger as a result.  It would not have been
possible to use this to replace GL(dl_initfirst) because that global
variable is used to pass the function pointer past the stack switch
from dl_main to the main program.  Replacing that requires adding
a new argument to _dl_init, which in turn needs changes to the
architecture-specific libc.so startup code written in assembler.

__libc_early_init should not be used to replace _dl_var_init (as
it exists today on some architectures).  Instead, _dl_lookup_direct
should be used to look up a new variable symbol in libc.so, and
that should then be initialized from the dynamic loader, immediately
after the object has been loaded in _dl_map_object_from_fd (before
relocation is run).  This way, more IFUNC resolvers which depend on
these variables will work.

-----
 csu/init-first.c                    |   4 --
 csu/libc-start.c                    |   5 ++
 elf/Makefile                        |   5 +-
 elf/Versions                        |   1 +
 elf/dl-call-libc-early-init.c       |  41 +++++++++++++
 elf/dl-load.c                       |   9 +++
 elf/dl-lookup-direct.c              | 116 ++++++++++++++++++++++++++++++++++++
 elf/dl-open.c                       |  25 ++++++++
 elf/libc-early-init.h               |  35 +++++++++++
 elf/libc_early_init.c               |  27 +++++++++
 elf/rtld.c                          |   4 ++
 sysdeps/generic/ldsodefs.h          |  17 ++++++
 sysdeps/mach/hurd/i386/init-first.c |   4 --
 13 files changed, 283 insertions(+), 10 deletions(-)

diff --git a/csu/init-first.c b/csu/init-first.c
index 264e6f348d..d214af7116 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -16,7 +16,6 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -75,9 +74,6 @@ _init_first (int argc, char **argv, char **envp)
 
   __init_misc (argc, argv, envp);
 
-  /* Initialize ctype data.  */
-  __ctype_init ();
-
 #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
   __libc_global_ctors ();
 #endif
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 12468c5a89..ccc743c9d1 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -22,6 +22,7 @@
 #include <ldsodefs.h>
 #include <exit-thread.h>
 #include <libc-internal.h>
+#include <elf/libc-early-init.h>
 
 #include <elf/dl-tunables.h>
 
@@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
     __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
 
 #ifndef SHARED
+  /* Perform early initialization.  In the shared case, this function
+     is called from the dynamic loader as early as possible.  */
+  __libc_early_init ();
+
   /* Call the initializer of the libc.  This is only needed here if we
      are compiling for the static library in which case we haven't
      run the constructors in `_dl_start_user'.  */
diff --git a/elf/Makefile b/elf/Makefile
index 6919e53c14..77da61ae64 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -25,7 +25,7 @@ headers		= elf.h bits/elfclass.h link.h bits/link.h
 routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 		  dl-addr dl-addr-obj enbl-secure dl-profstub \
 		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
-		  dl-reloc-static-pie
+		  dl-reloc-static-pie libc_early_init
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -33,7 +33,8 @@ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
 				  runtime init fini debug misc \
 				  version profile tls origin scope \
 				  execstack open close trampoline \
-				  exception sort-maps)
+				  exception sort-maps lookup-direct \
+				  call-libc-early-init)
 ifeq (yes,$(use-ldconfig))
 dl-routines += dl-cache
 endif
diff --git a/elf/Versions b/elf/Versions
index 705489fc51..3be879c4ad 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -26,6 +26,7 @@ libc {
     _dl_open_hook; _dl_open_hook2;
     _dl_sym; _dl_vsym;
     __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
+    __libc_early_init;
 
     # Internal error handling support.  Interposes the functions in ld.so.
     _dl_signal_exception; _dl_catch_exception;
diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
new file mode 100644
index 0000000000..41e9ad9aad
--- /dev/null
+++ b/elf/dl-call-libc-early-init.c
@@ -0,0 +1,41 @@
+/* Invoke the early initialization function in libc.so.
+   Copyright (C) 2020 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 <assert.h>
+#include <ldsodefs.h>
+#include <libc-early-init.h>
+#include <link.h>
+#include <stddef.h>
+
+void
+_dl_call_libc_early_init (struct link_map *libc_map)
+{
+  /* There is nothing to do if we did not actually load libc.so.  */
+  if (libc_map == NULL)
+    return;
+
+  const ElfW(Sym) *sym
+    = _dl_lookup_direct (libc_map, "__libc_early_init",
+                         0x069682ac, /* dl_new_hash output.  */
+                         "GLIBC_PRIVATE",
+                         0x0963cf85); /* _dl_elf_hash output.  */
+  assert (sym != NULL);
+  __typeof (__libc_early_init) *early_init
+    = DL_SYMBOL_ADDRESS (libc_map, sym);
+  early_init ();
+}
diff --git a/elf/dl-load.c b/elf/dl-load.c
index a6b80f9395..06f2ba7264 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -30,6 +30,7 @@
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <gnu/lib-names.h>
 
 /* Type for the buffer we put the ELF header and hopefully the program
    header.  This buffer does not really have to be too large.  In most
@@ -1374,6 +1375,14 @@ cannot enable executable stack as shared object requires");
     add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
 			    + l->l_info[DT_SONAME]->d_un.d_val));
 
+  /* If we have newly loaded libc.so, update the namespace
+     description.  */
+  if (GL(dl_ns)[nsid].libc_map == NULL
+      && l->l_info[DT_SONAME] != NULL
+      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
+		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
+    GL(dl_ns)[nsid].libc_map = l;
+
   /* _dl_close can only eventually undo the module ID assignment (via
      remove_slotinfo) if this function returns a pointer to a link
      map.  Therefore, delay this step until all possibilities for
diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
new file mode 100644
index 0000000000..5637ae89de
--- /dev/null
+++ b/elf/dl-lookup-direct.c
@@ -0,0 +1,116 @@
+/* Look up a symbol in a single specified object.
+   Copyright (C) 1995-2020 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 <string.h>
+#include <elf_machine_sym_no_match.h>
+#include <dl-hash.h>
+
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
+   variant here is simplified because it requires symbol
+   versioning.  */
+static const ElfW(Sym) *
+check_match (const struct link_map *const map, const char *const undef_name,
+             const char *version, uint32_t version_hash,
+             const Elf_Symndx symidx)
+{
+  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  const ElfW(Sym) *sym = &symtab[symidx];
+
+  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
+  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
+                         && sym->st_shndx != SHN_ABS
+                         && stt != STT_TLS)
+                        || elf_machine_sym_no_match (sym)))
+    return NULL;
+
+  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
+     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
+     code/data definitions.  */
+#define ALLOWED_STT \
+  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
+   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
+  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
+    return NULL;
+
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+
+  if (strcmp (strtab + sym->st_name, undef_name) != 0)
+    /* Not the symbol we are looking for.  */
+    return NULL;
+
+  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
+  if (map->l_versions[ndx].hash != version_hash
+      || strcmp (map->l_versions[ndx].name, version) != 0)
+    /* It's not the version we want.  */
+    return NULL;
+
+  return sym;
+}
+
+
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
+   variant here is simplified because it does not search object
+   dependencies.  It is optimized for a successful lookup.  */
+const ElfW(Sym) *
+_dl_lookup_direct (struct link_map *map,
+                   const char *undef_name, uint32_t new_hash,
+                   const char *version, uint32_t version_hash)
+{
+  const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
+  if (__glibc_likely (bitmask != NULL))
+    {
+      Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
+      if (bucket != 0)
+        {
+          const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
+
+          do
+            if (((*hasharr ^ new_hash) >> 1) == 0)
+              {
+                Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
+                const ElfW(Sym) *sym = check_match (map, undef_name,
+                                                    version, version_hash,
+                                                    symidx);
+                if (sym != NULL)
+                  return sym;
+              }
+          while ((*hasharr++ & 1u) == 0);
+        }
+    }
+  else
+    {
+      /* Fallback code for lack of GNU_HASH support.  */
+      uint32_t old_hash = _dl_elf_hash (undef_name);
+
+      /* Use the old SysV-style hash table.  Search the appropriate
+         hash bucket in this object's symbol table for a definition
+         for the same symbol name.  */
+      for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
+           symidx != STN_UNDEF;
+           symidx = map->l_chain[symidx])
+        {
+          const ElfW(Sym) *sym = check_match (map, undef_name,
+                                              version, version_hash, symidx);
+          if (sym != NULL)
+            return sym;
+        }
+    }
+
+  return NULL;
+}
diff --git a/elf/dl-open.c b/elf/dl-open.c
index d9fdb0bdce..86bc28e431 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -34,6 +34,7 @@
 #include <atomic.h>
 #include <libc-internal.h>
 #include <array_length.h>
+#include <libc-early-init.h>
 
 #include <dl-dst.h>
 #include <dl-prop.h>
@@ -57,6 +58,13 @@ struct dl_open_args
      (non-negative).  */
   unsigned int original_global_scope_pending_adds;
 
+  /* Set to true by dl_open_worker if libc.so was already loaded into
+     the namespace at the time dl_open_worker was called.  This is
+     used to determine whether libc.so early initialization has
+     already been done before, and whether to roll back the cached
+     libc_map value in the namespace in case of a dlopen failure.  */
+  bool libc_already_loaded;
+
   /* Original parameters to the program and the current environment.  */
   int argc;
   char **argv;
@@ -500,6 +508,11 @@ dl_open_worker (void *a)
 	args->nsid = call_map->l_ns;
     }
 
+  /* The namespace ID is now known.  Keep track of whether libc.so was
+     already loaded, to determine whether it is necessary to call the
+     early initialization routine (or clear libc_map on error).  */
+  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
+
   /* Retain the old value, so that it can be restored.  */
   args->original_global_scope_pending_adds
     = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
@@ -734,6 +747,11 @@ dl_open_worker (void *a)
   if (relocation_in_progress)
     LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
 
+  /* If libc.so was not there before, attempt to call its early
+     initialization routine.  */
+  if (!args->libc_already_loaded)
+    _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);
+
 #ifndef SHARED
   DL_STATIC_INIT (new);
 #endif
@@ -823,6 +841,8 @@ no more namespaces available for dlmopen()"));
   args.caller_dlopen = caller_dlopen;
   args.map = NULL;
   args.nsid = nsid;
+  /* args.libc_already_loaded is always assigned by dl_open_worker
+     (before any explicit/non-local returns).  */
   args.argc = argc;
   args.argv = argv;
   args.env = env;
@@ -851,6 +871,11 @@ no more namespaces available for dlmopen()"));
   /* See if an error occurred during loading.  */
   if (__glibc_unlikely (exception.errstring != NULL))
     {
+      /* Avoid keeping around a dangling reference to the libc.so link
+	 map in case it has been cached in libc_map.  */
+      if (!args.libc_already_loaded)
+	GL(dl_ns)[nsid].libc_map = NULL;
+
       /* Remove the object from memory.  It may be in an inconsistent
 	 state if relocation failed, for example.  */
       if (args.map)
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
new file mode 100644
index 0000000000..5185fa8895
--- /dev/null
+++ b/elf/libc-early-init.h
@@ -0,0 +1,35 @@
+/* Early initialization of libc.so.
+   Copyright (C) 2020 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/>.  */
+
+#ifndef _LIBC_EARLY_INIT_H
+#define _LIBC_EARLY_INIT_H
+
+struct link_map;
+
+/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
+   and call this function.  */
+void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
+
+/* In the shared case, this function is defined in libc.so and invoked
+   from ld.so (or on the fist static dlopen) after complete relocation
+   of a new loaded libc.so, but before user-defined ELF constructors
+   run.  In the static case, this function is called directly from the
+   startup code.  */
+void __libc_early_init (void);
+
+#endif /* _LIBC_EARLY_INIT_H */
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
new file mode 100644
index 0000000000..7f4ca332b8
--- /dev/null
+++ b/elf/libc_early_init.c
@@ -0,0 +1,27 @@
+/* Early initialization of libc.so, libc.so side.
+   Copyright (C) 2020 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 <ctype.h>
+#include <libc-early-init.h>
+
+void
+__libc_early_init (void)
+{
+  /* Initialize ctype data.  */
+  __ctype_init ();
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index b2ea21c98b..0016db86a7 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -46,6 +46,7 @@
 #include <stackinfo.h>
 #include <not-cancel.h>
 #include <array_length.h>
+#include <libc-early-init.h>
 
 #include <assert.h>
 
@@ -2372,6 +2373,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
       rtld_timer_accum (&relocate_time, start);
     }
 
+  /* Relocation is complete.  Perform early libc initialization.  */
+  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);
+
   /* Do any necessary cleanups for the startup OS interface code.
      We do these now so that no calls are made after rtld re-relocation
      which might be resolved to different functions than we expect.
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 497938ffa2..5ff4a2831b 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -336,6 +336,10 @@ struct rtld_global
        recursive dlopen calls from ELF constructors.  */
     unsigned int _ns_global_scope_pending_adds;
 
+    /* Once libc.so has been loaded into the namespace, this points to
+       its link map.  */
+    struct link_map *libc_map;
+
     /* Search table for unique objects.  */
     struct unique_sym_table
     {
@@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
      attribute_hidden;
 
 
+/* Restricted version of _dl_lookup_symbol_x.  Searches MAP (and only
+   MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
+   with dl_new_hash), symbol version VERSION, and symbol version hash
+   VERSION_HASH (computed with _dl_elf_hash).  Returns a pointer to
+   the symbol table entry in MAP on success, or NULL on failure.  MAP
+   must have symbol versioning information, or otherwise the result is
+   undefined.  */
+const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
+				    const char *undef_name,
+				    uint32_t new_hash,
+				    const char *version,
+				    uint32_t version_hash) attribute_hidden;
+
 /* Add the new link_map NEW to the end of the namespace list.  */
 extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
      attribute_hidden;
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 92bf45223f..a7dd4895d9 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -17,7 +17,6 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
-#include <ctype.h>
 #include <hurd.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -85,9 +84,6 @@ posixland_init (int argc, char **argv, char **envp)
 #endif
   __init_misc (argc, argv, envp);
 
-  /* Initialize ctype data.  */
-  __ctype_init ();
-
 #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
   __libc_global_ctors ();
 #endif

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

* Re: [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h>
  2020-04-24 18:20     ` Florian Weimer
@ 2020-04-24 20:11       ` Carlos O'Donell
  0 siblings, 0 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-24 20:11 UTC (permalink / raw)
  To: Florian Weimer, Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Joseph Myers

On 4/24/20 2:20 PM, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> On 3/26/20 11:56 AM, Mathieu Desnoyers wrote:
>>> From: Florian Weimer <fweimer@redhat.com>
>>>
>>> MIPS needs to ignore certain existing symbols during symbol lookup.
>>> The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
>>> inline function, within its own header, with a sysdeps override for
>>> MIPS.  This allows re-use of the function from another file (without
>>> having to include <dl-machine.h> or providing the default definition
>>> for ELF_MACHINE_SYM_NO_MATCH).
>>>
>>> Built with build-many-glibcs.py, with manual verification that
>>> sysdeps/mips/elf_machine_sym_no_match.h is picked up on MIPS.  Tested
>>> on aarch64-linux-gnu, i686-linux-gnu, powerpc64-linux-gnu,
>>> s390x-linux-gnu, x86_64-linux-gnu.
>>
>> The refactoring from a macro to a static inline function looks good to
>> me. There isn't anything that changes.
>>
>> This patch needs squashing with the second patch in the series.
>>
>> Technically speaking it's ready to be committed, but I want to see the
>> squashed patch before ACK'ing it.
> 
> Merged and updated patch below.  I've fixed the copyright years.
> 
> I did a mips-linux-gnu build, and the sysdeps override still appears
> to be effective:
> 
> …/bmg/default/src/glibc/elf/dl-lookup-direct.c:36
>   64:   11200031        beqz    t1,12c <check_match+0x12c>
>   68:   3043000f        andi    v1,v0,0xf
>   6c:   9206000d        lbu     a2,13(s0)
> elf_machine_sym_no_match():
> …/bmg/default/src/glibc/elf/../sysdeps/mips/elf_machine_sym_no_match.h:40

Thanks for cross-checking the built objects!

>   70:   15000003        bnez    t0,80 <check_match+0x80>
>   74:   30c60008        andi    a2,a2,0x8
>   78:   10c00021        beqz    a2,100 <check_match+0x100>
>   7c:   00000000        nop
> check_match():
> …/bmg/default/src/glibc/elf/dl-lookup-direct.c:48
>   80:   24020467        li      v0,1127
>   84:   00621007        srav    v0,v0,v1
> 
> 8<------------------------------------------------------------------8<
> Subject: [PATCH] elf: Introduce <elf_machine_sym_no_match.h>
> 
> MIPS needs to ignore certain existing symbols during symbol lookup.
> The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
> inline function, within its own header, with a sysdeps override for
> MIPS.  This allows re-use of the function from another file (without
> having to include <dl-machine.h> or providing the default definition
> for ELF_MACHINE_SYM_NO_MATCH).
> 

OK for master.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> -----
>  elf/dl-lookup.c                            | 10 ++-----
>  sysdeps/generic/elf_machine_sym_no_match.h | 34 +++++++++++++++++++++++
>  sysdeps/mips/dl-machine.h                  | 15 -----------
>  sysdeps/mips/elf_machine_sym_no_match.h    | 43 ++++++++++++++++++++++++++++++
>  4 files changed, 79 insertions(+), 23 deletions(-)
> 
> diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
> index 12a229f06c..807f3ea9b6 100644
> --- a/elf/dl-lookup.c
> +++ b/elf/dl-lookup.c
> @@ -28,18 +28,12 @@
>  #include <libc-lock.h>
>  #include <tls.h>
>  #include <atomic.h>
> +#include <elf_machine_sym_no_match.h>

OK.

>  
>  #include <assert.h>
>  
> -/* Return nonzero if check_match should consider SYM to fail to match a
> -   symbol reference for some machine-specific reason.  */
> -#ifndef ELF_MACHINE_SYM_NO_MATCH
> -# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
> -#endif
> -

OK.

>  #define VERSTAG(tag)	(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
>  
> -
>  struct sym_val
>    {
>      const ElfW(Sym) *s;
> @@ -78,7 +72,7 @@ check_match (const char *const undef_name,
>    if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
>  			 && sym->st_shndx != SHN_ABS
>  			 && stt != STT_TLS)
> -			|| ELF_MACHINE_SYM_NO_MATCH (sym)
> +			|| elf_machine_sym_no_match (sym)

OK.

>  			|| (type_class & (sym->st_shndx == SHN_UNDEF))))
>      return NULL;
>  
> diff --git a/sysdeps/generic/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h
> new file mode 100644
> index 0000000000..27155de4c0
> --- /dev/null
> +++ b/sysdeps/generic/elf_machine_sym_no_match.h

OK. Correct path.

> @@ -0,0 +1,34 @@
> +/* Function to ignore certain symbol matches for machine-specific reasons.
> +   Copyright (C) 2020 Free Software Foundation, Inc.

OK.

> +   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/>.  */
> +
> +#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
> +#define _ELF_MACHINE_SYM_NO_MATCH_H
> +
> +#include <link.h>
> +#include <stdbool.h>
> +
> +/* This can be customized to ignore certain symbols during lookup in
> +   case there are machine-specific rules to disregard some
> +   symbols.  */
> +static inline bool
> +elf_machine_sym_no_match (const ElfW(Sym) *sym)
> +{
> +  return false;
> +}
> +
> +#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */

OK.

> diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
> index 06021ea9ab..e3b11a4f21 100644
> --- a/sysdeps/mips/dl-machine.h
> +++ b/sysdeps/mips/dl-machine.h
> @@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
>    return value;
>  }
>  
> -/* The semantics of zero/non-zero values of undefined symbols differs
> -   depending on whether the non-PIC ABI is in use.  Under the non-PIC
> -   ABI, a non-zero value indicates that there is an address reference
> -   to the symbol and thus it must always be resolved (except when
> -   resolving a jump slot relocation) to the PLT entry whose address is
> -   provided as the symbol's value; a zero value indicates that this
> -   canonical-address behaviour is not required.  Yet under the classic
> -   MIPS psABI, a zero value indicates that there is an address
> -   reference to the function and the dynamic linker must resolve the
> -   symbol immediately upon loading.  To avoid conflict, symbols for
> -   which the dynamic linker must assume the non-PIC ABI semantics are
> -   marked with the STO_MIPS_PLT flag.  */
> -#define ELF_MACHINE_SYM_NO_MATCH(sym) \
> -  ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
> -

OK.

>  #endif /* !dl_machine_h */
>  
>  #ifdef RESOLVE_MAP
> diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h
> new file mode 100644
> index 0000000000..9d09e5fa2d
> --- /dev/null
> +++ b/sysdeps/mips/elf_machine_sym_no_match.h
> @@ -0,0 +1,43 @@
> +/* MIPS-specific handling of undefined symbols.
> +   Copyright (C) 2008-2020 Free Software Foundation, Inc.

OK.

Correct and tracked down to 63fb881a04bb46b83f95b83c3751ba9d0145e29a
which was indeed made in 2008, and is the original source of the change
and comment.

> +   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/>.  */
> +
> +#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
> +#define _ELF_MACHINE_SYM_NO_MATCH_H
> +
> +#include <link.h>
> +#include <stdbool.h>
> +
> +/* The semantics of zero/non-zero values of undefined symbols differs
> +   depending on whether the non-PIC ABI is in use.  Under the non-PIC
> +   ABI, a non-zero value indicates that there is an address reference
> +   to the symbol and thus it must always be resolved (except when
> +   resolving a jump slot relocation) to the PLT entry whose address is
> +   provided as the symbol's value; a zero value indicates that this
> +   canonical-address behaviour is not required.  Yet under the classic
> +   MIPS psABI, a zero value indicates that there is an address
> +   reference to the function and the dynamic linker must resolve the
> +   symbol immediately upon loading.  To avoid conflict, symbols for
> +   which the dynamic linker must assume the non-PIC ABI semantics are
> +   marked with the STO_MIPS_PLT flag.  */
> +static inline bool
> +elf_machine_sym_no_match (const ElfW(Sym) *sym)
> +{
> +  return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT);
> +}
> +
> +#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-24 18:22     ` Florian Weimer
@ 2020-04-24 20:18       ` Carlos O'Donell
  2020-04-27 12:43         ` Stefan Liebler
  2020-04-27 12:57         ` Adhemerval Zanella
  0 siblings, 2 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-24 20:18 UTC (permalink / raw)
  To: Florian Weimer, Carlos O'Donell via Libc-alpha
  Cc: Florian Weimer, Mathieu Desnoyers, Joseph Myers

On 4/24/20 2:22 PM, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> Please clarify or remove the comment related to libc_already_loaded.
> 
> I have removed the initialization.  It is no longer relevant in the
> current patch.  It may have been obsoleted by other dl_open_worker
> changes earlier.

Thanks!

> I fixed a few copyright years and one or two style issues.
> 
> Tested on i686-linux-gnu and x86_64-linux-gnu.
> 
> 8<------------------------------------------------------------------8<
> Subject: [PATCH] elf: Implement __libc_early_init
> 
> This function is defined in libc.so, and the dynamic loader calls
> right after relocation has been finished, before any ELF constructors
> or the preinit function is invoked.  It is also used in the static
> build for initializing parts of the static libc.
> 
> To locate __libc_early_init, a direct symbol lookup function is used,
> _dl_lookup_direct.  It does not search the entire symbol scope and
> consults merely a single link map.  This function could also be used
> to implement lookups in the vDSO (as an optimization).
> 
> A per-namespace variable (libc_map) is added for locating libc.so,
> to avoid repeated traversals of the search scope.  It is similar to
> GL(dl_initfirst).  An alternative would have been to thread a context
> argument from _dl_open down to _dl_map_object_from_fd (where libc.so
> is identified).  This could have avoided the global variable, but
> the change would be larger as a result.  It would not have been
> possible to use this to replace GL(dl_initfirst) because that global
> variable is used to pass the function pointer past the stack switch
> from dl_main to the main program.  Replacing that requires adding
> a new argument to _dl_init, which in turn needs changes to the
> architecture-specific libc.so startup code written in assembler.
> 
> __libc_early_init should not be used to replace _dl_var_init (as
> it exists today on some architectures).  Instead, _dl_lookup_direct
> should be used to look up a new variable symbol in libc.so, and
> that should then be initialized from the dynamic loader, immediately
> after the object has been loaded in _dl_map_object_from_fd (before
> relocation is run).  This way, more IFUNC resolvers which depend on
> these variables will work.

OK for master.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> -----
>  csu/init-first.c                    |   4 --
>  csu/libc-start.c                    |   5 ++
>  elf/Makefile                        |   5 +-
>  elf/Versions                        |   1 +
>  elf/dl-call-libc-early-init.c       |  41 +++++++++++++
>  elf/dl-load.c                       |   9 +++
>  elf/dl-lookup-direct.c              | 116 ++++++++++++++++++++++++++++++++++++
>  elf/dl-open.c                       |  25 ++++++++
>  elf/libc-early-init.h               |  35 +++++++++++
>  elf/libc_early_init.c               |  27 +++++++++
>  elf/rtld.c                          |   4 ++
>  sysdeps/generic/ldsodefs.h          |  17 ++++++
>  sysdeps/mach/hurd/i386/init-first.c |   4 --
>  13 files changed, 283 insertions(+), 10 deletions(-)
> 
> diff --git a/csu/init-first.c b/csu/init-first.c
> index 264e6f348d..d214af7116 100644
> --- a/csu/init-first.c
> +++ b/csu/init-first.c
> @@ -16,7 +16,6 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <ctype.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <fcntl.h>
> @@ -75,9 +74,6 @@ _init_first (int argc, char **argv, char **envp)
>  
>    __init_misc (argc, argv, envp);
>  
> -  /* Initialize ctype data.  */
> -  __ctype_init ();

OK.

> -
>  #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>    __libc_global_ctors ();
>  #endif
> diff --git a/csu/libc-start.c b/csu/libc-start.c
> index 12468c5a89..ccc743c9d1 100644
> --- a/csu/libc-start.c
> +++ b/csu/libc-start.c
> @@ -22,6 +22,7 @@
>  #include <ldsodefs.h>
>  #include <exit-thread.h>
>  #include <libc-internal.h>
> +#include <elf/libc-early-init.h>

OK.

>  
>  #include <elf/dl-tunables.h>
>  
> @@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
>      __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
>  
>  #ifndef SHARED
> +  /* Perform early initialization.  In the shared case, this function
> +     is called from the dynamic loader as early as possible.  */
> +  __libc_early_init ();
> +

OK.

>    /* Call the initializer of the libc.  This is only needed here if we
>       are compiling for the static library in which case we haven't
>       run the constructors in `_dl_start_user'.  */
> diff --git a/elf/Makefile b/elf/Makefile
> index 6919e53c14..77da61ae64 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -25,7 +25,7 @@ headers		= elf.h bits/elfclass.h link.h bits/link.h
>  routines	= $(all-dl-routines) dl-support dl-iteratephdr \
>  		  dl-addr dl-addr-obj enbl-secure dl-profstub \
>  		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
> -		  dl-reloc-static-pie
> +		  dl-reloc-static-pie libc_early_init

OK.

>  
>  # The core dynamic linking functions are in libc for the static and
>  # profiled libraries.
> @@ -33,7 +33,8 @@ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
>  				  runtime init fini debug misc \
>  				  version profile tls origin scope \
>  				  execstack open close trampoline \
> -				  exception sort-maps)
> +				  exception sort-maps lookup-direct \
> +				  call-libc-early-init)

OK.

>  ifeq (yes,$(use-ldconfig))
>  dl-routines += dl-cache
>  endif
> diff --git a/elf/Versions b/elf/Versions
> index 705489fc51..3be879c4ad 100644
> --- a/elf/Versions
> +++ b/elf/Versions
> @@ -26,6 +26,7 @@ libc {
>      _dl_open_hook; _dl_open_hook2;
>      _dl_sym; _dl_vsym;
>      __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
> +    __libc_early_init;

OK.

>  
>      # Internal error handling support.  Interposes the functions in ld.so.
>      _dl_signal_exception; _dl_catch_exception;
> diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
> new file mode 100644
> index 0000000000..41e9ad9aad
> --- /dev/null
> +++ b/elf/dl-call-libc-early-init.c
> @@ -0,0 +1,41 @@
> +/* Invoke the early initialization function in libc.so.
> +   Copyright (C) 2020 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 <assert.h>
> +#include <ldsodefs.h>
> +#include <libc-early-init.h>
> +#include <link.h>
> +#include <stddef.h>
> +
> +void
> +_dl_call_libc_early_init (struct link_map *libc_map)
> +{
> +  /* There is nothing to do if we did not actually load libc.so.  */
> +  if (libc_map == NULL)
> +    return;

OK.

> +
> +  const ElfW(Sym) *sym
> +    = _dl_lookup_direct (libc_map, "__libc_early_init",
> +                         0x069682ac, /* dl_new_hash output.  */
> +                         "GLIBC_PRIVATE",
> +                         0x0963cf85); /* _dl_elf_hash output.  */

OK.

> +  assert (sym != NULL);
> +  __typeof (__libc_early_init) *early_init
> +    = DL_SYMBOL_ADDRESS (libc_map, sym);
> +  early_init ();

OK. Call.

> +}
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index a6b80f9395..06f2ba7264 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -30,6 +30,7 @@
>  #include <sys/param.h>
>  #include <sys/stat.h>
>  #include <sys/types.h>
> +#include <gnu/lib-names.h>
>  
>  /* Type for the buffer we put the ELF header and hopefully the program
>     header.  This buffer does not really have to be too large.  In most
> @@ -1374,6 +1375,14 @@ cannot enable executable stack as shared object requires");
>      add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
>  			    + l->l_info[DT_SONAME]->d_un.d_val));
>  
> +  /* If we have newly loaded libc.so, update the namespace
> +     description.  */
> +  if (GL(dl_ns)[nsid].libc_map == NULL
> +      && l->l_info[DT_SONAME] != NULL
> +      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
> +		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
> +    GL(dl_ns)[nsid].libc_map = l;

OK.

> +
>    /* _dl_close can only eventually undo the module ID assignment (via
>       remove_slotinfo) if this function returns a pointer to a link
>       map.  Therefore, delay this step until all possibilities for
> diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
> new file mode 100644
> index 0000000000..5637ae89de
> --- /dev/null
> +++ b/elf/dl-lookup-direct.c
> @@ -0,0 +1,116 @@
> +/* Look up a symbol in a single specified object.
> +   Copyright (C) 1995-2020 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 <string.h>
> +#include <elf_machine_sym_no_match.h>
> +#include <dl-hash.h>
> +
> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
> +   variant here is simplified because it requires symbol
> +   versioning.  */
> +static const ElfW(Sym) *
> +check_match (const struct link_map *const map, const char *const undef_name,
> +             const char *version, uint32_t version_hash,
> +             const Elf_Symndx symidx)
> +{
> +  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
> +  const ElfW(Sym) *sym = &symtab[symidx];
> +
> +  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
> +  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
> +                         && sym->st_shndx != SHN_ABS
> +                         && stt != STT_TLS)
> +                        || elf_machine_sym_no_match (sym)))
> +    return NULL;
> +
> +  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
> +     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
> +     code/data definitions.  */
> +#define ALLOWED_STT \
> +  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
> +   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
> +  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
> +    return NULL;
> +
> +  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
> +
> +  if (strcmp (strtab + sym->st_name, undef_name) != 0)
> +    /* Not the symbol we are looking for.  */
> +    return NULL;
> +
> +  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
> +  if (map->l_versions[ndx].hash != version_hash
> +      || strcmp (map->l_versions[ndx].name, version) != 0)
> +    /* It's not the version we want.  */
> +    return NULL;
> +
> +  return sym;
> +}

OK.

> +
> +
> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
> +   variant here is simplified because it does not search object
> +   dependencies.  It is optimized for a successful lookup.  */
> +const ElfW(Sym) *
> +_dl_lookup_direct (struct link_map *map,
> +                   const char *undef_name, uint32_t new_hash,
> +                   const char *version, uint32_t version_hash)
> +{
> +  const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
> +  if (__glibc_likely (bitmask != NULL))
> +    {
> +      Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
> +      if (bucket != 0)
> +        {
> +          const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
> +
> +          do
> +            if (((*hasharr ^ new_hash) >> 1) == 0)
> +              {
> +                Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
> +                const ElfW(Sym) *sym = check_match (map, undef_name,
> +                                                    version, version_hash,
> +                                                    symidx);
> +                if (sym != NULL)
> +                  return sym;
> +              }
> +          while ((*hasharr++ & 1u) == 0);
> +        }
> +    }
> +  else
> +    {
> +      /* Fallback code for lack of GNU_HASH support.  */
> +      uint32_t old_hash = _dl_elf_hash (undef_name);
> +
> +      /* Use the old SysV-style hash table.  Search the appropriate
> +         hash bucket in this object's symbol table for a definition
> +         for the same symbol name.  */
> +      for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
> +           symidx != STN_UNDEF;
> +           symidx = map->l_chain[symidx])
> +        {
> +          const ElfW(Sym) *sym = check_match (map, undef_name,
> +                                              version, version_hash, symidx);
> +          if (sym != NULL)
> +            return sym;
> +        }
> +    }
> +
> +  return NULL;
> +}

OK.

> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index d9fdb0bdce..86bc28e431 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -34,6 +34,7 @@
>  #include <atomic.h>
>  #include <libc-internal.h>
>  #include <array_length.h>
> +#include <libc-early-init.h>
>  
>  #include <dl-dst.h>
>  #include <dl-prop.h>
> @@ -57,6 +58,13 @@ struct dl_open_args
>       (non-negative).  */
>    unsigned int original_global_scope_pending_adds;
>  
> +  /* Set to true by dl_open_worker if libc.so was already loaded into
> +     the namespace at the time dl_open_worker was called.  This is
> +     used to determine whether libc.so early initialization has
> +     already been done before, and whether to roll back the cached
> +     libc_map value in the namespace in case of a dlopen failure.  */
> +  bool libc_already_loaded;

OK.

> +
>    /* Original parameters to the program and the current environment.  */
>    int argc;
>    char **argv;
> @@ -500,6 +508,11 @@ dl_open_worker (void *a)
>  	args->nsid = call_map->l_ns;
>      }
>  
> +  /* The namespace ID is now known.  Keep track of whether libc.so was
> +     already loaded, to determine whether it is necessary to call the
> +     early initialization routine (or clear libc_map on error).  */
> +  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;

OK.

> +
>    /* Retain the old value, so that it can be restored.  */
>    args->original_global_scope_pending_adds
>      = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
> @@ -734,6 +747,11 @@ dl_open_worker (void *a)
>    if (relocation_in_progress)
>      LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
>  
> +  /* If libc.so was not there before, attempt to call its early
> +     initialization routine.  */
> +  if (!args->libc_already_loaded)
> +    _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);

OK.

> +
>  #ifndef SHARED
>    DL_STATIC_INIT (new);
>  #endif
> @@ -823,6 +841,8 @@ no more namespaces available for dlmopen()"));
>    args.caller_dlopen = caller_dlopen;
>    args.map = NULL;
>    args.nsid = nsid;
> +  /* args.libc_already_loaded is always assigned by dl_open_worker
> +     (before any explicit/non-local returns).  */

OK. It acts like a return value in the struct to indicate load status.

>    args.argc = argc;
>    args.argv = argv;
>    args.env = env;
> @@ -851,6 +871,11 @@ no more namespaces available for dlmopen()"));
>    /* See if an error occurred during loading.  */
>    if (__glibc_unlikely (exception.errstring != NULL))
>      {
> +      /* Avoid keeping around a dangling reference to the libc.so link
> +	 map in case it has been cached in libc_map.  */
> +      if (!args.libc_already_loaded)
> +	GL(dl_ns)[nsid].libc_map = NULL;

OK. We check it here to clear the link map in the event of a failure that
happened while libc was being loaded.

This logic is clearer and looks correct to me.

> +
>        /* Remove the object from memory.  It may be in an inconsistent
>  	 state if relocation failed, for example.  */
>        if (args.map)
> diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
> new file mode 100644
> index 0000000000..5185fa8895
> --- /dev/null
> +++ b/elf/libc-early-init.h
> @@ -0,0 +1,35 @@
> +/* Early initialization of libc.so.
> +   Copyright (C) 2020 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/>.  */
> +
> +#ifndef _LIBC_EARLY_INIT_H
> +#define _LIBC_EARLY_INIT_H
> +
> +struct link_map;
> +
> +/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
> +   and call this function.  */
> +void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;

OK.

> +
> +/* In the shared case, this function is defined in libc.so and invoked
> +   from ld.so (or on the fist static dlopen) after complete relocation
> +   of a new loaded libc.so, but before user-defined ELF constructors
> +   run.  In the static case, this function is called directly from the
> +   startup code.  */
> +void __libc_early_init (void);

OK.

> +
> +#endif /* _LIBC_EARLY_INIT_H */
> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
> new file mode 100644
> index 0000000000..7f4ca332b8
> --- /dev/null
> +++ b/elf/libc_early_init.c
> @@ -0,0 +1,27 @@
> +/* Early initialization of libc.so, libc.so side.
> +   Copyright (C) 2020 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 <ctype.h>
> +#include <libc-early-init.h>
> +
> +void
> +__libc_early_init (void)
> +{
> +  /* Initialize ctype data.  */
> +  __ctype_init ();
> +}

OK. I like the procedural list of things to call.

> diff --git a/elf/rtld.c b/elf/rtld.c
> index b2ea21c98b..0016db86a7 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -46,6 +46,7 @@
>  #include <stackinfo.h>
>  #include <not-cancel.h>
>  #include <array_length.h>
> +#include <libc-early-init.h>
>  
>  #include <assert.h>
>  
> @@ -2372,6 +2373,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
>        rtld_timer_accum (&relocate_time, start);
>      }
>  
> +  /* Relocation is complete.  Perform early libc initialization.  */
> +  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);

OK.

> +
>    /* Do any necessary cleanups for the startup OS interface code.
>       We do these now so that no calls are made after rtld re-relocation
>       which might be resolved to different functions than we expect.
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 497938ffa2..5ff4a2831b 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -336,6 +336,10 @@ struct rtld_global
>         recursive dlopen calls from ELF constructors.  */
>      unsigned int _ns_global_scope_pending_adds;
>  
> +    /* Once libc.so has been loaded into the namespace, this points to
> +       its link map.  */
> +    struct link_map *libc_map;

OK.

> +
>      /* Search table for unique objects.  */
>      struct unique_sym_table
>      {
> @@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
>       attribute_hidden;
>  
>  
> +/* Restricted version of _dl_lookup_symbol_x.  Searches MAP (and only
> +   MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
> +   with dl_new_hash), symbol version VERSION, and symbol version hash
> +   VERSION_HASH (computed with _dl_elf_hash).  Returns a pointer to
> +   the symbol table entry in MAP on success, or NULL on failure.  MAP
> +   must have symbol versioning information, or otherwise the result is
> +   undefined.  */
> +const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
> +				    const char *undef_name,
> +				    uint32_t new_hash,
> +				    const char *version,
> +				    uint32_t version_hash) attribute_hidden;

OK.

> +
>  /* Add the new link_map NEW to the end of the namespace list.  */
>  extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
>       attribute_hidden;
> diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
> index 92bf45223f..a7dd4895d9 100644
> --- a/sysdeps/mach/hurd/i386/init-first.c
> +++ b/sysdeps/mach/hurd/i386/init-first.c
> @@ -17,7 +17,6 @@
>     <https://www.gnu.org/licenses/>.  */
>  
>  #include <assert.h>
> -#include <ctype.h>

OK.

>  #include <hurd.h>
>  #include <stdio.h>
>  #include <unistd.h>
> @@ -85,9 +84,6 @@ posixland_init (int argc, char **argv, char **envp)
>  #endif
>    __init_misc (argc, argv, envp);
>  
> -  /* Initialize ctype data.  */
> -  __ctype_init ();

OK.

> -
>  #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>    __libc_global_ctors ();
>  #endif
> 


-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098]
  2020-04-22 17:04   ` Carlos O'Donell
@ 2020-04-24 20:35     ` Florian Weimer
  2020-04-26 18:49       ` Carlos O'Donell
  2020-04-27 13:11       ` Adhemerval Zanella
  0 siblings, 2 replies; 63+ messages in thread
From: Florian Weimer @ 2020-04-24 20:35 UTC (permalink / raw)
  To: Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Carlos O'Donell, Joseph Myers

* Carlos O'Donell via Libc-alpha:

> Outstanding items for Florian:
>
> Why don't we remove parent_cancelhandling?
>
> Technically the patch looks correct, but I'd like to know about the
> removal of this variable. This descriptor is internal to glibc and
> opaque, and the length is not ABI, so we should be able to just remove
> it. What am I missing?

I was following this precedent:

  /* Ununsed.  */
  pid_t pid_ununsed;

I don't have a strong preference here.  It may make sense to collect a
couple of these changes and drop all of them together, along with the
_res removal.

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

* Re: [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098]
  2020-04-24 20:35     ` Florian Weimer
@ 2020-04-26 18:49       ` Carlos O'Donell
  2020-04-27 13:11       ` Adhemerval Zanella
  1 sibling, 0 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-26 18:49 UTC (permalink / raw)
  To: Florian Weimer, Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Joseph Myers

On 4/24/20 4:35 PM, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> Outstanding items for Florian:
>>
>> Why don't we remove parent_cancelhandling?
>>
>> Technically the patch looks correct, but I'd like to know about the
>> removal of this variable. This descriptor is internal to glibc and
>> opaque, and the length is not ABI, so we should be able to just remove
>> it. What am I missing?
> 
> I was following this precedent:
> 
>   /* Ununsed.  */
>   pid_t pid_ununsed;
> 
> I don't have a strong preference here.  It may make sense to collect a
> couple of these changes and drop all of them together, along with the
> _res removal.
> 

Thanks for the clarification. I thought this was the case.

OK for master.

Here is my sign-off for the patch.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-03-26 15:56 ` [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17) Mathieu Desnoyers
@ 2020-04-27  9:11   ` Florian Weimer
  2020-04-27 16:40     ` Mathieu Desnoyers
  2020-04-27 11:59   ` Florian Weimer
  1 sibling, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27  9:11 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul E. McKenney,
	Paul Turner, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> +* Support for automatically registering threads with the Linux rseq(2)
> +  system call has been added.  This system call is implemented starting
> +  from Linux 4.18.  The Restartable Sequences ABI accelerates user-space
> +  operations on per-cpu data.  It allows user-space to perform updates
> +  on per-cpu data without requiring heavy-weight atomic operations.
> +  Automatically registering threads allows all libraries, including libc,
> +  to make immediate use of the rseq(2) support by using the documented ABI.
> +  See 'man 2 rseq' for the details of the ABI shared between libc and the
> +  kernel.

This should refer documentation in the glibc manual.

(It is currently a glibc project requirement to add documentation for
new Linux interfaces, something that I do not necessarily agree with.)

>  
>  Deprecated and removed features, and other changes affecting compatibility:
>  
> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
> index 1ac66d895d..30466afea0 100644
> --- a/elf/libc_early_init.c
> +++ b/elf/libc_early_init.c
> @@ -18,10 +18,13 @@
>  
>  #include <ctype.h>
>  #include <libc-early-init.h>
> +#include <rseq-internal.h>
>  
>  void
>  __libc_early_init (void)
>  {
>    /* Initialize ctype data.  */
>    __ctype_init ();
> +  /* Register rseq ABI to the kernel.   */
> +  (void) rseq_register_current_thread ();
>  }

The cast to void should be removed (see below the comment about the
return type.

> diff --git a/manual/threads.texi b/manual/threads.texi
> index 0858ef8f92..59f634e432 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -9,8 +9,10 @@ This chapter describes functions used for managing threads.
>  POSIX threads.
>  
>  @menu
> -* ISO C Threads::	Threads based on the ISO C specification.
> -* POSIX Threads::	Threads based on the POSIX specification.
> +* ISO C Threads::		Threads based on the ISO C specification.
> +* POSIX Threads::		Threads based on the POSIX specification.
> +* Restartable Sequences::	Linux-specific Restartable Sequences
> +				integration.
>  @end menu
>  
>  
> @@ -881,3 +883,27 @@ Behaves like @code{pthread_timedjoin_np} except that the absolute time in
>  @c pthread_spin_unlock
>  @c pthread_testcancel
>  @c pthread_yield
> +
> +@node Restartable Sequences
> +@section Restartable Sequences
> +@cindex rseq
> +
> +This section describes @theglibc{} Restartable Sequences integration.
> +
> +@deftypevar {struct rseq} __rseq_abi
> +@standards{GNU, sys/rseq.h}
> +@Theglibc{} implements a @code{__rseq_abi} TLS symbol to interact with the
> +Restartable Sequences system call (Linux-specific).  The layout of this
> +structure is defined by the Linux kernel @file{linux/rseq.h} UAPI.
> +Registration of each thread's @code{__rseq_abi} is performed by
> +@theglibc{} at libc initialization and pthread creation.
> +@end deftypevar
> +
> +@deftypevr Macro int RSEQ_SIG
> +@standards{GNU, sys/rseq.h}
> +Each supported architecture provide a @code{RSEQ_SIG} macro in
> +@file{sys/rseq.h} which contains a signature.  That signature is expected to be
> +present in the code before each Restartable Sequences abort handler.  Failure
> +to provide the expected signature may terminate the process with a Segmentation
> +fault.
> +@end deftypevr

This should say Linux, not GNU as the standards source, given that the
interface is not added to the GNU ABI.

Is this sufficient documentation of this feature?  What do others
think about this?

> diff --git a/misc/rseq-internal.h b/misc/rseq-internal.h
> new file mode 100644
> index 0000000000..d564cf1bc3
> --- /dev/null
> +++ b/misc/rseq-internal.h
> @@ -0,0 +1,33 @@

> +static inline int
> +rseq_register_current_thread (void)
> +{
> +  return -1;
> +}

Nothing checks the return value of this function as far as I can see,
so it can return void.

> +static inline int
> +rseq_unregister_current_thread (void)
> +{
> +  return -1;
> +}

This function is unused.  This also applies to the full version.  I
believe we switched to implicit deregistration on thread exit, so I
think you can just remove it.

> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index afd379e89a..1ff248042e 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -33,6 +33,7 @@
>  #include <default-sched.h>
>  #include <futex-internal.h>
>  #include <tls-setup.h>
> +#include <rseq-internal.h>
>  #include "libioP.h"
>  
>  #include <shlib-compat.h>
> @@ -384,6 +385,9 @@ START_THREAD_DEFN
>    /* Initialize pointers to locale data.  */
>    __ctype_init ();
>  
> +  /* Register rseq TLS to the kernel. */
> +  (void) rseq_register_current_thread ();
> +

The cast can go.

>  #ifndef __ASSUME_SET_ROBUST_LIST
>    if (__set_robust_list_avail >= 0)
>  #endif
> @@ -578,6 +582,14 @@ START_THREAD_DEFN
>       process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
>       flag.  The 'tid' field in the TCB will be set to zero.
>  
> +     rseq TLS is still registered at this point. Rely on implicit unregistration
> +     performed by the kernel on thread teardown. This is not a problem because the
> +     rseq TLS lives on the stack, and the stack outlives the thread. If TCB
> +     allocation is ever changed, additional steps may be required, such as
> +     performing explicit rseq unregistration before reclaiming the rseq TLS area
> +     memory. It is NOT sufficient to block signals because the kernel may write
> +     to the rseq area even without signals.
> +
>       The exit code is zero since in case all threads exit by calling
>       'pthread_exit' the exit status must be 0 (zero).  */
>    __exit_thread ();

Some of these lines are too long.  Also two spaces after . at the end
of sentences.

> diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
> new file mode 100644
> index 0000000000..5f7f02f1ec
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/rseq-internal.h

> +static inline int
> +rseq_register_current_thread (void)
> +{
> +  int rc, ret = 0;
> +
> +  if (__rseq_abi.cpu_id == RSEQ_CPU_ID_REGISTRATION_FAILED)
> +    return -1;
> +  rc = INTERNAL_SYSCALL_CALL (rseq, &__rseq_abi, sizeof (struct rseq),
> +                              0, RSEQ_SIG);
> +  if (!rc)
> +    goto end;
> +  if (INTERNAL_SYSCALL_ERRNO (rc) != EBUSY)
> +    __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
> +  ret = -1;
> +end:
> +  return ret;
> +}

This does not seem to use INTERNAL_SYSCALL_CALL correctly.  I think
you need to use INTERNAL_SYSCALL_ERROR_P on the result to check for an
error, and only then use INTERNAL_SYSCALL_ERRNO to extract the error
code.

> diff --git a/sysdeps/unix/sysv/linux/rseq-sym.c b/sysdeps/unix/sysv/linux/rseq-sym.c
> new file mode 100644
> index 0000000000..0e33fab278
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/rseq-sym.c

> +#include <sys/syscall.h>
> +#include <stdint.h>
> +#include <kernel-features.h>
> +#include <sys/rseq.h>
> +
> +__thread struct rseq __rseq_abi = {
> +  .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
> +};

{ should go onto its own line.  I'd also add attribute_tls_model_ie,
also it's implied by the declaration in the header.

> diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
> new file mode 100644
> index 0000000000..503dce4cac
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sys/rseq.h
> @@ -0,0 +1,186 @@

I think there is some value in making this header compatible with
inclusion from the assembler (including constants for the relevant
struct offsets), but that can be a later change.

> +#ifndef _SYS_RSEQ_H
> +#define _SYS_RSEQ_H	1
> +
> +/* Architecture-specific rseq signature.  */
> +#include <bits/rseq.h>

Maybe add a newline between the above and the following, to make clear
the comment only applies to the first #include.

> +#include <stdint.h>
> +#include <sys/cdefs.h>
> +
> +#ifdef __has_include
> +# if __has_include ("linux/rseq.h")
> +#   define __GLIBC_HAVE_KERNEL_RSEQ
> +# endif
> +#else
> +# include <linux/version.h>
> +# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
> +#   define __GLIBC_HAVE_KERNEL_RSEQ
> +# endif
> +#endif
> +
> +#ifdef __GLIBC_HAVE_KERNEL_RSEQ
> +/* We use the structures declarations from the kernel headers.  */
> +# include <linux/rseq.h>
> +#else
> +/* We use a copy of the include/uapi/linux/rseq.h kernel header.  */
> +
> +#include <asm/byteorder.h>
> +
> +enum rseq_cpu_id_state
> +  {
> +    RSEQ_CPU_ID_UNINITIALIZED = -1,
> +    RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
> +  };
> +
> +enum rseq_flags
> +  {
> +    RSEQ_FLAG_UNREGISTER = (1 << 0),
> +  };
> +
> +enum rseq_cs_flags_bit
> +  {
> +    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
> +    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
> +    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
> +  };
> +
> +enum rseq_cs_flags
> +  {
> +    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
> +    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
> +    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
> +  };
> +
> +/* struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
> +   contained within a single cache-line. It is usually declared as
> +   link-time constant data.  */
> +struct rseq_cs
> +  {
> +    /* Version of this structure.  */
> +    uint32_t version;
> +    /* enum rseq_cs_flags.  */
> +    uint32_t flags;
> +    uint64_t start_ip;
> +    /* Offset from start_ip.  */
> +    uint64_t post_commit_offset;
> +    uint64_t abort_ip;
> +} __attribute__((aligned(4 * sizeof(uint64_t))));

The comment is wrong.  32-byte alignment does not put struct rseq_cs
on its own cache line on many (most?) CPUs.  Not using the constant 32
looks like unnecessary obfuscation to me.

I still think we should avoid the alignment.  The _ip fields should
perhaps be _pc (IP is more or less specific to x86).

{ and } are not aligned.  Please do not forget to add spaces before
opening parentheses, and two spaces after the . and the end of
sentences.  The opening { should always be on its own line.  (This
also applies to the definition of struct rseq below.)

> +
> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
> +   contained within a single cache-line.
> +
> +   A single struct rseq per thread is allowed.  */
> +struct rseq
> +  {
> +    /* Restartable sequences cpu_id_start field. Updated by the
> +       kernel. Read by user-space with single-copy atomicity
> +       semantics. This field should only be read by the thread which
> +       registered this data structure. Aligned on 32-bit. Always

What does “Aligned on 32-bit” mean in this context?  Do you mean to
reference 32-*byte* alignment here?

> +    /* Restartable sequences rseq_cs field.
> +
> +       Contains NULL when no critical section is active for the current
> +       thread, or holds a pointer to the currently active struct rseq_cs.
> +
> +       Updated by user-space, which sets the address of the currently
> +       active rseq_cs at the beginning of assembly instruction sequence
> +       block, and set to NULL by the kernel when it restarts an assembly
> +       instruction sequence block, as well as when the kernel detects that
> +       it is preempting or delivering a signal outside of the range
> +       targeted by the rseq_cs. Also needs to be set to NULL by user-space
> +       before reclaiming memory that contains the targeted struct rseq_cs.
> +
> +       Read and set by the kernel. Set by user-space with single-copy
> +       atomicity semantics. This field should only be updated by the
> +       thread which registered this data structure. Aligned on 64-bit.  */
> +    union {
> +      uint64_t ptr64;
> +#ifdef __LP64__
> +      uint64_t ptr;
> +#else
> +      struct {
> +#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN)
> +        uint32_t padding; /* Initialized to zero.  */
> +        uint32_t ptr32;
> +#else /* LITTLE */
> +        uint32_t ptr32;
> +        uint32_t padding; /* Initialized to zero.  */
> +#endif /* ENDIAN */
> +      } ptr;
> +#endif
> +    } rseq_cs;

Are these conditionals correct for x32?  Shouldn't there be a member
of type const struct rseq_cs * somewhere?

> diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
> new file mode 100644
> index 0000000000..75f52d9788
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
> @@ -0,0 +1,30 @@
> +/* Restartable Sequences Linux x86 architecture header.
> +   Copyright (C) 2019-2020 Free Software Foundation, Inc.

Please make sure that none of the new files reference the 2019 year.
It should be 2020, per GNU policy.

The patch needs some rebasing on top of current master.

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

* Re: [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7)
  2020-03-26 15:56 ` [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7) Mathieu Desnoyers
@ 2020-04-27  9:13   ` Florian Weimer
  0 siblings, 0 replies; 63+ messages in thread
From: Florian Weimer @ 2020-04-27  9:13 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, linux-api, Boqun Feng,
	Will Deacon, linux-kernel, Peter Zijlstra, Ben Maurer,
	Thomas Gleixner, Paul E. McKenney, Paul Turner, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c
> index c019cfb3cf..2269c4f2bd 100644
> --- a/sysdeps/unix/sysv/linux/sched_getcpu.c
> +++ b/sysdeps/unix/sysv/linux/sched_getcpu.c
> @@ -18,10 +18,15 @@
>  #include <errno.h>
>  #include <sched.h>
>  #include <sysdep.h>
> +#include <atomic.h>
>  #include <sysdep-vdso.h>
>  
> -int
> -sched_getcpu (void)
> +#ifdef HAVE_GETCPU_VSYSCALL
> +# define HAVE_VSYSCALL
> +#endif
> +
> +static int
> +vsyscall_sched_getcpu (void)
>  {
>    unsigned int cpu;
>    int r = -1;
> @@ -32,3 +37,21 @@ sched_getcpu (void)
>  #endif
>    return r == -1 ? r : cpu;
>  }
> +
> +#include <sys/rseq.h>
> +
> +#ifdef RSEQ_SIG
> +int
> +sched_getcpu (void)
> +{
> +  int cpu_id = atomic_load_relaxed (&__rseq_abi.cpu_id);
> +
> +  return cpu_id >= 0 ? cpu_id : vsyscall_sched_getcpu ();
> +}
> +#else
> +int
> +sched_getcpu (void)
> +{
> +  return vsyscall_sched_getcpu ();
> +}
> +#endif

This patch needs to be rebased on current master, but the direction
looks right to me.

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-03-26 15:56 ` [PATCH glibc 8/9] support: implement xpthread key create/delete (v4) Mathieu Desnoyers
@ 2020-04-27  9:17   ` Florian Weimer
  2020-04-27 14:58     ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27  9:17 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> diff --git a/support/xthread.h b/support/xthread.h
> index d350d1506d..2a519874bf 100644
> --- a/support/xthread.h
> +++ b/support/xthread.h
> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
> +void xpthread_key_delete (pthread_key_t key);

I think xpthread_key_create should return the pthread_key_t result
directly.  It's similar to what we did for xpthread_create.

Please also update for the year 2020.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-03-26 15:56 ` [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17) Mathieu Desnoyers
  2020-04-27  9:11   ` Florian Weimer
@ 2020-04-27 11:59   ` Florian Weimer
  2020-04-27 16:47     ` Mathieu Desnoyers
  1 sibling, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 11:59 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul E. McKenney,
	Paul Turner, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
> index 1ac66d895d..30466afea0 100644
> --- a/elf/libc_early_init.c
> +++ b/elf/libc_early_init.c
> @@ -18,10 +18,13 @@
>  
>  #include <ctype.h>
>  #include <libc-early-init.h>
> +#include <rseq-internal.h>
>  
>  void
>  __libc_early_init (void)
>  {
>    /* Initialize ctype data.  */
>    __ctype_init ();
> +  /* Register rseq ABI to the kernel.   */
> +  (void) rseq_register_current_thread ();
>  }

I think the registration must be restricted to the primary namespace.
Otherwise, LD_AUDIT will register the area to the secondary libc (in
the audit module), not the primary libc for the entire process.

I think the easiest way to implement this for now is a flag argument
for __libc_early_init (as the upstream __libc_multiple_libcs is not
entirely accurate).  I will submit a patch.

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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-24 20:18       ` Carlos O'Donell
@ 2020-04-27 12:43         ` Stefan Liebler
  2020-04-27 13:23           ` Florian Weimer
  2020-04-27 12:57         ` Adhemerval Zanella
  1 sibling, 1 reply; 63+ messages in thread
From: Stefan Liebler @ 2020-04-27 12:43 UTC (permalink / raw)
  To: libc-alpha

On 4/24/20 10:18 PM, Carlos O'Donell via Libc-alpha wrote:
> On 4/24/20 2:22 PM, Florian Weimer wrote:
>> * Carlos O'Donell via Libc-alpha:
>>
>>> Please clarify or remove the comment related to libc_already_loaded.
>>
>> I have removed the initialization.  It is no longer relevant in the
>> current patch.  It may have been obsoleted by other dl_open_worker
>> changes earlier.
> 
> Thanks!
> 
>> I fixed a few copyright years and one or two style issues.
>>
>> Tested on i686-linux-gnu and x86_64-linux-gnu.
>>
>> 8<------------------------------------------------------------------8<
>> Subject: [PATCH] elf: Implement __libc_early_init
>>
>> This function is defined in libc.so, and the dynamic loader calls
>> right after relocation has been finished, before any ELF constructors
>> or the preinit function is invoked.  It is also used in the static
>> build for initializing parts of the static libc.
>>
>> To locate __libc_early_init, a direct symbol lookup function is used,
>> _dl_lookup_direct.  It does not search the entire symbol scope and
>> consults merely a single link map.  This function could also be used
>> to implement lookups in the vDSO (as an optimization).
>>
>> A per-namespace variable (libc_map) is added for locating libc.so,
>> to avoid repeated traversals of the search scope.  It is similar to
>> GL(dl_initfirst).  An alternative would have been to thread a context
>> argument from _dl_open down to _dl_map_object_from_fd (where libc.so
>> is identified).  This could have avoided the global variable, but
>> the change would be larger as a result.  It would not have been
>> possible to use this to replace GL(dl_initfirst) because that global
>> variable is used to pass the function pointer past the stack switch
>> from dl_main to the main program.  Replacing that requires adding
>> a new argument to _dl_init, which in turn needs changes to the
>> architecture-specific libc.so startup code written in assembler.
>>
>> __libc_early_init should not be used to replace _dl_var_init (as
>> it exists today on some architectures).  Instead, _dl_lookup_direct
>> should be used to look up a new variable symbol in libc.so, and
>> that should then be initialized from the dynamic loader, immediately
>> after the object has been loaded in _dl_map_object_from_fd (before
>> relocation is run).  This way, more IFUNC resolvers which depend on
>> these variables will work.
> 
> OK for master.
> 
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> 
>> -----
>>   csu/init-first.c                    |   4 --
>>   csu/libc-start.c                    |   5 ++
>>   elf/Makefile                        |   5 +-
>>   elf/Versions                        |   1 +
>>   elf/dl-call-libc-early-init.c       |  41 +++++++++++++
>>   elf/dl-load.c                       |   9 +++
>>   elf/dl-lookup-direct.c              | 116 ++++++++++++++++++++++++++++++++++++
>>   elf/dl-open.c                       |  25 ++++++++
>>   elf/libc-early-init.h               |  35 +++++++++++
>>   elf/libc_early_init.c               |  27 +++++++++
>>   elf/rtld.c                          |   4 ++
>>   sysdeps/generic/ldsodefs.h          |  17 ++++++
>>   sysdeps/mach/hurd/i386/init-first.c |   4 --
>>   13 files changed, 283 insertions(+), 10 deletions(-)
>>
>> diff --git a/csu/init-first.c b/csu/init-first.c
>> index 264e6f348d..d214af7116 100644
>> --- a/csu/init-first.c
>> +++ b/csu/init-first.c
>> @@ -16,7 +16,6 @@
>>      License along with the GNU C Library; if not, see
>>      <https://www.gnu.org/licenses/>.  */
>>   
>> -#include <ctype.h>
>>   #include <stdio.h>
>>   #include <stdlib.h>
>>   #include <fcntl.h>
>> @@ -75,9 +74,6 @@ _init_first (int argc, char **argv, char **envp)
>>   
>>     __init_misc (argc, argv, envp);
>>   
>> -  /* Initialize ctype data.  */
>> -  __ctype_init ();
> 
> OK.
> 
>> -
>>   #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>>     __libc_global_ctors ();
>>   #endif
>> diff --git a/csu/libc-start.c b/csu/libc-start.c
>> index 12468c5a89..ccc743c9d1 100644
>> --- a/csu/libc-start.c
>> +++ b/csu/libc-start.c
>> @@ -22,6 +22,7 @@
>>   #include <ldsodefs.h>
>>   #include <exit-thread.h>
>>   #include <libc-internal.h>
>> +#include <elf/libc-early-init.h>
> 
> OK.
> 
>>   
>>   #include <elf/dl-tunables.h>
>>   
>> @@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
>>       __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
>>   
>>   #ifndef SHARED
>> +  /* Perform early initialization.  In the shared case, this function
>> +     is called from the dynamic loader as early as possible.  */
>> +  __libc_early_init ();
>> +
> 
> OK.
> 
>>     /* Call the initializer of the libc.  This is only needed here if we
>>        are compiling for the static library in which case we haven't
>>        run the constructors in `_dl_start_user'.  */
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 6919e53c14..77da61ae64 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -25,7 +25,7 @@ headers		= elf.h bits/elfclass.h link.h bits/link.h
>>   routines	= $(all-dl-routines) dl-support dl-iteratephdr \
>>   		  dl-addr dl-addr-obj enbl-secure dl-profstub \
>>   		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
>> -		  dl-reloc-static-pie
>> +		  dl-reloc-static-pie libc_early_init
> 
> OK.
> 
>>   
>>   # The core dynamic linking functions are in libc for the static and
>>   # profiled libraries.
>> @@ -33,7 +33,8 @@ dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
>>   				  runtime init fini debug misc \
>>   				  version profile tls origin scope \
>>   				  execstack open close trampoline \
>> -				  exception sort-maps)
>> +				  exception sort-maps lookup-direct \
>> +				  call-libc-early-init)
> 
> OK.
> 
>>   ifeq (yes,$(use-ldconfig))
>>   dl-routines += dl-cache
>>   endif
>> diff --git a/elf/Versions b/elf/Versions
>> index 705489fc51..3be879c4ad 100644
>> --- a/elf/Versions
>> +++ b/elf/Versions
>> @@ -26,6 +26,7 @@ libc {
>>       _dl_open_hook; _dl_open_hook2;
>>       _dl_sym; _dl_vsym;
>>       __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
>> +    __libc_early_init;
> 
> OK.
> 
>>   
>>       # Internal error handling support.  Interposes the functions in ld.so.
>>       _dl_signal_exception; _dl_catch_exception;
>> diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
>> new file mode 100644
>> index 0000000000..41e9ad9aad
>> --- /dev/null
>> +++ b/elf/dl-call-libc-early-init.c
>> @@ -0,0 +1,41 @@
>> +/* Invoke the early initialization function in libc.so.
>> +   Copyright (C) 2020 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 <assert.h>
>> +#include <ldsodefs.h>
>> +#include <libc-early-init.h>
>> +#include <link.h>
>> +#include <stddef.h>
>> +
>> +void
>> +_dl_call_libc_early_init (struct link_map *libc_map)
>> +{
>> +  /* There is nothing to do if we did not actually load libc.so.  */
>> +  if (libc_map == NULL)
>> +    return;
> 
> OK.
> 
>> +
>> +  const ElfW(Sym) *sym
>> +    = _dl_lookup_direct (libc_map, "__libc_early_init",
>> +                         0x069682ac, /* dl_new_hash output.  */
>> +                         "GLIBC_PRIVATE",
>> +                         0x0963cf85); /* _dl_elf_hash output.  */
> 
> OK.
> 
>> +  assert (sym != NULL);
>> +  __typeof (__libc_early_init) *early_init
>> +    = DL_SYMBOL_ADDRESS (libc_map, sym);
>> +  early_init ();
> 
> OK. Call.
> 
>> +}
>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>> index a6b80f9395..06f2ba7264 100644
>> --- a/elf/dl-load.c
>> +++ b/elf/dl-load.c
>> @@ -30,6 +30,7 @@
>>   #include <sys/param.h>
>>   #include <sys/stat.h>
>>   #include <sys/types.h>
>> +#include <gnu/lib-names.h>
>>   
>>   /* Type for the buffer we put the ELF header and hopefully the program
>>      header.  This buffer does not really have to be too large.  In most
>> @@ -1374,6 +1375,14 @@ cannot enable executable stack as shared object requires");
>>       add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
>>   			    + l->l_info[DT_SONAME]->d_un.d_val));
>>   
>> +  /* If we have newly loaded libc.so, update the namespace
>> +     description.  */
>> +  if (GL(dl_ns)[nsid].libc_map == NULL
>> +      && l->l_info[DT_SONAME] != NULL
>> +      && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
>> +		  + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
>> +    GL(dl_ns)[nsid].libc_map = l;
> 
> OK.
> 
>> +
>>     /* _dl_close can only eventually undo the module ID assignment (via
>>        remove_slotinfo) if this function returns a pointer to a link
>>        map.  Therefore, delay this step until all possibilities for
>> diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
>> new file mode 100644
>> index 0000000000..5637ae89de
>> --- /dev/null
>> +++ b/elf/dl-lookup-direct.c
>> @@ -0,0 +1,116 @@
>> +/* Look up a symbol in a single specified object.
>> +   Copyright (C) 1995-2020 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 <string.h>
>> +#include <elf_machine_sym_no_match.h>
>> +#include <dl-hash.h>
>> +
>> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
>> +   variant here is simplified because it requires symbol
>> +   versioning.  */
>> +static const ElfW(Sym) *
>> +check_match (const struct link_map *const map, const char *const undef_name,
>> +             const char *version, uint32_t version_hash,
>> +             const Elf_Symndx symidx)
>> +{
>> +  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
>> +  const ElfW(Sym) *sym = &symtab[symidx];
>> +
>> +  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
>> +  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
>> +                         && sym->st_shndx != SHN_ABS
>> +                         && stt != STT_TLS)
>> +                        || elf_machine_sym_no_match (sym)))
>> +    return NULL;
>> +
>> +  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
>> +     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
>> +     code/data definitions.  */
>> +#define ALLOWED_STT \
>> +  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
>> +   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
>> +  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
>> +    return NULL;
>> +
>> +  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
>> +
>> +  if (strcmp (strtab + sym->st_name, undef_name) != 0)
>> +    /* Not the symbol we are looking for.  */
>> +    return NULL;
>> +
>> +  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
>> +  if (map->l_versions[ndx].hash != version_hash
>> +      || strcmp (map->l_versions[ndx].name, version) != 0)
>> +    /* It's not the version we want.  */
>> +    return NULL;
>> +
>> +  return sym;
>> +}
> 
> OK.
> 
>> +
>> +
>> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
>> +   variant here is simplified because it does not search object
>> +   dependencies.  It is optimized for a successful lookup.  */
>> +const ElfW(Sym) *
>> +_dl_lookup_direct (struct link_map *map,
>> +                   const char *undef_name, uint32_t new_hash,
>> +                   const char *version, uint32_t version_hash)
>> +{
>> +  const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
>> +  if (__glibc_likely (bitmask != NULL))
>> +    {
>> +      Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
>> +      if (bucket != 0)
>> +        {
>> +          const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
>> +
>> +          do
>> +            if (((*hasharr ^ new_hash) >> 1) == 0)
>> +              {
>> +                Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
>> +                const ElfW(Sym) *sym = check_match (map, undef_name,
>> +                                                    version, version_hash,
>> +                                                    symidx);
>> +                if (sym != NULL)
>> +                  return sym;
>> +              }
>> +          while ((*hasharr++ & 1u) == 0);
>> +        }
>> +    }
>> +  else
>> +    {
>> +      /* Fallback code for lack of GNU_HASH support.  */
>> +      uint32_t old_hash = _dl_elf_hash (undef_name);
>> +
>> +      /* Use the old SysV-style hash table.  Search the appropriate
>> +         hash bucket in this object's symbol table for a definition
>> +         for the same symbol name.  */
>> +      for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
>> +           symidx != STN_UNDEF;
>> +           symidx = map->l_chain[symidx])
>> +        {
>> +          const ElfW(Sym) *sym = check_match (map, undef_name,
>> +                                              version, version_hash, symidx);
>> +          if (sym != NULL)
>> +            return sym;
>> +        }
>> +    }
>> +
>> +  return NULL;
>> +}
> 
> OK.
> 
>> diff --git a/elf/dl-open.c b/elf/dl-open.c
>> index d9fdb0bdce..86bc28e431 100644
>> --- a/elf/dl-open.c
>> +++ b/elf/dl-open.c
>> @@ -34,6 +34,7 @@
>>   #include <atomic.h>
>>   #include <libc-internal.h>
>>   #include <array_length.h>
>> +#include <libc-early-init.h>
>>   
>>   #include <dl-dst.h>
>>   #include <dl-prop.h>
>> @@ -57,6 +58,13 @@ struct dl_open_args
>>        (non-negative).  */
>>     unsigned int original_global_scope_pending_adds;
>>   
>> +  /* Set to true by dl_open_worker if libc.so was already loaded into
>> +     the namespace at the time dl_open_worker was called.  This is
>> +     used to determine whether libc.so early initialization has
>> +     already been done before, and whether to roll back the cached
>> +     libc_map value in the namespace in case of a dlopen failure.  */
>> +  bool libc_already_loaded;
> 
> OK.
> 
>> +
>>     /* Original parameters to the program and the current environment.  */
>>     int argc;
>>     char **argv;
>> @@ -500,6 +508,11 @@ dl_open_worker (void *a)
>>   	args->nsid = call_map->l_ns;
>>       }
>>   
>> +  /* The namespace ID is now known.  Keep track of whether libc.so was
>> +     already loaded, to determine whether it is necessary to call the
>> +     early initialization routine (or clear libc_map on error).  */
>> +  args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
> 
> OK.
> 
>> +
>>     /* Retain the old value, so that it can be restored.  */
>>     args->original_global_scope_pending_adds
>>       = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
>> @@ -734,6 +747,11 @@ dl_open_worker (void *a)
>>     if (relocation_in_progress)
>>       LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
>>   
>> +  /* If libc.so was not there before, attempt to call its early
>> +     initialization routine.  */
>> +  if (!args->libc_already_loaded)
>> +    _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);
> 
> OK.
> 
>> +
>>   #ifndef SHARED
>>     DL_STATIC_INIT (new);
>>   #endif
>> @@ -823,6 +841,8 @@ no more namespaces available for dlmopen()"));
>>     args.caller_dlopen = caller_dlopen;
>>     args.map = NULL;
>>     args.nsid = nsid;
>> +  /* args.libc_already_loaded is always assigned by dl_open_worker
>> +     (before any explicit/non-local returns).  */
> 
> OK. It acts like a return value in the struct to indicate load status.
> 
>>     args.argc = argc;
>>     args.argv = argv;
>>     args.env = env;
>> @@ -851,6 +871,11 @@ no more namespaces available for dlmopen()"));
>>     /* See if an error occurred during loading.  */
>>     if (__glibc_unlikely (exception.errstring != NULL))
>>       {
>> +      /* Avoid keeping around a dangling reference to the libc.so link
>> +	 map in case it has been cached in libc_map.  */
>> +      if (!args.libc_already_loaded)
>> +	GL(dl_ns)[nsid].libc_map = NULL;
> 
> OK. We check it here to clear the link map in the event of a failure that
> happened while libc was being loaded.
> 
> This logic is clearer and looks correct to me.
> 
>> +
>>         /* Remove the object from memory.  It may be in an inconsistent
>>   	 state if relocation failed, for example.  */
>>         if (args.map)
>> diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
>> new file mode 100644
>> index 0000000000..5185fa8895
>> --- /dev/null
>> +++ b/elf/libc-early-init.h
>> @@ -0,0 +1,35 @@
>> +/* Early initialization of libc.so.
>> +   Copyright (C) 2020 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/>.  */
>> +
>> +#ifndef _LIBC_EARLY_INIT_H
>> +#define _LIBC_EARLY_INIT_H
>> +
>> +struct link_map;
>> +
>> +/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
>> +   and call this function.  */
>> +void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
> 
> OK.
> 
>> +
>> +/* In the shared case, this function is defined in libc.so and invoked
>> +   from ld.so (or on the fist static dlopen) after complete relocation
>> +   of a new loaded libc.so, but before user-defined ELF constructors
>> +   run.  In the static case, this function is called directly from the
>> +   startup code.  */
>> +void __libc_early_init (void);
> 
> OK.
> 
>> +
>> +#endif /* _LIBC_EARLY_INIT_H */
>> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
>> new file mode 100644
>> index 0000000000..7f4ca332b8
>> --- /dev/null
>> +++ b/elf/libc_early_init.c
>> @@ -0,0 +1,27 @@
>> +/* Early initialization of libc.so, libc.so side.
>> +   Copyright (C) 2020 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 <ctype.h>
>> +#include <libc-early-init.h>
>> +
>> +void
>> +__libc_early_init (void)
>> +{
>> +  /* Initialize ctype data.  */
>> +  __ctype_init ();
>> +}
> 
> OK. I like the procedural list of things to call.
> 
>> diff --git a/elf/rtld.c b/elf/rtld.c
>> index b2ea21c98b..0016db86a7 100644
>> --- a/elf/rtld.c
>> +++ b/elf/rtld.c
>> @@ -46,6 +46,7 @@
>>   #include <stackinfo.h>
>>   #include <not-cancel.h>
>>   #include <array_length.h>
>> +#include <libc-early-init.h>
>>   
>>   #include <assert.h>
>>   
>> @@ -2372,6 +2373,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
>>         rtld_timer_accum (&relocate_time, start);
>>       }
>>   
>> +  /* Relocation is complete.  Perform early libc initialization.  */
>> +  _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);
> 
> OK.
> 
>> +
>>     /* Do any necessary cleanups for the startup OS interface code.
>>        We do these now so that no calls are made after rtld re-relocation
>>        which might be resolved to different functions than we expect.
>> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
>> index 497938ffa2..5ff4a2831b 100644
>> --- a/sysdeps/generic/ldsodefs.h
>> +++ b/sysdeps/generic/ldsodefs.h
>> @@ -336,6 +336,10 @@ struct rtld_global
>>          recursive dlopen calls from ELF constructors.  */
>>       unsigned int _ns_global_scope_pending_adds;
>>   
>> +    /* Once libc.so has been loaded into the namespace, this points to
>> +       its link map.  */
>> +    struct link_map *libc_map;
> 
> OK.
> 
>> +
>>       /* Search table for unique objects.  */
>>       struct unique_sym_table
>>       {
>> @@ -946,6 +950,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
>>        attribute_hidden;
>>   
>>   
>> +/* Restricted version of _dl_lookup_symbol_x.  Searches MAP (and only
>> +   MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
>> +   with dl_new_hash), symbol version VERSION, and symbol version hash
>> +   VERSION_HASH (computed with _dl_elf_hash).  Returns a pointer to
>> +   the symbol table entry in MAP on success, or NULL on failure.  MAP
>> +   must have symbol versioning information, or otherwise the result is
>> +   undefined.  */
>> +const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
>> +				    const char *undef_name,
>> +				    uint32_t new_hash,
>> +				    const char *version,
>> +				    uint32_t version_hash) attribute_hidden;
> 
> OK.
> 
>> +
>>   /* Add the new link_map NEW to the end of the namespace list.  */
>>   extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
>>        attribute_hidden;
>> diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
>> index 92bf45223f..a7dd4895d9 100644
>> --- a/sysdeps/mach/hurd/i386/init-first.c
>> +++ b/sysdeps/mach/hurd/i386/init-first.c
>> @@ -17,7 +17,6 @@
>>      <https://www.gnu.org/licenses/>.  */
>>   
>>   #include <assert.h>
>> -#include <ctype.h>
> 
> OK.
> 
>>   #include <hurd.h>
>>   #include <stdio.h>
>>   #include <unistd.h>
>> @@ -85,9 +84,6 @@ posixland_init (int argc, char **argv, char **envp)
>>   #endif
>>     __init_misc (argc, argv, envp);
>>   
>> -  /* Initialize ctype data.  */
>> -  __ctype_init ();
> 
> OK.
> 
>> -
>>   #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
>>     __libc_global_ctors ();
>>   #endif
>>
> 
> 

Hi Florian,

I've observed a test fail (make xcheck) with this commit on x86_64/s390x:

nptl/tst-setuid1-static: dl-call-libc-early-init.c:37: 
_dl_call_libc_early_init: Assertion `sym != NULL' failed.
Didn't expect signal from child: got `Aborted'

Have you already seen this?

Bye,
Stefan


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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-24 20:18       ` Carlos O'Donell
  2020-04-27 12:43         ` Stefan Liebler
@ 2020-04-27 12:57         ` Adhemerval Zanella
  2020-04-27 20:35           ` Carlos O'Donell
  1 sibling, 1 reply; 63+ messages in thread
From: Adhemerval Zanella @ 2020-04-27 12:57 UTC (permalink / raw)
  To: Carlos O'Donell, Florian Weimer, Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Joseph Myers



On 24/04/2020 17:18, Carlos O'Donell via Libc-alpha wrote:
> On 4/24/20 2:22 PM, Florian Weimer wrote:
>> * Carlos O'Donell via Libc-alpha:
>>
>>> Please clarify or remove the comment related to libc_already_loaded.
>>
>> I have removed the initialization.  It is no longer relevant in the
>> current patch.  It may have been obsoleted by other dl_open_worker
>> changes earlier.
> 
> Thanks!
[...]
>> diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
>> new file mode 100644
>> index 0000000000..5637ae89de
>> --- /dev/null
>> +++ b/elf/dl-lookup-direct.c
>> @@ -0,0 +1,116 @@
>> +/* Look up a symbol in a single specified object.
>> +   Copyright (C) 1995-2020 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 <string.h>
>> +#include <elf_machine_sym_no_match.h>
>> +#include <dl-hash.h>
>> +
>> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
>> +   variant here is simplified because it requires symbol
>> +   versioning.  */
>> +static const ElfW(Sym) *
>> +check_match (const struct link_map *const map, const char *const undef_name,
>> +             const char *version, uint32_t version_hash,
>> +             const Elf_Symndx symidx)
>> +{
>> +  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
>> +  const ElfW(Sym) *sym = &symtab[symidx];
>> +
>> +  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
>> +  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
>> +                         && sym->st_shndx != SHN_ABS
>> +                         && stt != STT_TLS)
>> +                        || elf_machine_sym_no_match (sym)))
>> +    return NULL;
>> +
>> +  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
>> +     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
>> +     code/data definitions.  */
>> +#define ALLOWED_STT \
>> +  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
>> +   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
>> +  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
>> +    return NULL;
>> +
>> +  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
>> +
>> +  if (strcmp (strtab + sym->st_name, undef_name) != 0)
>> +    /* Not the symbol we are looking for.  */
>> +    return NULL;
>> +
>> +  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
>> +  if (map->l_versions[ndx].hash != version_hash
>> +      || strcmp (map->l_versions[ndx].name, version) != 0)
>> +    /* It's not the version we want.  */
>> +    return NULL;
>> +
>> +  return sym;
>> +}
> 
> OK.

The only reservation I have with this change it this code duplication,
could we refactor to have this patch in a common place?

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

* Re: [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098]
  2020-04-24 20:35     ` Florian Weimer
  2020-04-26 18:49       ` Carlos O'Donell
@ 2020-04-27 13:11       ` Adhemerval Zanella
  1 sibling, 0 replies; 63+ messages in thread
From: Adhemerval Zanella @ 2020-04-27 13:11 UTC (permalink / raw)
  To: libc-alpha



On 24/04/2020 17:35, Florian Weimer wrote:
> * Carlos O'Donell via Libc-alpha:
> 
>> Outstanding items for Florian:
>>
>> Why don't we remove parent_cancelhandling?
>>
>> Technically the patch looks correct, but I'd like to know about the
>> removal of this variable. This descriptor is internal to glibc and
>> opaque, and the length is not ABI, so we should be able to just remove
>> it. What am I missing?
> 
> I was following this precedent:
> 
>   /* Ununsed.  */
>   pid_t pid_ununsed;
> 
> I don't have a strong preference here.  It may make sense to collect a
> couple of these changes and drop all of them together, along with the
> _res removal.
> 

I have added this to try minimize the sanitizer requirement to handle
different struct pthread sizes (and yes, it is a ABI abuse).  But now
I am not sure if this is worth, since we already handle the ABI specific
bits in tcbhead_t. 

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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-27 12:43         ` Stefan Liebler
@ 2020-04-27 13:23           ` Florian Weimer
  2020-04-27 16:23             ` Stefan Liebler
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 13:23 UTC (permalink / raw)
  To: Stefan Liebler via Libc-alpha; +Cc: Stefan Liebler

* Stefan Liebler via Libc-alpha:

> I've observed a test fail (make xcheck) with this commit on x86_64/s390x:
>
> nptl/tst-setuid1-static: dl-call-libc-early-init.c:37: 
> _dl_call_libc_early_init: Assertion `sym != NULL' failed.
> Didn't expect signal from child: got `Aborted'
>
> Have you already seen this?

I have not.  Does this patch fix the failure for you?

The system libc does not yet have __libc_early_init, so it cannot be
loaded by the new, statically linked dlopen.

8<------------------------------------------------------------------8<
Subject: nptl/tst-setuid1-static: Improve isolation from system objects

Static dlopen needs an LD_LIBRARY_PATH setting to avoid loading system
libraries.

-----
 nptl/Makefile | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/nptl/Makefile b/nptl/Makefile
index 33fa03807e..ef9a6eb561 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -714,6 +714,11 @@ tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
 
 CFLAGS-tst-unwind-thread.c += -funwind-tables
 
+# The test uses dlopen indirectly and would otherwise load system
+# objects.
+tst-setuid1-static-ENV = \
+  LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
+
 # The tests here better do not run in parallel.
 ifeq ($(run-built-tests),yes)
 ifneq ($(filter %tests,$(MAKECMDGOALS)),)

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-04-27  9:17   ` Florian Weimer
@ 2020-04-27 14:58     ` Mathieu Desnoyers
  2020-04-27 15:23       ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 14:58 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, carlos, Joseph Myers

----- On Apr 27, 2020, at 5:17 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> diff --git a/support/xthread.h b/support/xthread.h
>> index d350d1506d..2a519874bf 100644
>> --- a/support/xthread.h
>> +++ b/support/xthread.h
>> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
>> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
>> +void xpthread_key_delete (pthread_key_t key);
> 
> I think xpthread_key_create should return the pthread_key_t result
> directly.  It's similar to what we did for xpthread_create.

Good point, done.

> 
> Please also update for the year 2020.

OK,

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-04-27 14:58     ` Mathieu Desnoyers
@ 2020-04-27 15:23       ` Florian Weimer
  2020-04-27 15:34         ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 15:23 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha; +Cc: Mathieu Desnoyers, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> ----- On Apr 27, 2020, at 5:17 AM, Florian Weimer fw@deneb.enyo.de wrote:
>
>> * Mathieu Desnoyers via Libc-alpha:
>> 
>>> diff --git a/support/xthread.h b/support/xthread.h
>>> index d350d1506d..2a519874bf 100644
>>> --- a/support/xthread.h
>>> +++ b/support/xthread.h
>>> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>>>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>>>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>>>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
>>> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
>>> +void xpthread_key_delete (pthread_key_t key);
>> 
>> I think xpthread_key_create should return the pthread_key_t result
>> directly.  It's similar to what we did for xpthread_create.
>
> Good point, done.

If you post a new patch, we can install it right now.

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-04-27 15:23       ` Florian Weimer
@ 2020-04-27 15:34         ` Mathieu Desnoyers
  2020-04-27 17:00           ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 15:34 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, Joseph Myers

----- On Apr 27, 2020, at 11:23 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> ----- On Apr 27, 2020, at 5:17 AM, Florian Weimer fw@deneb.enyo.de wrote:
>>
>>> * Mathieu Desnoyers via Libc-alpha:
>>> 
>>>> diff --git a/support/xthread.h b/support/xthread.h
>>>> index d350d1506d..2a519874bf 100644
>>>> --- a/support/xthread.h
>>>> +++ b/support/xthread.h
>>>> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>>>>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>>>>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>>>>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
>>>> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
>>>> +void xpthread_key_delete (pthread_key_t key);
>>> 
>>> I think xpthread_key_create should return the pthread_key_t result
>>> directly.  It's similar to what we did for xpthread_create.
>>
>> Good point, done.
> 
> If you post a new patch, we can install it right now.

I expect I'll be able to do a new round of post (including this patch)
later today.

Thanks!

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-27 13:23           ` Florian Weimer
@ 2020-04-27 16:23             ` Stefan Liebler
  2020-04-27 16:38               ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Stefan Liebler @ 2020-04-27 16:23 UTC (permalink / raw)
  To: Florian Weimer, Stefan Liebler via Libc-alpha

On 4/27/20 3:23 PM, Florian Weimer wrote:
> * Stefan Liebler via Libc-alpha:
> 
>> I've observed a test fail (make xcheck) with this commit on x86_64/s390x:
>>
>> nptl/tst-setuid1-static: dl-call-libc-early-init.c:37:
>> _dl_call_libc_early_init: Assertion `sym != NULL' failed.
>> Didn't expect signal from child: got `Aborted'
>>
>> Have you already seen this?
> 
> I have not.  Does this patch fix the failure for you?
yes. This fixes the failure for me.
Thanks.
> 
> The system libc does not yet have __libc_early_init, so it cannot be
> loaded by the new, statically linked dlopen.
> 
> 8<------------------------------------------------------------------8<
> Subject: nptl/tst-setuid1-static: Improve isolation from system objects
> 
> Static dlopen needs an LD_LIBRARY_PATH setting to avoid loading system
> libraries.
> 
> -----
>   nptl/Makefile | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/nptl/Makefile b/nptl/Makefile
> index 33fa03807e..ef9a6eb561 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -714,6 +714,11 @@ tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so
>   
>   CFLAGS-tst-unwind-thread.c += -funwind-tables
>   
> +# The test uses dlopen indirectly and would otherwise load system
> +# objects.
> +tst-setuid1-static-ENV = \
> +  LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
> +
>   # The tests here better do not run in parallel.
>   ifeq ($(run-built-tests),yes)
>   ifneq ($(filter %tests,$(MAKECMDGOALS)),)
> 


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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-27 16:23             ` Stefan Liebler
@ 2020-04-27 16:38               ` Florian Weimer
  0 siblings, 0 replies; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 16:38 UTC (permalink / raw)
  To: Stefan Liebler; +Cc: Stefan Liebler via Libc-alpha

* Stefan Liebler:

> On 4/27/20 3:23 PM, Florian Weimer wrote:
>> * Stefan Liebler via Libc-alpha:
>> 
>>> I've observed a test fail (make xcheck) with this commit on x86_64/s390x:
>>>
>>> nptl/tst-setuid1-static: dl-call-libc-early-init.c:37:
>>> _dl_call_libc_early_init: Assertion `sym != NULL' failed.
>>> Didn't expect signal from child: got `Aborted'
>>>
>>> Have you already seen this?
>> 
>> I have not.  Does this patch fix the failure for you?

> yes. This fixes the failure for me.

Thanks, I've pushed it.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27  9:11   ` Florian Weimer
@ 2020-04-27 16:40     ` Mathieu Desnoyers
  2020-04-27 16:54       ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 16:40 UTC (permalink / raw)
  To: Florian Weimer, Michael Kerrisk
  Cc: libc-alpha, carlos, Rich Felker, linux-api, Boqun Feng,
	Will Deacon, linux-kernel, Peter Zijlstra, Ben Maurer,
	Dave Watson, Thomas Gleixner, Paul, Paul Turner, Joseph Myers,
	Szabolcs Nagy

----- On Apr 27, 2020, at 5:11 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> +* Support for automatically registering threads with the Linux rseq(2)
>> +  system call has been added.  This system call is implemented starting
>> +  from Linux 4.18.  The Restartable Sequences ABI accelerates user-space
>> +  operations on per-cpu data.  It allows user-space to perform updates
>> +  on per-cpu data without requiring heavy-weight atomic operations.
>> +  Automatically registering threads allows all libraries, including libc,
>> +  to make immediate use of the rseq(2) support by using the documented ABI.
>> +  See 'man 2 rseq' for the details of the ABI shared between libc and the
>> +  kernel.
> 
> This should refer documentation in the glibc manual.
> 
> (It is currently a glibc project requirement to add documentation for
> new Linux interfaces, something that I do not necessarily agree with.)

A related issue here is that editing of the rseq(2) man pages has been stalled
since March 2019. I have been waiting for reply from Michael Kerrisk, and I
suspect he might have be side-tracked by other projects. I just bumped that
thread.

Ref.: https://lore.kernel.org/r/211707091.921.1551722548347.JavaMail.zimbra@efficios.com

So as of today, "man 2 rseq" does not exist in the kernel man pages, so I
suggest we remove that sentence. Would the following change be OK with you ?

-  See 'man 2 rseq' for the details of the ABI shared between libc and the
-  kernel.
+  The GNU C Library manual has details on integration of Restartable
+  Sequences.

> 
>>  
>>  Deprecated and removed features, and other changes affecting compatibility:
>>  
>> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
>> index 1ac66d895d..30466afea0 100644
>> --- a/elf/libc_early_init.c
>> +++ b/elf/libc_early_init.c
>> @@ -18,10 +18,13 @@
>>  
>>  #include <ctype.h>
>>  #include <libc-early-init.h>
>> +#include <rseq-internal.h>
>>  
>>  void
>>  __libc_early_init (void)
>>  {
>>    /* Initialize ctype data.  */
>>    __ctype_init ();
>> +  /* Register rseq ABI to the kernel.   */
>> +  (void) rseq_register_current_thread ();
>>  }
> 
> The cast to void should be removed (see below the comment about the
> return type.

OK

> 
>> diff --git a/manual/threads.texi b/manual/threads.texi
>> index 0858ef8f92..59f634e432 100644
>> --- a/manual/threads.texi
>> +++ b/manual/threads.texi
>> @@ -9,8 +9,10 @@ This chapter describes functions used for managing threads.
>>  POSIX threads.
>>  
>>  @menu
>> -* ISO C Threads::	Threads based on the ISO C specification.
>> -* POSIX Threads::	Threads based on the POSIX specification.
>> +* ISO C Threads::		Threads based on the ISO C specification.
>> +* POSIX Threads::		Threads based on the POSIX specification.
>> +* Restartable Sequences::	Linux-specific Restartable Sequences
>> +				integration.
>>  @end menu
>>  
>>  
>> @@ -881,3 +883,27 @@ Behaves like @code{pthread_timedjoin_np} except that the
>> absolute time in
>>  @c pthread_spin_unlock
>>  @c pthread_testcancel
>>  @c pthread_yield
>> +
>> +@node Restartable Sequences
>> +@section Restartable Sequences
>> +@cindex rseq
>> +
>> +This section describes @theglibc{} Restartable Sequences integration.
>> +
>> +@deftypevar {struct rseq} __rseq_abi
>> +@standards{GNU, sys/rseq.h}
>> +@Theglibc{} implements a @code{__rseq_abi} TLS symbol to interact with the
>> +Restartable Sequences system call (Linux-specific).  The layout of this
>> +structure is defined by the Linux kernel @file{linux/rseq.h} UAPI.
>> +Registration of each thread's @code{__rseq_abi} is performed by
>> +@theglibc{} at libc initialization and pthread creation.
>> +@end deftypevar
>> +
>> +@deftypevr Macro int RSEQ_SIG
>> +@standards{GNU, sys/rseq.h}
>> +Each supported architecture provide a @code{RSEQ_SIG} macro in
>> +@file{sys/rseq.h} which contains a signature.  That signature is expected to be
>> +present in the code before each Restartable Sequences abort handler.  Failure
>> +to provide the expected signature may terminate the process with a Segmentation
>> +fault.
>> +@end deftypevr
> 
> This should say Linux, not GNU as the standards source, given that the
> interface is not added to the GNU ABI.

Good point, done.

> 
> Is this sufficient documentation of this feature?  What do others
> think about this?

I'll leave this question to others.

> 
>> diff --git a/misc/rseq-internal.h b/misc/rseq-internal.h
>> new file mode 100644
>> index 0000000000..d564cf1bc3
>> --- /dev/null
>> +++ b/misc/rseq-internal.h
>> @@ -0,0 +1,33 @@
> 
>> +static inline int
>> +rseq_register_current_thread (void)
>> +{
>> +  return -1;
>> +}
> 
> Nothing checks the return value of this function as far as I can see,
> so it can return void.

OK

> 
>> +static inline int
>> +rseq_unregister_current_thread (void)
>> +{
>> +  return -1;
>> +}
> 
> This function is unused.  This also applies to the full version.  I
> believe we switched to implicit deregistration on thread exit, so I
> think you can just remove it.

OK

> 
>> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
>> index afd379e89a..1ff248042e 100644
>> --- a/nptl/pthread_create.c
>> +++ b/nptl/pthread_create.c
>> @@ -33,6 +33,7 @@
>>  #include <default-sched.h>
>>  #include <futex-internal.h>
>>  #include <tls-setup.h>
>> +#include <rseq-internal.h>
>>  #include "libioP.h"
>>  
>>  #include <shlib-compat.h>
>> @@ -384,6 +385,9 @@ START_THREAD_DEFN
>>    /* Initialize pointers to locale data.  */
>>    __ctype_init ();
>>  
>> +  /* Register rseq TLS to the kernel. */
>> +  (void) rseq_register_current_thread ();
>> +
> 
> The cast can go.

OK

> 
>>  #ifndef __ASSUME_SET_ROBUST_LIST
>>    if (__set_robust_list_avail >= 0)
>>  #endif
>> @@ -578,6 +582,14 @@ START_THREAD_DEFN
>>       process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
>>       flag.  The 'tid' field in the TCB will be set to zero.
>>  
>> +     rseq TLS is still registered at this point. Rely on implicit
>> unregistration
>> +     performed by the kernel on thread teardown. This is not a problem because
>> the
>> +     rseq TLS lives on the stack, and the stack outlives the thread. If TCB
>> +     allocation is ever changed, additional steps may be required, such as
>> +     performing explicit rseq unregistration before reclaiming the rseq TLS
>> area
>> +     memory. It is NOT sufficient to block signals because the kernel may write
>> +     to the rseq area even without signals.
>> +
>>       The exit code is zero since in case all threads exit by calling
>>       'pthread_exit' the exit status must be 0 (zero).  */
>>    __exit_thread ();
> 
> Some of these lines are too long.  Also two spaces after . at the end
> of sentences.

OK

> 
>> diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h
>> b/sysdeps/unix/sysv/linux/rseq-internal.h
>> new file mode 100644
>> index 0000000000..5f7f02f1ec
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/rseq-internal.h
> 
>> +static inline int
>> +rseq_register_current_thread (void)
>> +{
>> +  int rc, ret = 0;
>> +
>> +  if (__rseq_abi.cpu_id == RSEQ_CPU_ID_REGISTRATION_FAILED)
>> +    return -1;
>> +  rc = INTERNAL_SYSCALL_CALL (rseq, &__rseq_abi, sizeof (struct rseq),
>> +                              0, RSEQ_SIG);
>> +  if (!rc)
>> +    goto end;
>> +  if (INTERNAL_SYSCALL_ERRNO (rc) != EBUSY)
>> +    __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
>> +  ret = -1;
>> +end:
>> +  return ret;
>> +}
> 
> This does not seem to use INTERNAL_SYSCALL_CALL correctly.  I think
> you need to use INTERNAL_SYSCALL_ERROR_P on the result to check for an
> error, and only then use INTERNAL_SYSCALL_ERRNO to extract the error
> code.

OK

> 
>> diff --git a/sysdeps/unix/sysv/linux/rseq-sym.c
>> b/sysdeps/unix/sysv/linux/rseq-sym.c
>> new file mode 100644
>> index 0000000000..0e33fab278
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/rseq-sym.c
> 
>> +#include <sys/syscall.h>
>> +#include <stdint.h>
>> +#include <kernel-features.h>
>> +#include <sys/rseq.h>
>> +
>> +__thread struct rseq __rseq_abi = {
>> +  .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
>> +};
> 
> { should go onto its own line.

OK

> I'd also add attribute_tls_model_ie,
> also it's implied by the declaration in the header.

This contradicts feedback I received from Szabolcs Nagy in September 2019:

https://public-inbox.org/libc-alpha/c58d4d6e-f22a-f5d9-e23a-5bd72cec1a86@arm.com/

"note that libpthread.so is built with -ftls-model=initial-exec

(and if it wasn't then you'd want to put the attribute on the
declaration in the internal header file, not on the definition,
so the actual tls accesses generate the right code)"

In the context of his feedback, __rseq_abi was defined within nptl/pthread_create.c.
It is now defined in sysdeps/unix/sysv/linux/rseq-sym.c, which is built into the
csu which AFAIU ends up in libc.so. His comment still applies though, because
libc.so is also built with -ftls-model=initial-exec.

So should I apply the "initial-exec" TLS model only to the __rseq_abi
declaration, or is it preferred to apply it to both the declaration
and the definition ?

> 
>> diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h
>> b/sysdeps/unix/sysv/linux/sys/rseq.h
>> new file mode 100644
>> index 0000000000..503dce4cac
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/sys/rseq.h
>> @@ -0,0 +1,186 @@
> 
> I think there is some value in making this header compatible with
> inclusion from the assembler (including constants for the relevant
> struct offsets), but that can be a later change.

Agreed. By "later", do you mean before merging the patch, between
merge of the patch and next glibc release, or for a subsequent glibc
release ?

> 
>> +#ifndef _SYS_RSEQ_H
>> +#define _SYS_RSEQ_H	1
>> +
>> +/* Architecture-specific rseq signature.  */
>> +#include <bits/rseq.h>
> 
> Maybe add a newline between the above and the following, to make clear
> the comment only applies to the first #include.

OK

> 
>> +#include <stdint.h>
>> +#include <sys/cdefs.h>
>> +
>> +#ifdef __has_include
>> +# if __has_include ("linux/rseq.h")
>> +#   define __GLIBC_HAVE_KERNEL_RSEQ
>> +# endif
>> +#else
>> +# include <linux/version.h>
>> +# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
>> +#   define __GLIBC_HAVE_KERNEL_RSEQ
>> +# endif
>> +#endif
>> +
>> +#ifdef __GLIBC_HAVE_KERNEL_RSEQ
>> +/* We use the structures declarations from the kernel headers.  */
>> +# include <linux/rseq.h>
>> +#else
>> +/* We use a copy of the include/uapi/linux/rseq.h kernel header.  */
>> +
>> +#include <asm/byteorder.h>
>> +
>> +enum rseq_cpu_id_state
>> +  {
>> +    RSEQ_CPU_ID_UNINITIALIZED = -1,
>> +    RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
>> +  };
>> +
>> +enum rseq_flags
>> +  {
>> +    RSEQ_FLAG_UNREGISTER = (1 << 0),
>> +  };
>> +
>> +enum rseq_cs_flags_bit
>> +  {
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
>> +  };
>> +
>> +enum rseq_cs_flags
>> +  {
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
>> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
>> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
>> +    RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
>> +      (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
>> +  };
>> +
>> +/* struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
>> +   contained within a single cache-line. It is usually declared as
>> +   link-time constant data.  */
>> +struct rseq_cs
>> +  {
>> +    /* Version of this structure.  */
>> +    uint32_t version;
>> +    /* enum rseq_cs_flags.  */
>> +    uint32_t flags;
>> +    uint64_t start_ip;
>> +    /* Offset from start_ip.  */
>> +    uint64_t post_commit_offset;
>> +    uint64_t abort_ip;
>> +} __attribute__((aligned(4 * sizeof(uint64_t))));
> 
> The comment is wrong.  32-byte alignment does not put struct rseq_cs
> on its own cache line on many (most?) CPUs.  Not using the constant 32
> looks like unnecessary obfuscation to me.

There is a difference between "being contained within a single cache-line"
and "being the only structure in a cache-line". The objective here is the
former.

For instance, if we do not enforce any minimum alignment, the compiler could
decide to align that structure on __alignof__(uint64_t) which happens to be
4 bytes on some architectures. This can cause this frequently accessed structure
to be sitting across 2 cache-lines, thus requiring the CPU to load two cache
lines rather than one very frequently.

I think what you have in mind is "being the only structure in a cache-line",
which is useful to eliminate false-sharing. However, considering that this is
a TLS variable, we don't care about false-sharing, because it is never meant
to be updated concurrently by many threads or CPUs.

So I think my comment is correct.

I agree that the constant 32 may be clearer here. I will change to align(32).

> I still think we should avoid the alignment.  The _ip fields should
> perhaps be _pc (IP is more or less specific to x86).

I am concerned that removing an alignment attribute which is exposed
in a public Linux UAPI header can be an ABI breakage.

I am also concerned about changing field names for fields already
exposed in a public Linux UAPI header, especially if the change is
only for cosmetic reasons.

> 
> { and } are not aligned.  Please do not forget to add spaces before
> opening parentheses, and two spaces after the . and the end of
> sentences.  The opening { should always be on its own line.  (This
> also applies to the definition of struct rseq below.)

OK. Old coding style habits die hard ;)

> 
>> +
>> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
>> +   contained within a single cache-line.
>> +
>> +   A single struct rseq per thread is allowed.  */
>> +struct rseq
>> +  {
>> +    /* Restartable sequences cpu_id_start field. Updated by the
>> +       kernel. Read by user-space with single-copy atomicity
>> +       semantics. This field should only be read by the thread which
>> +       registered this data structure. Aligned on 32-bit. Always
> 
> What does “Aligned on 32-bit” mean in this context?  Do you mean to
> reference 32-*byte* alignment here?

No. I really mean 32-bit (4-byte). Being aligned on 32-byte guarantees that
this field is aligned at least on 4-byte. This is required by single-copy
atomicity semantics.

Should I update this comment to state "Aligned on 4-byte" instead ?

> 
>> +    /* Restartable sequences rseq_cs field.
>> +
>> +       Contains NULL when no critical section is active for the current
>> +       thread, or holds a pointer to the currently active struct rseq_cs.
>> +
>> +       Updated by user-space, which sets the address of the currently
>> +       active rseq_cs at the beginning of assembly instruction sequence
>> +       block, and set to NULL by the kernel when it restarts an assembly
>> +       instruction sequence block, as well as when the kernel detects that
>> +       it is preempting or delivering a signal outside of the range
>> +       targeted by the rseq_cs. Also needs to be set to NULL by user-space
>> +       before reclaiming memory that contains the targeted struct rseq_cs.
>> +
>> +       Read and set by the kernel. Set by user-space with single-copy
>> +       atomicity semantics. This field should only be updated by the
>> +       thread which registered this data structure. Aligned on 64-bit.  */
>> +    union {
>> +      uint64_t ptr64;
>> +#ifdef __LP64__
>> +      uint64_t ptr;
>> +#else
>> +      struct {
>> +#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) ||
>> defined(__BIG_ENDIAN)
>> +        uint32_t padding; /* Initialized to zero.  */
>> +        uint32_t ptr32;
>> +#else /* LITTLE */
>> +        uint32_t ptr32;
>> +        uint32_t padding; /* Initialized to zero.  */
>> +#endif /* ENDIAN */
>> +      } ptr;
>> +#endif
>> +    } rseq_cs;
> 
> Are these conditionals correct for x32?

Let's see. With x86 gcc:

-m64: (__x86_64__ && __LP64__)
-m32: (__i386__)
-mx32: (__x86_64__ && __ILP32__)

So with "#ifdef __LP64__" we specifically target 64-bit pointers. The rest
falls into the "else" case, which expects 32-bit pointers. Considering that
x32 has 32-bit pointers, I don't see any issue here.

> Shouldn't there be a member of type const struct rseq_cs * somewhere?

Having pointers within structures in kernel UAPI headers is frowned upon. Indeed
here having it in the union could possibly make some use-cases easier in
user-space, so I'm open to it. It basically depends on how much we want the
Linux UAPI header and the glibc header to stay in sync, and if other kernel
maintainers are open to this addition.

We don't mind that user-space uses that pointer, but we never want the kernel
to touch that pointer rather than the 32/64-bit-aware fields. One possibility
would be to do:

    union
      {
        uint64_t ptr64;
#ifdef __LP64__
        uint64_t ptr;
#else
        struct
          {
#if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
            uint32_t padding; /* Initialized to zero.  */
            uint32_t ptr32;
#else /* LITTLE */
            uint32_t ptr32;
            uint32_t padding; /* Initialized to zero.  */
#endif /* ENDIAN */
          } ptr;
#endif

#ifndef __KERNEL__
     const struct rseq_cs *uptr;
#endif
      } rseq_cs;

in the union, so only user-space can see that field. Thoughts ?

> 
>> diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h
>> b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
>> new file mode 100644
>> index 0000000000..75f52d9788
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
>> @@ -0,0 +1,30 @@
>> +/* Restartable Sequences Linux x86 architecture header.
>> +   Copyright (C) 2019-2020 Free Software Foundation, Inc.
> 
> Please make sure that none of the new files reference the 2019 year.
> It should be 2020, per GNU policy.

OK

> 
> The patch needs some rebasing on top of current master.

Done.

Thanks for the review!

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 11:59   ` Florian Weimer
@ 2020-04-27 16:47     ` Mathieu Desnoyers
  2020-04-27 16:59       ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 16:47 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, Carlos O'Donell, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers

----- On Apr 27, 2020, at 7:59 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
>> index 1ac66d895d..30466afea0 100644
>> --- a/elf/libc_early_init.c
>> +++ b/elf/libc_early_init.c
>> @@ -18,10 +18,13 @@
>>  
>>  #include <ctype.h>
>>  #include <libc-early-init.h>
>> +#include <rseq-internal.h>
>>  
>>  void
>>  __libc_early_init (void)
>>  {
>>    /* Initialize ctype data.  */
>>    __ctype_init ();
>> +  /* Register rseq ABI to the kernel.   */
>> +  (void) rseq_register_current_thread ();
>>  }
> 
> I think the registration must be restricted to the primary namespace.
> Otherwise, LD_AUDIT will register the area to the secondary libc (in
> the audit module), not the primary libc for the entire process.
> 
> I think the easiest way to implement this for now is a flag argument
> for __libc_early_init (as the upstream __libc_multiple_libcs is not
> entirely accurate).  I will submit a patch.

OK, once I get the patch, I will pick it up in my series.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 16:40     ` Mathieu Desnoyers
@ 2020-04-27 16:54       ` Florian Weimer
  2020-04-27 17:26         ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 16:54 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

* Mathieu Desnoyers:

>>> +#include <sys/syscall.h>
>>> +#include <stdint.h>
>>> +#include <kernel-features.h>
>>> +#include <sys/rseq.h>
>>> +
>>> +__thread struct rseq __rseq_abi = {
>>> +  .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
>>> +};
>> 
>> { should go onto its own line.
>
> OK
>
>> I'd also add attribute_tls_model_ie,
>> also it's implied by the declaration in the header.
>
> This contradicts feedback I received from Szabolcs Nagy in September 2019:
>
> https://public-inbox.org/libc-alpha/c58d4d6e-f22a-f5d9-e23a-5bd72cec1a86@arm.com/
>
> "note that libpthread.so is built with -ftls-model=initial-exec
>
> (and if it wasn't then you'd want to put the attribute on the
> declaration in the internal header file, not on the definition,
> so the actual tls accesses generate the right code)"
>
> In the context of his feedback, __rseq_abi was defined within nptl/pthread_create.c.
> It is now defined in sysdeps/unix/sysv/linux/rseq-sym.c, which is built into the
> csu which AFAIU ends up in libc.so. His comment still applies though, because
> libc.so is also built with -ftls-model=initial-exec.
>
> So should I apply the "initial-exec" TLS model only to the __rseq_abi
> declaration, or is it preferred to apply it to both the declaration
> and the definition ?

I do not have a strong preference here.  Technically, the declaration
in the header file should be enough.

>>> diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h
>>> b/sysdeps/unix/sysv/linux/sys/rseq.h
>>> new file mode 100644
>>> index 0000000000..503dce4cac
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/sys/rseq.h
>>> @@ -0,0 +1,186 @@
>> 
>> I think there is some value in making this header compatible with
>> inclusion from the assembler (including constants for the relevant
>> struct offsets), but that can be a later change.
>
> Agreed. By "later", do you mean before merging the patch, between
> merge of the patch and next glibc release, or for a subsequent glibc
> release ?

It can happen some time after merging the patch, preferably for this
release.  But I don't think it's release-critical.

>>> +/* struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
>>> +   contained within a single cache-line. It is usually declared as
>>> +   link-time constant data.  */
>>> +struct rseq_cs
>>> +  {
>>> +    /* Version of this structure.  */
>>> +    uint32_t version;
>>> +    /* enum rseq_cs_flags.  */
>>> +    uint32_t flags;
>>> +    uint64_t start_ip;
>>> +    /* Offset from start_ip.  */
>>> +    uint64_t post_commit_offset;
>>> +    uint64_t abort_ip;
>>> +} __attribute__((aligned(4 * sizeof(uint64_t))));
>> 
>> The comment is wrong.  32-byte alignment does not put struct rseq_cs
>> on its own cache line on many (most?) CPUs.  Not using the constant 32
>> looks like unnecessary obfuscation to me.
>
> There is a difference between "being contained within a single cache-line"
> and "being the only structure in a cache-line". The objective here is the
> former.

Fair enough.

> I agree that the constant 32 may be clearer here. I will change to align(32).

With a space, please. 8-)

>>> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
>>> +   contained within a single cache-line.
>>> +
>>> +   A single struct rseq per thread is allowed.  */
>>> +struct rseq
>>> +  {
>>> +    /* Restartable sequences cpu_id_start field. Updated by the
>>> +       kernel. Read by user-space with single-copy atomicity
>>> +       semantics. This field should only be read by the thread which
>>> +       registered this data structure. Aligned on 32-bit. Always
>> 
>> What does “Aligned on 32-bit” mean in this context?  Do you mean to
>> reference 32-*byte* alignment here?
>
> No. I really mean 32-bit (4-byte). Being aligned on 32-byte guarantees that
> this field is aligned at least on 4-byte. This is required by single-copy
> atomicity semantics.
>
> Should I update this comment to state "Aligned on 4-byte" instead ?

I think this is implied by all Linux ABIs.  And the explicit alignment
specification for struct rseq makes the alignment 32 bytes.

>>> +    /* Restartable sequences rseq_cs field.
>>> +
>>> +       Contains NULL when no critical section is active for the current
>>> +       thread, or holds a pointer to the currently active struct rseq_cs.
>>> +
>>> +       Updated by user-space, which sets the address of the currently
>>> +       active rseq_cs at the beginning of assembly instruction sequence
>>> +       block, and set to NULL by the kernel when it restarts an assembly
>>> +       instruction sequence block, as well as when the kernel detects that
>>> +       it is preempting or delivering a signal outside of the range
>>> +       targeted by the rseq_cs. Also needs to be set to NULL by user-space
>>> +       before reclaiming memory that contains the targeted struct rseq_cs.
>>> +
>>> +       Read and set by the kernel. Set by user-space with single-copy
>>> +       atomicity semantics. This field should only be updated by the
>>> +       thread which registered this data structure. Aligned on 64-bit.  */
>>> +    union {
>>> +      uint64_t ptr64;
>>> +#ifdef __LP64__
>>> +      uint64_t ptr;
>>> +#else
>>> +      struct {
>>> +#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) ||
>>> defined(__BIG_ENDIAN)
>>> +        uint32_t padding; /* Initialized to zero.  */
>>> +        uint32_t ptr32;
>>> +#else /* LITTLE */
>>> +        uint32_t ptr32;
>>> +        uint32_t padding; /* Initialized to zero.  */
>>> +#endif /* ENDIAN */
>>> +      } ptr;
>>> +#endif
>>> +    } rseq_cs;
>> 
>> Are these conditionals correct for x32?
>
> Let's see. With x86 gcc:
>
> -m64: (__x86_64__ && __LP64__)
> -m32: (__i386__)
> -mx32: (__x86_64__ && __ILP32__)
>
> So with "#ifdef __LP64__" we specifically target 64-bit pointers. The rest
> falls into the "else" case, which expects 32-bit pointers. Considering that
> x32 has 32-bit pointers, I don't see any issue here.

Does the kernel have a separate 32-bit entry point for rseq on x32?
If not, it will expect the 64-bit struct layout.

> We don't mind that user-space uses that pointer, but we never want the kernel
> to touch that pointer rather than the 32/64-bit-aware fields. One possibility
> would be to do:
>
>     union
>       {
>         uint64_t ptr64;
> #ifdef __LP64__
>         uint64_t ptr;
> #else
>         struct
>           {
> #if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
>             uint32_t padding; /* Initialized to zero.  */
>             uint32_t ptr32;
> #else /* LITTLE */
>             uint32_t ptr32;
>             uint32_t padding; /* Initialized to zero.  */
> #endif /* ENDIAN */
>           } ptr;
> #endif
>
> #ifndef __KERNEL__
>      const struct rseq_cs *uptr;
> #endif
>       } rseq_cs;
>
> in the union, so only user-space can see that field. Thoughts ?

I think this depends on where the x32 question lands.

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

* Re: [PATCH glibc 9/9] rseq registration tests (v9)
  2020-03-26 15:56 ` [PATCH glibc 9/9] rseq registration tests (v9) Mathieu Desnoyers
@ 2020-04-27 16:55   ` Florian Weimer
  2020-04-27 17:48     ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 16:55 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, Boqun Feng, Will Deacon,
	Peter Zijlstra, Ben Maurer, Thomas Gleixner, Paul E. McKenney,
	Paul Turner, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> These tests validate that rseq is registered from various execution
> contexts (main thread, constructor, destructor, other threads, other
> threads created from constructor and destructor, forked process
> (without exec), pthread_atfork handlers, pthread setspecific
> destructors, C++ thread and process destructors, signal handlers,
> atexit handlers).
>
> tst-rseq.c only links against libc.so, testing registration of rseq in
> a non-multithreaded environment.
>
> tst-rseq-nptl.c also links against libpthread.so, testing registration
> of rseq in a multithreaded environment.

I suggest to split the fork-in-constructor test case off from the
other tests, so that the majority of tests can go in independently of
what we do with the support_record_failure initialization code.

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

* Re: [PATCH glibc 7/9] support record failure: allow use from constructor
  2020-03-26 15:56 ` [PATCH glibc 7/9] support record failure: allow use from constructor Mathieu Desnoyers
@ 2020-04-27 16:58   ` Florian Weimer
  2020-04-27 17:49     ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 16:58 UTC (permalink / raw)
  To: Mathieu Desnoyers via Libc-alpha
  Cc: Carlos O'Donell, Mathieu Desnoyers, Joseph Myers

* Mathieu Desnoyers via Libc-alpha:

> Expose support_record_failure_init () so constructors can explicitly
> initialize the record failure API.
>
> This is preferred to lazy initialization at first use, because
> lazy initialization does not cover use in constructors within
> forked children processes (forked from parent constructor).

My intent behind lazy initialization was that it avoids perturbing the
address space until the first failure.  This is supposed to make the
test harness more compatible.

A test in the constructor completely breaks major assumptions in the
old test skeleton (and those were carried over into the current test
framework).  In general, if a test involves constructors, we tend to
avoid using the test harness at all.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 16:47     ` Mathieu Desnoyers
@ 2020-04-27 16:59       ` Florian Weimer
  0 siblings, 0 replies; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 16:59 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: libc-alpha, Carlos O'Donell, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers

* Mathieu Desnoyers:

> ----- On Apr 27, 2020, at 7:59 AM, Florian Weimer fw@deneb.enyo.de wrote:
>
>> * Mathieu Desnoyers via Libc-alpha:
>> 
>>> diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
>>> index 1ac66d895d..30466afea0 100644
>>> --- a/elf/libc_early_init.c
>>> +++ b/elf/libc_early_init.c
>>> @@ -18,10 +18,13 @@
>>>  
>>>  #include <ctype.h>
>>>  #include <libc-early-init.h>
>>> +#include <rseq-internal.h>
>>>  
>>>  void
>>>  __libc_early_init (void)
>>>  {
>>>    /* Initialize ctype data.  */
>>>    __ctype_init ();
>>> +  /* Register rseq ABI to the kernel.   */
>>> +  (void) rseq_register_current_thread ();
>>>  }
>> 
>> I think the registration must be restricted to the primary namespace.
>> Otherwise, LD_AUDIT will register the area to the secondary libc (in
>> the audit module), not the primary libc for the entire process.
>> 
>> I think the easiest way to implement this for now is a flag argument
>> for __libc_early_init (as the upstream __libc_multiple_libcs is not
>> entirely accurate).  I will submit a patch.
>
> OK, once I get the patch, I will pick it up in my series.

There should be no need for that, it can be reviewed and committed
separately:

  <https://sourceware.org/pipermail/libc-alpha/2020-April/113182.html>

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-04-27 15:34         ` Mathieu Desnoyers
@ 2020-04-27 17:00           ` Florian Weimer
  2020-04-27 17:30             ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-27 17:00 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: libc-alpha, Joseph Myers

* Mathieu Desnoyers:

> ----- On Apr 27, 2020, at 11:23 AM, Florian Weimer fw@deneb.enyo.de wrote:
>
>> * Mathieu Desnoyers via Libc-alpha:
>> 
>>> ----- On Apr 27, 2020, at 5:17 AM, Florian Weimer fw@deneb.enyo.de wrote:
>>>
>>>> * Mathieu Desnoyers via Libc-alpha:
>>>> 
>>>>> diff --git a/support/xthread.h b/support/xthread.h
>>>>> index d350d1506d..2a519874bf 100644
>>>>> --- a/support/xthread.h
>>>>> +++ b/support/xthread.h
>>>>> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>>>>>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>>>>>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>>>>>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
>>>>> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
>>>>> +void xpthread_key_delete (pthread_key_t key);
>>>> 
>>>> I think xpthread_key_create should return the pthread_key_t result
>>>> directly.  It's similar to what we did for xpthread_create.
>>>
>>> Good point, done.
>> 
>> If you post a new patch, we can install it right now.
>
> I expect I'll be able to do a new round of post (including this patch)
> later today.

Please submit it separately, so that we can commit it and remove it
from the series.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 16:54       ` Florian Weimer
@ 2020-04-27 17:26         ` Mathieu Desnoyers
  2020-04-27 20:27           ` Mathieu Desnoyers
  2020-04-28 12:02           ` Florian Weimer
  0 siblings, 2 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 17:26 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy



----- On Apr 27, 2020, at 12:54 PM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers:
> 
>>>> +#include <sys/syscall.h>
>>>> +#include <stdint.h>
>>>> +#include <kernel-features.h>
>>>> +#include <sys/rseq.h>
>>>> +
>>>> +__thread struct rseq __rseq_abi = {
>>>> +  .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
>>>> +};
>>> 
>>> { should go onto its own line.
>>
>> OK
>>
>>> I'd also add attribute_tls_model_ie,
>>> also it's implied by the declaration in the header.
>>
>> This contradicts feedback I received from Szabolcs Nagy in September 2019:
>>
>> https://public-inbox.org/libc-alpha/c58d4d6e-f22a-f5d9-e23a-5bd72cec1a86@arm.com/
>>
>> "note that libpthread.so is built with -ftls-model=initial-exec
>>
>> (and if it wasn't then you'd want to put the attribute on the
>> declaration in the internal header file, not on the definition,
>> so the actual tls accesses generate the right code)"
>>
>> In the context of his feedback, __rseq_abi was defined within
>> nptl/pthread_create.c.
>> It is now defined in sysdeps/unix/sysv/linux/rseq-sym.c, which is built into the
>> csu which AFAIU ends up in libc.so. His comment still applies though, because
>> libc.so is also built with -ftls-model=initial-exec.
>>
>> So should I apply the "initial-exec" TLS model only to the __rseq_abi
>> declaration, or is it preferred to apply it to both the declaration
>> and the definition ?
> 
> I do not have a strong preference here.  Technically, the declaration
> in the header file should be enough.

OK, so I'll just keep the attribute on the declaration in the header.

> 
>>>> diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h
>>>> b/sysdeps/unix/sysv/linux/sys/rseq.h
>>>> new file mode 100644
>>>> index 0000000000..503dce4cac
>>>> --- /dev/null
>>>> +++ b/sysdeps/unix/sysv/linux/sys/rseq.h
>>>> @@ -0,0 +1,186 @@
>>> 
>>> I think there is some value in making this header compatible with
>>> inclusion from the assembler (including constants for the relevant
>>> struct offsets), but that can be a later change.
>>
>> Agreed. By "later", do you mean before merging the patch, between
>> merge of the patch and next glibc release, or for a subsequent glibc
>> release ?
> 
> It can happen some time after merging the patch, preferably for this
> release.  But I don't think it's release-critical.

OK

> 
>>>> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
>>>> +   contained within a single cache-line.
>>>> +
>>>> +   A single struct rseq per thread is allowed.  */
>>>> +struct rseq
>>>> +  {
>>>> +    /* Restartable sequences cpu_id_start field. Updated by the
>>>> +       kernel. Read by user-space with single-copy atomicity
>>>> +       semantics. This field should only be read by the thread which
>>>> +       registered this data structure. Aligned on 32-bit. Always
>>> 
>>> What does “Aligned on 32-bit” mean in this context?  Do you mean to
>>> reference 32-*byte* alignment here?
>>
>> No. I really mean 32-bit (4-byte). Being aligned on 32-byte guarantees that
>> this field is aligned at least on 4-byte. This is required by single-copy
>> atomicity semantics.
>>
>> Should I update this comment to state "Aligned on 4-byte" instead ?
> 
> I think this is implied by all Linux ABIs.  And the explicit alignment
> specification for struct rseq makes the alignment 32 bytes.

Unless a structure ends up being packed, which is of course not the case
here.

I would prefer to keep the comment about 32-bit alignment requirement on
the specific fields, because the motivation for alignment requirement is
much more strict for fields (correctness) than the motivation for alignment
of the structure (performance).

> 
>>>> +    /* Restartable sequences rseq_cs field.
>>>> +
>>>> +       Contains NULL when no critical section is active for the current
>>>> +       thread, or holds a pointer to the currently active struct rseq_cs.
>>>> +
>>>> +       Updated by user-space, which sets the address of the currently
>>>> +       active rseq_cs at the beginning of assembly instruction sequence
>>>> +       block, and set to NULL by the kernel when it restarts an assembly
>>>> +       instruction sequence block, as well as when the kernel detects that
>>>> +       it is preempting or delivering a signal outside of the range
>>>> +       targeted by the rseq_cs. Also needs to be set to NULL by user-space
>>>> +       before reclaiming memory that contains the targeted struct rseq_cs.
>>>> +
>>>> +       Read and set by the kernel. Set by user-space with single-copy
>>>> +       atomicity semantics. This field should only be updated by the
>>>> +       thread which registered this data structure. Aligned on 64-bit.  */
>>>> +    union {
>>>> +      uint64_t ptr64;
>>>> +#ifdef __LP64__
>>>> +      uint64_t ptr;
>>>> +#else
>>>> +      struct {
>>>> +#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) ||
>>>> defined(__BIG_ENDIAN)
>>>> +        uint32_t padding; /* Initialized to zero.  */
>>>> +        uint32_t ptr32;
>>>> +#else /* LITTLE */
>>>> +        uint32_t ptr32;
>>>> +        uint32_t padding; /* Initialized to zero.  */
>>>> +#endif /* ENDIAN */
>>>> +      } ptr;
>>>> +#endif
>>>> +    } rseq_cs;
>>> 
>>> Are these conditionals correct for x32?
>>
>> Let's see. With x86 gcc:
>>
>> -m64: (__x86_64__ && __LP64__)
>> -m32: (__i386__)
>> -mx32: (__x86_64__ && __ILP32__)
>>
>> So with "#ifdef __LP64__" we specifically target 64-bit pointers. The rest
>> falls into the "else" case, which expects 32-bit pointers. Considering that
>> x32 has 32-bit pointers, I don't see any issue here.
> 
> Does the kernel have a separate 32-bit entry point for rseq on x32?
> If not, it will expect the 64-bit struct layout.

No, there is a single entry point into rseq covering all of 32-bit, 64-bit and x32.
We achieve this by ensuring the layout of the linux/rseq.h structures
uses the union representation for pointers. Therefore, the kernel does not care
whether it reads a pointer from a 32-bit or 64-bit process. This is becoming the
preferred way to design Linux kernel ABIs nowadays.

> 
>> We don't mind that user-space uses that pointer, but we never want the kernel
>> to touch that pointer rather than the 32/64-bit-aware fields. One possibility
>> would be to do:
>>
>>     union
>>       {
>>         uint64_t ptr64;
>> #ifdef __LP64__
>>         uint64_t ptr;
>> #else
>>         struct
>>           {
>> #if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined
>> (__BIG_ENDIAN)
>>             uint32_t padding; /* Initialized to zero.  */
>>             uint32_t ptr32;
>> #else /* LITTLE */
>>             uint32_t ptr32;
>>             uint32_t padding; /* Initialized to zero.  */
>> #endif /* ENDIAN */
>>           } ptr;
>> #endif
>>
>> #ifndef __KERNEL__
>>      const struct rseq_cs *uptr;
>> #endif
>>       } rseq_cs;
>>
>> in the union, so only user-space can see that field. Thoughts ?
> 
> I think this depends on where the x32 question lands.

x32 should not be an issue as explained above, so I'm very open to
add this "uptr" for user-space only.

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 8/9] support: implement xpthread key create/delete (v4)
  2020-04-27 17:00           ` Florian Weimer
@ 2020-04-27 17:30             ` Mathieu Desnoyers
  0 siblings, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 17:30 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, Joseph Myers

----- On Apr 27, 2020, at 1:00 PM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers:
> 
>> ----- On Apr 27, 2020, at 11:23 AM, Florian Weimer fw@deneb.enyo.de wrote:
>>
>>> * Mathieu Desnoyers via Libc-alpha:
>>> 
>>>> ----- On Apr 27, 2020, at 5:17 AM, Florian Weimer fw@deneb.enyo.de wrote:
>>>>
>>>>> * Mathieu Desnoyers via Libc-alpha:
>>>>> 
>>>>>> diff --git a/support/xthread.h b/support/xthread.h
>>>>>> index d350d1506d..2a519874bf 100644
>>>>>> --- a/support/xthread.h
>>>>>> +++ b/support/xthread.h
>>>>>> @@ -95,6 +95,8 @@ void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
>>>>>>  void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
>>>>>>  void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
>>>>>>  void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
>>>>>> +void xpthread_key_create (pthread_key_t *key, void (*destr_function) (void *));
>>>>>> +void xpthread_key_delete (pthread_key_t key);
>>>>> 
>>>>> I think xpthread_key_create should return the pthread_key_t result
>>>>> directly.  It's similar to what we did for xpthread_create.
>>>>
>>>> Good point, done.
>>> 
>>> If you post a new patch, we can install it right now.
>>
>> I expect I'll be able to do a new round of post (including this patch)
>> later today.
> 
> Please submit it separately, so that we can commit it and remove it
> from the series.

OK, now sent,

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 9/9] rseq registration tests (v9)
  2020-04-27 16:55   ` Florian Weimer
@ 2020-04-27 17:48     ` Mathieu Desnoyers
  0 siblings, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 17:48 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, carlos, Boqun Feng, Will Deacon, Peter Zijlstra,
	Ben Maurer, Thomas Gleixner, Paul, Paul Turner, Joseph Myers

----- On Apr 27, 2020, at 12:55 PM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> These tests validate that rseq is registered from various execution
>> contexts (main thread, constructor, destructor, other threads, other
>> threads created from constructor and destructor, forked process
>> (without exec), pthread_atfork handlers, pthread setspecific
>> destructors, C++ thread and process destructors, signal handlers,
>> atexit handlers).
>>
>> tst-rseq.c only links against libc.so, testing registration of rseq in
>> a non-multithreaded environment.
>>
>> tst-rseq-nptl.c also links against libpthread.so, testing registration
>> of rseq in a multithreaded environment.
> 
> I suggest to split the fork-in-constructor test case off from the
> other tests, so that the majority of tests can go in independently of
> what we do with the support_record_failure initialization code.

OK will do, thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 7/9] support record failure: allow use from constructor
  2020-04-27 16:58   ` Florian Weimer
@ 2020-04-27 17:49     ` Mathieu Desnoyers
  0 siblings, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 17:49 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, carlos, Joseph Myers

----- On Apr 27, 2020, at 12:58 PM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers via Libc-alpha:
> 
>> Expose support_record_failure_init () so constructors can explicitly
>> initialize the record failure API.
>>
>> This is preferred to lazy initialization at first use, because
>> lazy initialization does not cover use in constructors within
>> forked children processes (forked from parent constructor).
> 
> My intent behind lazy initialization was that it avoids perturbing the
> address space until the first failure.  This is supposed to make the
> test harness more compatible.
> 
> A test in the constructor completely breaks major assumptions in the
> old test skeleton (and those were carried over into the current test
> framework).  In general, if a test involves constructors, we tend to
> avoid using the test harness at all.

OK, now that I moved this to separate patches, we can focus on the
rest and address it later.

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 17:26         ` Mathieu Desnoyers
@ 2020-04-27 20:27           ` Mathieu Desnoyers
  2020-04-28 12:02           ` Florian Weimer
  1 sibling, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-27 20:27 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, Carlos O'Donell, Rich Felker,
	linux-api, Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

----- On Apr 27, 2020, at 1:26 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:
[...]
>>> We don't mind that user-space uses that pointer, but we never want the kernel
>>> to touch that pointer rather than the 32/64-bit-aware fields. One possibility
>>> would be to do:
>>>
>>>     union
>>>       {
>>>         uint64_t ptr64;
>>> #ifdef __LP64__
>>>         uint64_t ptr;
>>> #else
>>>         struct
>>>           {
>>> #if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined
>>> (__BIG_ENDIAN)
>>>             uint32_t padding; /* Initialized to zero.  */
>>>             uint32_t ptr32;
>>> #else /* LITTLE */
>>>             uint32_t ptr32;
>>>             uint32_t padding; /* Initialized to zero.  */
>>> #endif /* ENDIAN */
>>>           } ptr;
>>> #endif
>>>
>>> #ifndef __KERNEL__
>>>      const struct rseq_cs *uptr;
>>> #endif
>>>       } rseq_cs;
>>>
>>> in the union, so only user-space can see that field. Thoughts ?
>> 
>> I think this depends on where the x32 question lands.
> 
> x32 should not be an issue as explained above, so I'm very open to
> add this "uptr" for user-space only.

Actually, the snippet above is broken on 32-bit. It needs to be:

    union
      {
        uint64_t ptr64;
#ifdef __LP64__
        uint64_t ptr;
# ifndef __KERNEL__
        const struct rseq_cs *uptr;
# endif
#else   
        struct
          {
#if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
            uint32_t padding; /* Initialized to zero.  */
            uint32_t ptr32;
#else /* LITTLE */
            uint32_t ptr32;
            uint32_t padding; /* Initialized to zero.  */
#endif /* ENDIAN */
          } ptr;
# ifndef __KERNEL__
        struct
          {
#  if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
            uint32_t padding; /* Initialized to zero.  */
            const struct rseq_cs *uptr32;
#  else /* LITTLE */
            const struct rseq_cs *uptr32;
            uint32_t padding; /* Initialized to zero.  */
#  endif /* ENDIAN */
          } uptr;
# endif
#endif
      } rseq_cs;

I'll leave this out of the patchset for now as we'd need more feedback on its
usefulness.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 3/9] Implement __libc_early_init
  2020-04-27 12:57         ` Adhemerval Zanella
@ 2020-04-27 20:35           ` Carlos O'Donell
  0 siblings, 0 replies; 63+ messages in thread
From: Carlos O'Donell @ 2020-04-27 20:35 UTC (permalink / raw)
  To: Adhemerval Zanella, Florian Weimer, Carlos O'Donell via Libc-alpha
  Cc: Mathieu Desnoyers, Joseph Myers

On 4/27/20 8:57 AM, Adhemerval Zanella wrote:
> 
> 
> On 24/04/2020 17:18, Carlos O'Donell via Libc-alpha wrote:
>> On 4/24/20 2:22 PM, Florian Weimer wrote:
>>> * Carlos O'Donell via Libc-alpha:
>>>
>>>> Please clarify or remove the comment related to libc_already_loaded.
>>>
>>> I have removed the initialization.  It is no longer relevant in the
>>> current patch.  It may have been obsoleted by other dl_open_worker
>>> changes earlier.
>>
>> Thanks!
> [...]
>>> diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
>>> new file mode 100644
>>> index 0000000000..5637ae89de
>>> --- /dev/null
>>> +++ b/elf/dl-lookup-direct.c
>>> @@ -0,0 +1,116 @@
>>> +/* Look up a symbol in a single specified object.
>>> +   Copyright (C) 1995-2020 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 <string.h>
>>> +#include <elf_machine_sym_no_match.h>
>>> +#include <dl-hash.h>
>>> +
>>> +/* This function corresponds to do_lookup_x in elf/dl-lookup.c.  The
>>> +   variant here is simplified because it requires symbol
>>> +   versioning.  */
>>> +static const ElfW(Sym) *
>>> +check_match (const struct link_map *const map, const char *const undef_name,
>>> +             const char *version, uint32_t version_hash,
>>> +             const Elf_Symndx symidx)
>>> +{
>>> +  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
>>> +  const ElfW(Sym) *sym = &symtab[symidx];
>>> +
>>> +  unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
>>> +  if (__glibc_unlikely ((sym->st_value == 0 /* No value.  */
>>> +                         && sym->st_shndx != SHN_ABS
>>> +                         && stt != STT_TLS)
>>> +                        || elf_machine_sym_no_match (sym)))
>>> +    return NULL;
>>> +
>>> +  /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
>>> +     STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
>>> +     code/data definitions.  */
>>> +#define ALLOWED_STT \
>>> +  ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
>>> +   | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
>>> +  if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
>>> +    return NULL;
>>> +
>>> +  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
>>> +
>>> +  if (strcmp (strtab + sym->st_name, undef_name) != 0)
>>> +    /* Not the symbol we are looking for.  */
>>> +    return NULL;
>>> +
>>> +  ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
>>> +  if (map->l_versions[ndx].hash != version_hash
>>> +      || strcmp (map->l_versions[ndx].name, version) != 0)
>>> +    /* It's not the version we want.  */
>>> +    return NULL;
>>> +
>>> +  return sym;
>>> +}
>>
>> OK.
> 
> The only reservation I have with this change it this code duplication,
> could we refactor to have this patch in a common place?
> 

I thought about asking this, but the code is so short, and the refactor
would be significantly more complicated with all the fallbacks. It's easier
to read this simplified version and maintain it because you know what it's
expected to do.

It *might* be possible to refactor it a bit more, but I wasn't going to push
on that as a requirement for the direct versioned symbol lookup.

-- 
Cheers,
Carlos.


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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-27 17:26         ` Mathieu Desnoyers
  2020-04-27 20:27           ` Mathieu Desnoyers
@ 2020-04-28 12:02           ` Florian Weimer
  2020-04-28 12:33             ` Mathieu Desnoyers
  1 sibling, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-28 12:02 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

* Mathieu Desnoyers:

>>>>> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
>>>>> +   contained within a single cache-line.
>>>>> +
>>>>> +   A single struct rseq per thread is allowed.  */
>>>>> +struct rseq
>>>>> +  {
>>>>> +    /* Restartable sequences cpu_id_start field. Updated by the
>>>>> +       kernel. Read by user-space with single-copy atomicity
>>>>> +       semantics. This field should only be read by the thread which
>>>>> +       registered this data structure. Aligned on 32-bit. Always
>>>> 
>>>> What does “Aligned on 32-bit” mean in this context?  Do you mean to
>>>> reference 32-*byte* alignment here?
>>>
>>> No. I really mean 32-bit (4-byte). Being aligned on 32-byte guarantees that
>>> this field is aligned at least on 4-byte. This is required by single-copy
>>> atomicity semantics.
>>>
>>> Should I update this comment to state "Aligned on 4-byte" instead ?
>> 
>> I think this is implied by all Linux ABIs.  And the explicit alignment
>> specification for struct rseq makes the alignment 32 bytes.
>
> Unless a structure ends up being packed, which is of course not the case
> here.
>
> I would prefer to keep the comment about 32-bit alignment requirement on
> the specific fields, because the motivation for alignment requirement is
> much more strict for fields (correctness) than the motivation for alignment
> of the structure (performance).

But the correctness is already enforced by the compiler, so I fail to
see point of mentioning this in the comment.

Anyway, I don't want to make a big deal of it.  Please leave it in if
you think it is ehlpful.

> x32 should not be an issue as explained above, so I'm very open to
> add this "uptr" for user-space only.

Okay, then please use anonymous unions and structs as necessary, to
ensure that the uptr field can be reached on all platforms in the same
way.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:02           ` Florian Weimer
@ 2020-04-28 12:33             ` Mathieu Desnoyers
  2020-04-28 12:35               ` Florian Weimer
  2020-04-28 12:56               ` Mathieu Desnoyers
  0 siblings, 2 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-28 12:33 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

----- On Apr 28, 2020, at 8:02 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers:
> 
>>>>>> +/* struct rseq is aligned on 4 * 8 bytes to ensure it is always
>>>>>> +   contained within a single cache-line.
>>>>>> +
>>>>>> +   A single struct rseq per thread is allowed.  */
>>>>>> +struct rseq
>>>>>> +  {
>>>>>> +    /* Restartable sequences cpu_id_start field. Updated by the
>>>>>> +       kernel. Read by user-space with single-copy atomicity
>>>>>> +       semantics. This field should only be read by the thread which
>>>>>> +       registered this data structure. Aligned on 32-bit. Always
>>>>> 
>>>>> What does “Aligned on 32-bit” mean in this context?  Do you mean to
>>>>> reference 32-*byte* alignment here?
>>>>
>>>> No. I really mean 32-bit (4-byte). Being aligned on 32-byte guarantees that
>>>> this field is aligned at least on 4-byte. This is required by single-copy
>>>> atomicity semantics.
>>>>
>>>> Should I update this comment to state "Aligned on 4-byte" instead ?
>>> 
>>> I think this is implied by all Linux ABIs.  And the explicit alignment
>>> specification for struct rseq makes the alignment 32 bytes.
>>
>> Unless a structure ends up being packed, which is of course not the case
>> here.
>>
>> I would prefer to keep the comment about 32-bit alignment requirement on
>> the specific fields, because the motivation for alignment requirement is
>> much more strict for fields (correctness) than the motivation for alignment
>> of the structure (performance).
> 
> But the correctness is already enforced by the compiler, so I fail to
> see point of mentioning this in the comment.
> 
> Anyway, I don't want to make a big deal of it.  Please leave it in if
> you think it is ehlpful.

I would prefer to leave it in, just to make the requirements plain clear in
case those structures are allocated on the heap (for instance).

> 
>> x32 should not be an issue as explained above, so I'm very open to
>> add this "uptr" for user-space only.
> 
> Okay, then please use anonymous unions and structs as necessary, to
> ensure that the uptr field can be reached on all platforms in the same
> way.

OK, will do!

One issue I'm currently facing when running "make check": because nptl/tst-rseq-nptl.c
uses pthread_cancel(), I run into an Abort with:

libgcc_s.so.1 must be installed for pthread_cancel to work
Didn't expect signal from child: got `Aborted'

So far I've tested the rest of that file with a patch on top which disables the use of
pthread_cancel (), but I'd really like to give it a full coverage before sending this out.
In https://sourceware.org/glibc/wiki/Testing/Builds there is a section about
"Building glibc with intent to install" which describes that libgcc must be copied
manually. My use-case is that I just want to run "make check" in the build directory
and make sure it finds the libgcc it needs to succeed using pthread_cancel ().
How can I achieve this ?

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:33             ` Mathieu Desnoyers
@ 2020-04-28 12:35               ` Florian Weimer
  2020-04-28 12:43                 ` Mathieu Desnoyers
  2020-04-28 12:56               ` Mathieu Desnoyers
  1 sibling, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-28 12:35 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

* Mathieu Desnoyers:

> One issue I'm currently facing when running "make check": because
> nptl/tst-rseq-nptl.c uses pthread_cancel(), I run into an Abort
> with:
>
> libgcc_s.so.1 must be installed for pthread_cancel to work
> Didn't expect signal from child: got `Aborted'

This is really unusual.  Is the affected test statically linked?

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:35               ` Florian Weimer
@ 2020-04-28 12:43                 ` Mathieu Desnoyers
  2020-04-28 12:54                   ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-28 12:43 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

----- On Apr 28, 2020, at 8:35 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers:
> 
>> One issue I'm currently facing when running "make check": because
>> nptl/tst-rseq-nptl.c uses pthread_cancel(), I run into an Abort
>> with:
>>
>> libgcc_s.so.1 must be installed for pthread_cancel to work
>> Didn't expect signal from child: got `Aborted'
> 
> This is really unusual.  Is the affected test statically linked?

I built glibc without specifying anything particular, and ran
"make check". It indeed seems to be dynamically linked to libc:

ldd tst-rseq-nptl
./tst-rseq-nptl: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./tst-rseq-nptl)
linux-vdso.so.1 (0x00007ffd3a2f3000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0527560000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f052716f000)
/home/efficios/glibc-test5/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f0527986000)

After make check I have:

cat tst-rseq-nptl.test-result 
FAIL: nptl/tst-rseq-nptl
original exit status 134

And if I run

./tst-rseq-nptl

Then I get

libgcc_s.so.1 must be installed for pthread_cancel to work
Didn't expect signal from child: got `Aborted'
libgcc_s.so.1 must be installed for pthread_cancel to work
Aborted (core dumped)

Same result if I do ./testrun.sh nptl/tst-rseq-nptl

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:43                 ` Mathieu Desnoyers
@ 2020-04-28 12:54                   ` Florian Weimer
  2020-04-28 14:58                     ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-28 12:54 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

* Mathieu Desnoyers:

> ----- On Apr 28, 2020, at 8:35 AM, Florian Weimer fw@deneb.enyo.de wrote:
>
>> * Mathieu Desnoyers:
>> 
>>> One issue I'm currently facing when running "make check": because
>>> nptl/tst-rseq-nptl.c uses pthread_cancel(), I run into an Abort
>>> with:
>>>
>>> libgcc_s.so.1 must be installed for pthread_cancel to work
>>> Didn't expect signal from child: got `Aborted'
>> 
>> This is really unusual.  Is the affected test statically linked?
>
> I built glibc without specifying anything particular, and ran
> "make check". It indeed seems to be dynamically linked to libc:
>
> ldd tst-rseq-nptl
> ./tst-rseq-nptl: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./tst-rseq-nptl)
> linux-vdso.so.1 (0x00007ffd3a2f3000)
> libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0527560000)
> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f052716f000)
> /home/efficios/glibc-test5/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f0527986000)

That's expected if the installed glibc is older than the built glibc.

> After make check I have:
>
> cat tst-rseq-nptl.test-result 
> FAIL: nptl/tst-rseq-nptl
> original exit status 134

What's in the tst-rseq-nptl.out file?

> And if I run
>
> ./tst-rseq-nptl
>
> Then I get
>
> libgcc_s.so.1 must be installed for pthread_cancel to work
> Didn't expect signal from child: got `Aborted'
> libgcc_s.so.1 must be installed for pthread_cancel to work
> Aborted (core dumped)

I'm puzzled why you don't get a GLIBC_2.32 version error in this case.
Do you build with --enable-hardcoded-path-in-tests?

> Same result if I do ./testrun.sh nptl/tst-rseq-nptl

That one definitely should work.

I expect you might see this if libgcc_s.so.1 is installed into a
multiarch subdirectory that upstream glibc does not search.  (The
Debian patches are unfortunately not upstream.)

I think on my system, the built glibc can find the system libgcc_s via
/etc/ld.so.cache, so I haven't seen this issue yet.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:33             ` Mathieu Desnoyers
  2020-04-28 12:35               ` Florian Weimer
@ 2020-04-28 12:56               ` Mathieu Desnoyers
  2020-04-29 12:19                 ` Florian Weimer
  1 sibling, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-28 12:56 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

----- On Apr 28, 2020, at 8:33 AM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:

> ----- On Apr 28, 2020, at 8:02 AM, Florian Weimer fw@deneb.enyo.de wrote:
> 
[...]
>> 
>>> x32 should not be an issue as explained above, so I'm very open to
>>> add this "uptr" for user-space only.
>> 
>> Okay, then please use anonymous unions and structs as necessary, to
>> ensure that the uptr field can be reached on all platforms in the same
>> way.
> 
> OK, will do!

What I came up with looks like this. User-space can use rseq_cs.uptr.ptr
both on 32-bit and 64-bit to update the pointer:

    /* Restartable sequences rseq_cs field.

       Contains NULL when no critical section is active for the current
       thread, or holds a pointer to the currently active struct rseq_cs.

       Updated by user-space, which sets the address of the currently
       active rseq_cs at the beginning of assembly instruction sequence
       block, and set to NULL by the kernel when it restarts an assembly
       instruction sequence block, as well as when the kernel detects that
       it is preempting or delivering a signal outside of the range
       targeted by the rseq_cs.  Also needs to be set to NULL by user-space
       before reclaiming memory that contains the targeted struct rseq_cs.

       Read and set by the kernel.  Set by user-space with single-copy
       atomicity semantics.  This field should only be updated by the
       thread which registered this data structure.  Aligned on 64-bit.

       User-space may perform the update through the rseq_cs.uptr.ptr
       field.  The padding needs to be initialized to zero on 32-bit.  */
    union
      {
        uint64_t ptr64;
#ifdef __LP64__
        uint64_t ptr;
#else   
        struct
          {
# if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
            uint32_t padding; /* Initialized to zero.  */
            uint32_t ptr32;
# else /* LITTLE */
            uint32_t ptr32;
            uint32_t padding; /* Initialized to zero.  */
# endif /* ENDIAN */
          } ptr;
#endif

#ifndef __KERNEL__
        struct
          {
# ifdef __LP64__
            const struct rseq_cs *ptr;
# else
#  if (defined (__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined (__BIG_ENDIAN)
            uint32_t padding; /* Initialized to zero.  */
            const struct rseq_cs *ptr;
#  else /* LITTLE */
            const struct rseq_cs *ptr;
            uint32_t padding; /* Initialized to zero.  */
#  endif /* ENDIAN */
# endif
          } uptr;
#endif
      } rseq_cs;

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:54                   ` Florian Weimer
@ 2020-04-28 14:58                     ` Mathieu Desnoyers
  2020-04-29  8:16                       ` Szabolcs Nagy
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-28 14:58 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

----- On Apr 28, 2020, at 8:54 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Mathieu Desnoyers:
> 
>> ----- On Apr 28, 2020, at 8:35 AM, Florian Weimer fw@deneb.enyo.de wrote:
>>
>>> * Mathieu Desnoyers:
>>> 
>>>> One issue I'm currently facing when running "make check": because
>>>> nptl/tst-rseq-nptl.c uses pthread_cancel(), I run into an Abort
>>>> with:
>>>>
>>>> libgcc_s.so.1 must be installed for pthread_cancel to work
>>>> Didn't expect signal from child: got `Aborted'
>>> 
>>> This is really unusual.  Is the affected test statically linked?
>>
>> I built glibc without specifying anything particular, and ran
>> "make check". It indeed seems to be dynamically linked to libc:
>>
>> ldd tst-rseq-nptl
>> ./tst-rseq-nptl: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found
>> (required by ./tst-rseq-nptl)
>> linux-vdso.so.1 (0x00007ffd3a2f3000)
>> libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0527560000)
>> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f052716f000)
>> /home/efficios/glibc-test5/lib/ld-linux-x86-64.so.2 =>
>> /lib64/ld-linux-x86-64.so.2 (0x00007f0527986000)
> 
> That's expected if the installed glibc is older than the built glibc.
> 
>> After make check I have:
>>
>> cat tst-rseq-nptl.test-result
>> FAIL: nptl/tst-rseq-nptl
>> original exit status 134
> 
> What's in the tst-rseq-nptl.out file?

It contains:

Didn't expect signal from child: got `Aborted'

>> And if I run
>>
>> ./tst-rseq-nptl
>>
>> Then I get
>>
>> libgcc_s.so.1 must be installed for pthread_cancel to work
>> Didn't expect signal from child: got `Aborted'
>> libgcc_s.so.1 must be installed for pthread_cancel to work
>> Aborted (core dumped)
> 
> I'm puzzled why you don't get a GLIBC_2.32 version error in this case.
> Do you build with --enable-hardcoded-path-in-tests?

Just tried with this, and it fails the same way. However, the output
of ldd nptl/tst-rseq-nptl changes:

linux-vdso.so.1 (0x00007ffc235c9000)
libpthread.so.0 => /home/efficios/git/glibc-build/nptl/libpthread.so.0 (0x00007fd308278000)
libc.so.6 => /home/efficios/git/glibc-build/libc.so.6 (0x00007fd307ebc000)
/home/efficios/git/glibc-build/elf/ld.so => /lib64/ld-linux-x86-64.so.2 (0x00007fd30869e000)


>> Same result if I do ./testrun.sh nptl/tst-rseq-nptl
> 
> That one definitely should work.
> 
> I expect you might see this if libgcc_s.so.1 is installed into a
> multiarch subdirectory that upstream glibc does not search.  (The
> Debian patches are unfortunately not upstream.)

My test environment is a Ubuntu 18.04.1 LTS.

> 
> I think on my system, the built glibc can find the system libgcc_s via
> /etc/ld.so.cache, so I haven't seen this issue yet.

On my system, libgcc_s is provided here:

/lib/x86_64-linux-gnu/libgcc_s.so.1

by this package:

Package: libgcc1
Architecture: amd64
Version: 1:8.4.0-1ubuntu1~18.04

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 14:58                     ` Mathieu Desnoyers
@ 2020-04-29  8:16                       ` Szabolcs Nagy
  2020-04-29  8:18                         ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Szabolcs Nagy @ 2020-04-29  8:16 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Florian Weimer, Michael Kerrisk, libc-alpha, carlos, Rich Felker,
	linux-api, Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers

The 04/28/2020 10:58, Mathieu Desnoyers wrote:
> ----- On Apr 28, 2020, at 8:54 AM, Florian Weimer fw@deneb.enyo.de wrote:
> > That one definitely should work.
> > 
> > I expect you might see this if libgcc_s.so.1 is installed into a
> > multiarch subdirectory that upstream glibc does not search.  (The
> > Debian patches are unfortunately not upstream.)
> 
> My test environment is a Ubuntu 18.04.1 LTS.
> 
> > 
> > I think on my system, the built glibc can find the system libgcc_s via
> > /etc/ld.so.cache, so I haven't seen this issue yet.
> 
> On my system, libgcc_s is provided here:
> 
> /lib/x86_64-linux-gnu/libgcc_s.so.1
> 
> by this package:
> 
> Package: libgcc1
> Architecture: amd64
> Version: 1:8.4.0-1ubuntu1~18.04

before running the tests

cp `$CC --print-file-name libgcc_s.so.1` glibc/build/dir
cp `$CC --print-file-name libstdc++.so.6` glibc/build/dir

so those toolchain libs are in the search path
of the newly built libc when running tests.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-29  8:16                       ` Szabolcs Nagy
@ 2020-04-29  8:18                         ` Florian Weimer
  2020-04-29  8:52                           ` Szabolcs Nagy
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-29  8:18 UTC (permalink / raw)
  To: Szabolcs Nagy
  Cc: Mathieu Desnoyers, Michael Kerrisk, libc-alpha, carlos,
	Rich Felker, linux-api, Boqun Feng, Will Deacon, linux-kernel,
	Peter Zijlstra, Ben Maurer, Dave Watson, Thomas Gleixner, Paul,
	Paul Turner, Joseph Myers

* Szabolcs Nagy:

> The 04/28/2020 10:58, Mathieu Desnoyers wrote:
>> ----- On Apr 28, 2020, at 8:54 AM, Florian Weimer fw@deneb.enyo.de wrote:
>> > That one definitely should work.
>> > 
>> > I expect you might see this if libgcc_s.so.1 is installed into a
>> > multiarch subdirectory that upstream glibc does not search.  (The
>> > Debian patches are unfortunately not upstream.)
>> 
>> My test environment is a Ubuntu 18.04.1 LTS.
>> 
>> > 
>> > I think on my system, the built glibc can find the system libgcc_s via
>> > /etc/ld.so.cache, so I haven't seen this issue yet.
>> 
>> On my system, libgcc_s is provided here:
>> 
>> /lib/x86_64-linux-gnu/libgcc_s.so.1
>> 
>> by this package:
>> 
>> Package: libgcc1
>> Architecture: amd64
>> Version: 1:8.4.0-1ubuntu1~18.04
>
> before running the tests
>
> cp `$CC --print-file-name libgcc_s.so.1` glibc/build/dir
> cp `$CC --print-file-name libstdc++.so.6` glibc/build/dir
>
> so those toolchain libs are in the search path
> of the newly built libc when running tests.

Do you actually see the need for these steps yourself?

I guess the correct fix would be to upstream the Debian multiarch
changes and activate them automatically with a configure check on
systems that use multiarch paths.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-29  8:18                         ` Florian Weimer
@ 2020-04-29  8:52                           ` Szabolcs Nagy
  2020-04-29  9:01                             ` Florian Weimer
  0 siblings, 1 reply; 63+ messages in thread
From: Szabolcs Nagy @ 2020-04-29  8:52 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Mathieu Desnoyers, Michael Kerrisk, libc-alpha, carlos,
	Rich Felker, linux-api, Boqun Feng, Will Deacon, linux-kernel,
	Peter Zijlstra, Ben Maurer, Dave Watson, Thomas Gleixner, Paul,
	Paul Turner, Joseph Myers

The 04/29/2020 10:18, Florian Weimer wrote:
> * Szabolcs Nagy:
> 
> > The 04/28/2020 10:58, Mathieu Desnoyers wrote:
> >> ----- On Apr 28, 2020, at 8:54 AM, Florian Weimer fw@deneb.enyo.de wrote:
> >> > That one definitely should work.
> >> > 
> >> > I expect you might see this if libgcc_s.so.1 is installed into a
> >> > multiarch subdirectory that upstream glibc does not search.  (The
> >> > Debian patches are unfortunately not upstream.)
> >> 
> >> My test environment is a Ubuntu 18.04.1 LTS.
> >> 
> >> > 
> >> > I think on my system, the built glibc can find the system libgcc_s via
> >> > /etc/ld.so.cache, so I haven't seen this issue yet.
> >> 
> >> On my system, libgcc_s is provided here:
> >> 
> >> /lib/x86_64-linux-gnu/libgcc_s.so.1
> >> 
> >> by this package:
> >> 
> >> Package: libgcc1
> >> Architecture: amd64
> >> Version: 1:8.4.0-1ubuntu1~18.04
> >
> > before running the tests
> >
> > cp `$CC --print-file-name libgcc_s.so.1` glibc/build/dir
> > cp `$CC --print-file-name libstdc++.so.6` glibc/build/dir
> >
> > so those toolchain libs are in the search path
> > of the newly built libc when running tests.
> 
> Do you actually see the need for these steps yourself?
> 
> I guess the correct fix would be to upstream the Debian multiarch
> changes and activate them automatically with a configure check on
> systems that use multiarch paths.

cancel tests work for me on an ubuntu system because
of /etc/ld.so.cache, but that may not be present
or the system may not be glibc based at all.

i always do the cp because i build gcc myself (usually
close to current master) and don't install it to the
system path which means at compile time and runtime
different libraries are used if i dont copy

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-29  8:52                           ` Szabolcs Nagy
@ 2020-04-29  9:01                             ` Florian Weimer
  2020-04-29 12:57                               ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Florian Weimer @ 2020-04-29  9:01 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: libc-alpha, Mathieu Desnoyers, Joseph Myers

* Szabolcs Nagy:

> cancel tests work for me on an ubuntu system because
> of /etc/ld.so.cache, but that may not be present
> or the system may not be glibc based at all.

I see.

> i always do the cp because i build gcc myself (usually
> close to current master) and don't install it to the
> system path which means at compile time and runtime
> different libraries are used if i dont copy

I wonder if we should do this automatically (maybe using a symbolic
link), at least of GCC and ld can find these shared objects.  Maybe
it's possible to tell ld to provide output that makes it easy to
locate the actual objects in the file system?

(Trimmed the Cc: list.)

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-28 12:56               ` Mathieu Desnoyers
@ 2020-04-29 12:19                 ` Florian Weimer
  0 siblings, 0 replies; 63+ messages in thread
From: Florian Weimer @ 2020-04-29 12:19 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Michael Kerrisk, libc-alpha, carlos, Rich Felker, linux-api,
	Boqun Feng, Will Deacon, linux-kernel, Peter Zijlstra,
	Ben Maurer, Dave Watson, Thomas Gleixner, Paul, Paul Turner,
	Joseph Myers, Szabolcs Nagy

* Mathieu Desnoyers:

> ----- On Apr 28, 2020, at 8:33 AM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:
>
>> ----- On Apr 28, 2020, at 8:02 AM, Florian Weimer fw@deneb.enyo.de wrote:
>> 
> [...]
>>> 
>>>> x32 should not be an issue as explained above, so I'm very open to
>>>> add this "uptr" for user-space only.
>>> 
>>> Okay, then please use anonymous unions and structs as necessary, to
>>> ensure that the uptr field can be reached on all platforms in the same
>>> way.
>> 
>> OK, will do!
>
> What I came up with looks like this. User-space can use rseq_cs.uptr.ptr
> both on 32-bit and 64-bit to update the pointer:

Agreed, this should work.

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-29  9:01                             ` Florian Weimer
@ 2020-04-29 12:57                               ` Mathieu Desnoyers
  2020-04-30 10:40                                 ` Szabolcs Nagy
  0 siblings, 1 reply; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-29 12:57 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Szabolcs Nagy, libc-alpha, Joseph Myers

----- On Apr 29, 2020, at 5:01 AM, Florian Weimer fw@deneb.enyo.de wrote:

> * Szabolcs Nagy:
> 
>> cancel tests work for me on an ubuntu system because
>> of /etc/ld.so.cache, but that may not be present
>> or the system may not be glibc based at all.
> 
> I see.
> 
>> i always do the cp because i build gcc myself (usually
>> close to current master) and don't install it to the
>> system path which means at compile time and runtime
>> different libraries are used if i dont copy
> 
> I wonder if we should do this automatically (maybe using a symbolic
> link), at least of GCC and ld can find these shared objects.  Maybe
> it's possible to tell ld to provide output that makes it easy to
> locate the actual objects in the file system?
> 
> (Trimmed the Cc: list.)

For the records, here is the output I get here:

$ gcc --print-file-name libgcc_s.so.1
/usr/lib/gcc/x86_64-linux-gnu/7/libgcc_s.so.1
$ gcc --print-file-name libstdc++.so.6
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libstdc++.so.6
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 

Even if this becomes worked-around upstream, I suspect it would be good to mention
this trick in https://sourceware.org/glibc/wiki/Testing/Builds for those
working on older glibc versions.

Considering that I my build directory is in:

/home/efficios/git/glibc-build

and I configure my glibc from the build directory with:
"../glibc/configure --prefix=/home/efficios/glibc-test"

Where exactly should I copy libgcc_s.so.1 and libstdc++.so.6 ? I tried copying
them to /home/efficios/git/glibc-build/ but it does not appear to fix the issue.
I notice that other .so are pulled into /home/efficios/git/glibc-build/testroot.pristine
and then /home/efficios/git/glibc-build/testroot.root though. Is it where I should
copy them, and if so, under which subdirectory are they expected ?

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-29 12:57                               ` Mathieu Desnoyers
@ 2020-04-30 10:40                                 ` Szabolcs Nagy
  2020-04-30 19:04                                   ` Mathieu Desnoyers
  0 siblings, 1 reply; 63+ messages in thread
From: Szabolcs Nagy @ 2020-04-30 10:40 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: Florian Weimer, libc-alpha, Joseph Myers

The 04/29/2020 08:57, Mathieu Desnoyers wrote:
> ----- On Apr 29, 2020, at 5:01 AM, Florian Weimer fw@deneb.enyo.de wrote:
> 
> > * Szabolcs Nagy:
> > 
> >> cancel tests work for me on an ubuntu system because
> >> of /etc/ld.so.cache, but that may not be present
> >> or the system may not be glibc based at all.
> > 
> > I see.
> > 
> >> i always do the cp because i build gcc myself (usually
> >> close to current master) and don't install it to the
> >> system path which means at compile time and runtime
> >> different libraries are used if i dont copy
> > 
> > I wonder if we should do this automatically (maybe using a symbolic
> > link), at least of GCC and ld can find these shared objects.  Maybe
> > it's possible to tell ld to provide output that makes it easy to
> > locate the actual objects in the file system?
> > 
> > (Trimmed the Cc: list.)
> 
> For the records, here is the output I get here:
> 
> $ gcc --print-file-name libgcc_s.so.1
> /usr/lib/gcc/x86_64-linux-gnu/7/libgcc_s.so.1
> $ gcc --print-file-name libstdc++.so.6
> /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libstdc++.so.6
> $ gcc -v
> Using built-in specs.
> COLLECT_GCC=gcc
> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
> OFFLOAD_TARGET_NAMES=nvptx-none
> OFFLOAD_TARGET_DEFAULT=1
> Target: x86_64-linux-gnu
> Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
> Thread model: posix
> gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
> 
> Even if this becomes worked-around upstream, I suspect it would be good to mention
> this trick in https://sourceware.org/glibc/wiki/Testing/Builds for those
> working on older glibc versions.
> 
> Considering that I my build directory is in:
> 
> /home/efficios/git/glibc-build
> 
> and I configure my glibc from the build directory with:
> "../glibc/configure --prefix=/home/efficios/glibc-test"
> 
> Where exactly should I copy libgcc_s.so.1 and libstdc++.so.6 ? I tried copying
> them to /home/efficios/git/glibc-build/ but it does not appear to fix the issue.

hm then the issue may be something else.

the build directory should be early in the runtime
library search path so if the right libs are there
then things should work.

> I notice that other .so are pulled into /home/efficios/git/glibc-build/testroot.pristine
> and then /home/efficios/git/glibc-build/testroot.root though. Is it where I should
> copy them, and if so, under which subdirectory are they expected ?

that is used if the test is running in a container
(e.g. resolver tests that use custom /etc/resolv.conf)

i'd try to run

strace -f ./testrun.sh nptl/tst-rseq-nptl --direct 2>strace.log

and grep libgcc_s strace.log

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

* Re: [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17)
  2020-04-30 10:40                                 ` Szabolcs Nagy
@ 2020-04-30 19:04                                   ` Mathieu Desnoyers
  0 siblings, 0 replies; 63+ messages in thread
From: Mathieu Desnoyers @ 2020-04-30 19:04 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Florian Weimer, libc-alpha, Joseph Myers

----- On Apr 30, 2020, at 6:40 AM, Szabolcs Nagy szabolcs.nagy@arm.com wrote:

> The 04/29/2020 08:57, Mathieu Desnoyers wrote:
>> ----- On Apr 29, 2020, at 5:01 AM, Florian Weimer fw@deneb.enyo.de wrote:
>> 
>> > * Szabolcs Nagy:
>> > 
>> >> cancel tests work for me on an ubuntu system because
>> >> of /etc/ld.so.cache, but that may not be present
>> >> or the system may not be glibc based at all.
>> > 
>> > I see.
>> > 
>> >> i always do the cp because i build gcc myself (usually
>> >> close to current master) and don't install it to the
>> >> system path which means at compile time and runtime
>> >> different libraries are used if i dont copy
>> > 
>> > I wonder if we should do this automatically (maybe using a symbolic
>> > link), at least of GCC and ld can find these shared objects.  Maybe
>> > it's possible to tell ld to provide output that makes it easy to
>> > locate the actual objects in the file system?
>> > 
>> > (Trimmed the Cc: list.)
>> 
>> For the records, here is the output I get here:
>> 
>> $ gcc --print-file-name libgcc_s.so.1
>> /usr/lib/gcc/x86_64-linux-gnu/7/libgcc_s.so.1
>> $ gcc --print-file-name libstdc++.so.6
>> /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libstdc++.so.6
>> $ gcc -v
>> Using built-in specs.
>> COLLECT_GCC=gcc
>> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
>> OFFLOAD_TARGET_NAMES=nvptx-none
>> OFFLOAD_TARGET_DEFAULT=1
>> Target: x86_64-linux-gnu
>> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
>> 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs
>> --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr
>> --with-gcc-major-version-only --program-suffix=-7
>> --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id
>> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
>> --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu
>> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
>> --with-default-libstdcxx-abi=new --enable-gnu-unique-object
>> --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie
>> --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto
>> --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64
>> --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic
>> --enable-offload-targets=nvptx-none --without-cuda-driver
>> --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
>> --target=x86_64-linux-gnu
>> Thread model: posix
>> gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
>> 
>> Even if this becomes worked-around upstream, I suspect it would be good to
>> mention
>> this trick in https://sourceware.org/glibc/wiki/Testing/Builds for those
>> working on older glibc versions.
>> 
>> Considering that I my build directory is in:
>> 
>> /home/efficios/git/glibc-build
>> 
>> and I configure my glibc from the build directory with:
>> "../glibc/configure --prefix=/home/efficios/glibc-test"
>> 
>> Where exactly should I copy libgcc_s.so.1 and libstdc++.so.6 ? I tried copying
>> them to /home/efficios/git/glibc-build/ but it does not appear to fix the issue.
> 
> hm then the issue may be something else.
> 
> the build directory should be early in the runtime
> library search path so if the right libs are there
> then things should work.
> 
>> I notice that other .so are pulled into
>> /home/efficios/git/glibc-build/testroot.pristine
>> and then /home/efficios/git/glibc-build/testroot.root though. Is it where I
>> should
>> copy them, and if so, under which subdirectory are they expected ?
> 
> that is used if the test is running in a container
> (e.g. resolver tests that use custom /etc/resolv.conf)
> 
> i'd try to run
> 
> strace -f ./testrun.sh nptl/tst-rseq-nptl --direct 2>strace.log
> 
> and grep libgcc_s strace.log

After a few attempts, it appears that the issue was that I had already
run "make check" in my build directory beforehand, so even though I then
copied over the .so files to the build directory top level, it did not
populate them into the testroot.pristine nor testroot.root directories
for the following "make check".

If I delete both testroot.pristine and testroot.root, and make check
after making sure both .so are in the toplevel build directory, then
they are copied over to testroot.pristine, but testroot.root is not
created at all (and the test still fails).

Starting from a brand new empty build directory, and copying the .so
files before the first make check gets the test to run fine! By doing so,
the .so are copied into testroot.pristine and testroot.root.

Thanks,

Mathieu


-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

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

end of thread, other threads:[~2020-04-30 19:04 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26 15:56 [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
2020-03-26 15:56 ` [PATCH glibc 1/9] Introduce <elf_machine_sym_no_match.h> Mathieu Desnoyers
2020-04-22 16:27   ` Carlos O'Donell
2020-04-24 18:20     ` Florian Weimer
2020-04-24 20:11       ` Carlos O'Donell
2020-03-26 15:56 ` [PATCH glibc 2/9] Move elf/elf_machine_sym_no_match.h to sysdeps/generic Mathieu Desnoyers
2020-04-22 16:27   ` Carlos O'Donell
2020-03-26 15:56 ` [PATCH glibc 3/9] Implement __libc_early_init Mathieu Desnoyers
2020-04-22 16:28   ` Carlos O'Donell
2020-04-24 18:22     ` Florian Weimer
2020-04-24 20:18       ` Carlos O'Donell
2020-04-27 12:43         ` Stefan Liebler
2020-04-27 13:23           ` Florian Weimer
2020-04-27 16:23             ` Stefan Liebler
2020-04-27 16:38               ` Florian Weimer
2020-04-27 12:57         ` Adhemerval Zanella
2020-04-27 20:35           ` Carlos O'Donell
2020-03-26 15:56 ` [PATCH glibc 4/9] nptl: Start new threads with all signals blocked [BZ #25098] Mathieu Desnoyers
2020-04-22 17:04   ` Carlos O'Donell
2020-04-24 20:35     ` Florian Weimer
2020-04-26 18:49       ` Carlos O'Donell
2020-04-27 13:11       ` Adhemerval Zanella
2020-03-26 15:56 ` [PATCH glibc 5/9] glibc: Perform rseq(2) registration at C startup and thread creation (v17) Mathieu Desnoyers
2020-04-27  9:11   ` Florian Weimer
2020-04-27 16:40     ` Mathieu Desnoyers
2020-04-27 16:54       ` Florian Weimer
2020-04-27 17:26         ` Mathieu Desnoyers
2020-04-27 20:27           ` Mathieu Desnoyers
2020-04-28 12:02           ` Florian Weimer
2020-04-28 12:33             ` Mathieu Desnoyers
2020-04-28 12:35               ` Florian Weimer
2020-04-28 12:43                 ` Mathieu Desnoyers
2020-04-28 12:54                   ` Florian Weimer
2020-04-28 14:58                     ` Mathieu Desnoyers
2020-04-29  8:16                       ` Szabolcs Nagy
2020-04-29  8:18                         ` Florian Weimer
2020-04-29  8:52                           ` Szabolcs Nagy
2020-04-29  9:01                             ` Florian Weimer
2020-04-29 12:57                               ` Mathieu Desnoyers
2020-04-30 10:40                                 ` Szabolcs Nagy
2020-04-30 19:04                                   ` Mathieu Desnoyers
2020-04-28 12:56               ` Mathieu Desnoyers
2020-04-29 12:19                 ` Florian Weimer
2020-04-27 11:59   ` Florian Weimer
2020-04-27 16:47     ` Mathieu Desnoyers
2020-04-27 16:59       ` Florian Weimer
2020-03-26 15:56 ` [PATCH glibc 6/9] glibc: sched_getcpu(): use rseq cpu_id TLS on Linux (v7) Mathieu Desnoyers
2020-04-27  9:13   ` Florian Weimer
2020-03-26 15:56 ` [PATCH glibc 7/9] support record failure: allow use from constructor Mathieu Desnoyers
2020-04-27 16:58   ` Florian Weimer
2020-04-27 17:49     ` Mathieu Desnoyers
2020-03-26 15:56 ` [PATCH glibc 8/9] support: implement xpthread key create/delete (v4) Mathieu Desnoyers
2020-04-27  9:17   ` Florian Weimer
2020-04-27 14:58     ` Mathieu Desnoyers
2020-04-27 15:23       ` Florian Weimer
2020-04-27 15:34         ` Mathieu Desnoyers
2020-04-27 17:00           ` Florian Weimer
2020-04-27 17:30             ` Mathieu Desnoyers
2020-03-26 15:56 ` [PATCH glibc 9/9] rseq registration tests (v9) Mathieu Desnoyers
2020-04-27 16:55   ` Florian Weimer
2020-04-27 17:48     ` Mathieu Desnoyers
2020-04-15 20:45 ` [PATCH glibc 0/9] Restartable Sequences enablement Mathieu Desnoyers
2020-04-22 16:27 ` Carlos O'Donell

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).