08c3a6
commit 1cc4ddfeebdb68e0b6de7e4878eef94d3438706f
08c3a6
Author: Florian Weimer <fweimer@redhat.com>
08c3a6
Date:   Fri Feb 11 16:01:19 2022 +0100
08c3a6
08c3a6
    Revert "Linux: Consolidate auxiliary vector parsing"
08c3a6
    
08c3a6
    This reverts commit 8c8510ab2790039e58995ef3a22309582413d3ff.  The
08c3a6
    revert is not perfect because the commit included a bug fix for
08c3a6
    _dl_sysdep_start with an empty argv, introduced in commit
08c3a6
    2d47fa68628e831a692cba8fc9050cef435afc5e ("Linux: Remove
08c3a6
    DL_FIND_ARG_COMPONENTS"), and this bug fix is kept.
08c3a6
    
08c3a6
    The revert is necessary because the reverted commit introduced an
08c3a6
    early memset call on aarch64, which leads to crash due to lack of TCB
08c3a6
    initialization.
08c3a6
    
08c3a6
    (cherry picked from commit d96d2995c1121d3310102afda2deb1f35761b5e6)
08c3a6
08c3a6
diff --git a/elf/dl-support.c b/elf/dl-support.c
08c3a6
index 40ef07521336857d..f29dc965f4d10648 100644
08c3a6
--- a/elf/dl-support.c
08c3a6
+++ b/elf/dl-support.c
08c3a6
@@ -241,21 +241,93 @@ __rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
08c3a6
 
08c3a6
 
08c3a6
 #ifdef HAVE_AUX_VECTOR
08c3a6
-#include <dl-parse_auxv.h>
08c3a6
-
08c3a6
 int _dl_clktck;
08c3a6
 
08c3a6
 void
08c3a6
 _dl_aux_init (ElfW(auxv_t) *av)
08c3a6
 {
08c3a6
+  int seen = 0;
08c3a6
+  uid_t uid = 0;
08c3a6
+  gid_t gid = 0;
08c3a6
+
08c3a6
 #ifdef NEED_DL_SYSINFO
08c3a6
   /* NB: Avoid RELATIVE relocation in static PIE.  */
08c3a6
   GL(dl_sysinfo) = DL_SYSINFO_DEFAULT;
08c3a6
 #endif
08c3a6
 
08c3a6
   _dl_auxv = av;
08c3a6
-  dl_parse_auxv_t auxv_values = { 0, };
08c3a6
-  _dl_parse_auxv (av, auxv_values);
08c3a6
+  for (; av->a_type != AT_NULL; ++av)
08c3a6
+    switch (av->a_type)
08c3a6
+      {
08c3a6
+      case AT_PAGESZ:
08c3a6
+	if (av->a_un.a_val != 0)
08c3a6
+	  GLRO(dl_pagesize) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_CLKTCK:
08c3a6
+	GLRO(dl_clktck) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PHDR:
08c3a6
+	GL(dl_phdr) = (const void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PHNUM:
08c3a6
+	GL(dl_phnum) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PLATFORM:
08c3a6
+	GLRO(dl_platform) = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_HWCAP:
08c3a6
+	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_HWCAP2:
08c3a6
+	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_FPUCW:
08c3a6
+	GLRO(dl_fpu_control) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+#ifdef NEED_DL_SYSINFO
08c3a6
+      case AT_SYSINFO:
08c3a6
+	GL(dl_sysinfo) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+#endif
08c3a6
+#ifdef NEED_DL_SYSINFO_DSO
08c3a6
+      case AT_SYSINFO_EHDR:
08c3a6
+	GL(dl_sysinfo_dso) = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+#endif
08c3a6
+      case AT_UID:
08c3a6
+	uid ^= av->a_un.a_val;
08c3a6
+	seen |= 1;
08c3a6
+	break;
08c3a6
+      case AT_EUID:
08c3a6
+	uid ^= av->a_un.a_val;
08c3a6
+	seen |= 2;
08c3a6
+	break;
08c3a6
+      case AT_GID:
08c3a6
+	gid ^= av->a_un.a_val;
08c3a6
+	seen |= 4;
08c3a6
+	break;
08c3a6
+      case AT_EGID:
08c3a6
+	gid ^= av->a_un.a_val;
08c3a6
+	seen |= 8;
08c3a6
+	break;
08c3a6
+      case AT_SECURE:
08c3a6
+	seen = -1;
08c3a6
+	__libc_enable_secure = av->a_un.a_val;
08c3a6
+	__libc_enable_secure_decided = 1;
08c3a6
+	break;
08c3a6
+      case AT_RANDOM:
08c3a6
+	_dl_random = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_MINSIGSTKSZ:
08c3a6
+	_dl_minsigstacksize = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      DL_PLATFORM_AUXV
08c3a6
+      }
08c3a6
+  if (seen == 0xf)
08c3a6
+    {
08c3a6
+      __libc_enable_secure = uid != 0 || gid != 0;
08c3a6
+      __libc_enable_secure_decided = 1;
08c3a6
+    }
08c3a6
 }
08c3a6
 #endif
08c3a6
 
08c3a6
diff --git a/sysdeps/unix/sysv/linux/alpha/dl-auxv.h b/sysdeps/unix/sysv/linux/alpha/dl-auxv.h
08c3a6
index 8c99e776a0af9cef..1aa9dca80d189ebe 100644
08c3a6
--- a/sysdeps/unix/sysv/linux/alpha/dl-auxv.h
08c3a6
+++ b/sysdeps/unix/sysv/linux/alpha/dl-auxv.h
08c3a6
@@ -20,8 +20,16 @@
08c3a6
 
08c3a6
 extern long __libc_alpha_cache_shape[4];
08c3a6
 
08c3a6
-#define DL_PLATFORM_AUXV					\
08c3a6
-  __libc_alpha_cache_shape[0] = auxv_values[AT_L1I_CACHESHAPE]; \
08c3a6
-  __libc_alpha_cache_shape[1] = auxv_values[AT_L1D_CACHESHAPE]; \
08c3a6
-  __libc_alpha_cache_shape[2] = auxv_values[AT_L2_CACHESHAPE];	\
08c3a6
-  __libc_alpha_cache_shape[3] = auxv_values[AT_L3_CACHESHAPE];
08c3a6
+#define DL_PLATFORM_AUXV				\
08c3a6
+      case AT_L1I_CACHESHAPE:				\
08c3a6
+	__libc_alpha_cache_shape[0] = av->a_un.a_val;	\
08c3a6
+	break;						\
08c3a6
+      case AT_L1D_CACHESHAPE:				\
08c3a6
+	__libc_alpha_cache_shape[1] = av->a_un.a_val;	\
08c3a6
+	break;						\
08c3a6
+      case AT_L2_CACHESHAPE:				\
08c3a6
+	__libc_alpha_cache_shape[2] = av->a_un.a_val;	\
08c3a6
+	break;						\
08c3a6
+      case AT_L3_CACHESHAPE:				\
08c3a6
+	__libc_alpha_cache_shape[3] = av->a_un.a_val;	\
08c3a6
+	break;
08c3a6
diff --git a/sysdeps/unix/sysv/linux/dl-parse_auxv.h b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
08c3a6
deleted file mode 100644
08c3a6
index b3d82f69946d6d2c..0000000000000000
08c3a6
--- a/sysdeps/unix/sysv/linux/dl-parse_auxv.h
08c3a6
+++ /dev/null
08c3a6
@@ -1,61 +0,0 @@
08c3a6
-/* Parse the Linux auxiliary vector.
08c3a6
-   Copyright (C) 1995-2022 Free Software Foundation, Inc.
08c3a6
-   This file is part of the GNU C Library.
08c3a6
-
08c3a6
-   The GNU C Library is free software; you can redistribute it and/or
08c3a6
-   modify it under the terms of the GNU Lesser General Public
08c3a6
-   License as published by the Free Software Foundation; either
08c3a6
-   version 2.1 of the License, or (at your option) any later version.
08c3a6
-
08c3a6
-   The GNU C Library is distributed in the hope that it will be useful,
08c3a6
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
08c3a6
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
08c3a6
-   Lesser General Public License for more details.
08c3a6
-
08c3a6
-   You should have received a copy of the GNU Lesser General Public
08c3a6
-   License along with the GNU C Library; if not, see
08c3a6
-   <https://www.gnu.org/licenses/>.  */
08c3a6
-
08c3a6
-#include <elf.h>
08c3a6
-#include <entry.h>
08c3a6
-#include <fpu_control.h>
08c3a6
-#include <ldsodefs.h>
08c3a6
-#include <link.h>
08c3a6
-
08c3a6
-typedef ElfW(Addr) dl_parse_auxv_t[AT_MINSIGSTKSZ + 1];
08c3a6
-
08c3a6
-/* Copy the auxiliary vector into AUX_VALUES and set up GLRO
08c3a6
-   variables.  */
08c3a6
-static inline
08c3a6
-void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
08c3a6
-{
08c3a6
-  auxv_values[AT_ENTRY] = (ElfW(Addr)) ENTRY_POINT;
08c3a6
-  auxv_values[AT_PAGESZ] = EXEC_PAGESIZE;
08c3a6
-  auxv_values[AT_FPUCW] = _FPU_DEFAULT;
08c3a6
-
08c3a6
-  /* NB: Default to a constant CONSTANT_MINSIGSTKSZ.  */
08c3a6
-  _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
08c3a6
-                  "CONSTANT_MINSIGSTKSZ is constant");
08c3a6
-  auxv_values[AT_MINSIGSTKSZ] = CONSTANT_MINSIGSTKSZ;
08c3a6
-
08c3a6
-  for (; av->a_type != AT_NULL; av++)
08c3a6
-    if (av->a_type <= AT_MINSIGSTKSZ)
08c3a6
-      auxv_values[av->a_type] = av->a_un.a_val;
08c3a6
-
08c3a6
-  GLRO(dl_pagesize) = auxv_values[AT_PAGESZ];
08c3a6
-  __libc_enable_secure = auxv_values[AT_SECURE];
08c3a6
-  GLRO(dl_platform) = (void *) auxv_values[AT_PLATFORM];
08c3a6
-  GLRO(dl_hwcap) = auxv_values[AT_HWCAP];
08c3a6
-  GLRO(dl_hwcap2) = auxv_values[AT_HWCAP2];
08c3a6
-  GLRO(dl_clktck) = auxv_values[AT_CLKTCK];
08c3a6
-  GLRO(dl_fpu_control) = auxv_values[AT_FPUCW];
08c3a6
-  _dl_random = (void *) auxv_values[AT_RANDOM];
08c3a6
-  GLRO(dl_minsigstacksize) = auxv_values[AT_MINSIGSTKSZ];
08c3a6
-  GLRO(dl_sysinfo_dso) = (void *) auxv_values[AT_SYSINFO_EHDR];
08c3a6
-#ifdef NEED_DL_SYSINFO
08c3a6
-  if (GLRO(dl_sysinfo_dso) != NULL)
08c3a6
-    GLRO(dl_sysinfo) = auxv_values[AT_SYSINFO];
08c3a6
-#endif
08c3a6
-
08c3a6
-  DL_PLATFORM_AUXV
08c3a6
-}
08c3a6
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
08c3a6
index 80aa9f6f4acb7e3c..facaaba3b9d091b3 100644
08c3a6
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
08c3a6
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
08c3a6
@@ -21,12 +21,13 @@
08c3a6
 #include <dl-auxv.h>
08c3a6
 #include <dl-hwcap-check.h>
08c3a6
 #include <dl-osinfo.h>
08c3a6
-#include <dl-parse_auxv.h>
08c3a6
 #include <dl-procinfo.h>
08c3a6
 #include <dl-tunables.h>
08c3a6
 #include <elf.h>
08c3a6
+#include <entry.h>
08c3a6
 #include <errno.h>
08c3a6
 #include <fcntl.h>
08c3a6
+#include <fpu_control.h>
08c3a6
 #include <ldsodefs.h>
08c3a6
 #include <libc-internal.h>
08c3a6
 #include <libintl.h>
08c3a6
@@ -62,20 +63,20 @@ void *_dl_random attribute_relro = NULL;
08c3a6
 # define DL_STACK_END(cookie) ((void *) (cookie))
08c3a6
 #endif
08c3a6
 
08c3a6
-/* Arguments passed to dl_main.  */
08c3a6
-struct dl_main_arguments
08c3a6
+ElfW(Addr)
08c3a6
+_dl_sysdep_start (void **start_argptr,
08c3a6
+		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
08c3a6
+				   ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
08c3a6
 {
08c3a6
-  const ElfW(Phdr) *phdr;
08c3a6
-  ElfW(Word) phnum;
08c3a6
+  const ElfW(Phdr) *phdr = NULL;
08c3a6
+  ElfW(Word) phnum = 0;
08c3a6
   ElfW(Addr) user_entry;
08c3a6
-};
08c3a6
+  ElfW(auxv_t) *av;
08c3a6
+#ifdef NEED_DL_SYSINFO
08c3a6
+  uintptr_t new_sysinfo = 0;
08c3a6
+#endif
08c3a6
 
08c3a6
-/* Separate function, so that dl_main can be called without the large
08c3a6
-   array on the stack.  */
08c3a6
-static void
08c3a6
-_dl_sysdep_parse_arguments (void **start_argptr,
08c3a6
-			    struct dl_main_arguments *args)
08c3a6
-{
08c3a6
+  __libc_stack_end = DL_STACK_END (start_argptr);
08c3a6
   _dl_argc = (intptr_t) *start_argptr;
08c3a6
   _dl_argv = (char **) (start_argptr + 1); /* Necessary aliasing violation.  */
08c3a6
   _environ = _dl_argv + _dl_argc + 1;
08c3a6
@@ -87,26 +88,75 @@ _dl_sysdep_parse_arguments (void **start_argptr,
08c3a6
 	break;
08c3a6
       }
08c3a6
 
08c3a6
-  dl_parse_auxv_t auxv_values = { 0, };
08c3a6
-  _dl_parse_auxv (GLRO(dl_auxv), auxv_values);
08c3a6
+  user_entry = (ElfW(Addr)) ENTRY_POINT;
08c3a6
+  GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
08c3a6
 
08c3a6
-  args->phdr = (const ElfW(Phdr) *) auxv_values[AT_PHDR];
08c3a6
-  args->phnum = auxv_values[AT_PHNUM];
08c3a6
-  args->user_entry = auxv_values[AT_ENTRY];
08c3a6
-}
08c3a6
+  /* NB: Default to a constant CONSTANT_MINSIGSTKSZ.  */
08c3a6
+  _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
08c3a6
+		  "CONSTANT_MINSIGSTKSZ is constant");
08c3a6
+  GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
08c3a6
 
08c3a6
-ElfW(Addr)
08c3a6
-_dl_sysdep_start (void **start_argptr,
08c3a6
-		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
08c3a6
-				   ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
08c3a6
-{
08c3a6
-  __libc_stack_end = DL_STACK_END (start_argptr);
08c3a6
-
08c3a6
-  struct dl_main_arguments dl_main_args;
08c3a6
-  _dl_sysdep_parse_arguments (start_argptr, &dl_main_args);
08c3a6
+  for (av = GLRO(dl_auxv); av->a_type != AT_NULL; av++)
08c3a6
+    switch (av->a_type)
08c3a6
+      {
08c3a6
+      case AT_PHDR:
08c3a6
+	phdr = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PHNUM:
08c3a6
+	phnum = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PAGESZ:
08c3a6
+	GLRO(dl_pagesize) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_ENTRY:
08c3a6
+	user_entry = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_SECURE:
08c3a6
+	__libc_enable_secure = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_PLATFORM:
08c3a6
+	GLRO(dl_platform) = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_HWCAP:
08c3a6
+	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_HWCAP2:
08c3a6
+	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_CLKTCK:
08c3a6
+	GLRO(dl_clktck) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_FPUCW:
08c3a6
+	GLRO(dl_fpu_control) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+#ifdef NEED_DL_SYSINFO
08c3a6
+      case AT_SYSINFO:
08c3a6
+	new_sysinfo = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+#endif
08c3a6
+      case AT_SYSINFO_EHDR:
08c3a6
+	GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_RANDOM:
08c3a6
+	_dl_random = (void *) av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      case AT_MINSIGSTKSZ:
08c3a6
+	GLRO(dl_minsigstacksize) = av->a_un.a_val;
08c3a6
+	break;
08c3a6
+      DL_PLATFORM_AUXV
08c3a6
+      }
08c3a6
 
08c3a6
   dl_hwcap_check ();
08c3a6
 
08c3a6
+#ifdef NEED_DL_SYSINFO
08c3a6
+  if (new_sysinfo != 0)
08c3a6
+    {
08c3a6
+      /* Only set the sysinfo value if we also have the vsyscall DSO.  */
08c3a6
+      if (GLRO(dl_sysinfo_dso) != 0)
08c3a6
+        GLRO(dl_sysinfo) = new_sysinfo;
08c3a6
+    }
08c3a6
+#endif
08c3a6
+
08c3a6
   __tunables_init (_environ);
08c3a6
 
08c3a6
   /* Initialize DSO sorting algorithm after tunables.  */
08c3a6
@@ -137,9 +187,8 @@ _dl_sysdep_start (void **start_argptr,
08c3a6
   if (__builtin_expect (__libc_enable_secure, 0))
08c3a6
     __libc_check_standard_fds ();
08c3a6
 
08c3a6
-  (*dl_main) (dl_main_args.phdr, dl_main_args.phnum,
08c3a6
-              &dl_main_args.user_entry, GLRO(dl_auxv));
08c3a6
-  return dl_main_args.user_entry;
08c3a6
+  (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
08c3a6
+  return user_entry;
08c3a6
 }
08c3a6
 
08c3a6
 void
08c3a6
diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-auxv.h b/sysdeps/unix/sysv/linux/powerpc/dl-auxv.h
08c3a6
index 7f35fb531ba22098..36ba0f3e9e45f3e2 100644
08c3a6
--- a/sysdeps/unix/sysv/linux/powerpc/dl-auxv.h
08c3a6
+++ b/sysdeps/unix/sysv/linux/powerpc/dl-auxv.h
08c3a6
@@ -16,5 +16,15 @@
08c3a6
    License along with the GNU C Library; if not, see
08c3a6
    <https://www.gnu.org/licenses/>.  */
08c3a6
 
08c3a6
-#define DL_PLATFORM_AUXV \
08c3a6
-  GLRO(dl_cache_line_size) = auxv_values[AT_DCACHEBSIZE];
08c3a6
+#include <ldsodefs.h>
08c3a6
+
08c3a6
+#if IS_IN (libc) && !defined SHARED
08c3a6
+int GLRO(dl_cache_line_size);
08c3a6
+#endif
08c3a6
+
08c3a6
+/* Scan the Aux Vector for the "Data Cache Block Size" entry and assign it
08c3a6
+   to dl_cache_line_size.  */
08c3a6
+#define DL_PLATFORM_AUXV						      \
08c3a6
+      case AT_DCACHEBSIZE:						      \
08c3a6
+	GLRO(dl_cache_line_size) = av->a_un.a_val;			      \
08c3a6
+	break;
08c3a6
diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-support.c b/sysdeps/unix/sysv/linux/powerpc/dl-support.c
08c3a6
deleted file mode 100644
08c3a6
index abe68a704946b90f..0000000000000000
08c3a6
--- a/sysdeps/unix/sysv/linux/powerpc/dl-support.c
08c3a6
+++ /dev/null
08c3a6
@@ -1,4 +0,0 @@
08c3a6
-#include <elf/dl-support.c>
08c3a6
-
08c3a6
-/* Populated from the auxiliary vector.  */
08c3a6
-int _dl_cache_line_size;