[glibc] aarch64: Fix static PIE CPU feature detection (BZ 34205)

Adhemerval Zanella via Glibc-cvs <[email protected]> Mon, 15 Jun 2026 17:41:58 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=6adb7400fd9de486b5fb3db799c9fabee1ab5786

commit 6adb7400fd9de486b5fb3db799c9fabee1ab5786
Author: Adhemerval Zanella <[email protected]>
Date:   Fri Jun 5 13:43:17 2026 +0000

    aarch64: Fix static PIE CPU feature detection (BZ 34205)
    
    ARCH_INIT_CPU_FEATURES is called from __libc_start_main before
    _dl_relocate_static_pie, so any code it runs must not rely on
    relocations being applied yet.  Two issues break this under static PIE:
    
      1. The cpu_list table held 'const char *name' members, whose
         addresses are not link-time constants under PIE and thus require
         base-relative relocations that are not yet in place.  Replace the
         array of structs with a flat NUL-separated name string and a
         parallel midr array, removing the pointer relocations.
    
      2. tunable_strcmp pulls in memcmp, which is an IFUNC and is likewise
         unresolved at this point.  Redirect memcmp to __memcmp_generic in
         the aarch64 dl-symbol-redir-ifunc.h and include it from
         csu/libc-start.c.
    
    Checked on aarch64-linux-gnu.
    
    Reviewed-by: Wilco Dijkstra  <[email protected]>

Diff:
---
 csu/libc-start.c                                   |  1 +
 sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h  |  1 +
 sysdeps/unix/sysv/linux/aarch64/Makefile           | 10 +++++++
 sysdeps/unix/sysv/linux/aarch64/cpu-features.c     | 35 ++++++++++++----------
 .../linux/aarch64/tst-cpu-tunable-static-pie.c     | 26 ++++++++++++++++
 5 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/csu/libc-start.c b/csu/libc-start.c
index 03d770ef15..28af53f7db 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -59,6 +59,7 @@ uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
 #ifndef SHARED
 # include <link.h>
 # include <dl-irel.h>
+# include <dl-symbol-redir-ifunc.h>
 
 # ifdef ELF_MACHINE_IRELA
 #  define IREL_T	ElfW(Rela)
diff --git a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
index 26fcd1977e..0910e321d2 100644
--- a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
+++ b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h
@@ -24,6 +24,7 @@ asm ("strlen = __strlen_generic");
 #ifndef SHARED
 asm ("memcpy = __memcpy_generic");
 asm ("memmove = __memmove_generic");
+asm ("memcmp = __memcmp_generic");
 #endif
 
 #endif
diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index 7e17e7741f..d1fcb48aa2 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -9,6 +9,16 @@ modules-names += \
 LDFLAGS-tst-tlsdesc-pac = -rdynamic
 
 $(objpfx)tst-tlsdesc-pac.out: $(objpfx)tst-tlsdesc-pac-mod.so
+
+ifeq (yes,$(enable-static-pie))
+tests += \
+  tst-cpu-tunable-static-pie \
+  # tests
+tests-static += \
+  tst-cpu-tunable-static-pie \
+  # tests-static
+tst-cpu-tunable-static-pie-TUNABLES = glibc.cpu.name=generic
+endif
 endif
 
 ifeq ($(subdir),misc)
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index 0bc4addb2a..9a87332ac4 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -33,29 +33,32 @@
    to see when pointer have been correctly tagged.  */
 #define MTE_ALLOWED_TAGS (0xfffe << PR_MTE_TAG_SHIFT)
 
-struct cpu_list
-{
-  const char *name;
-  size_t len;
-  uint64_t midr;
+static const char cpu_list_name[] = {
+  "kunpeng920\0"
+  "kunpeng950\0"
+  "a64fx\0"
+  "generic\0",
 };
 
-static const struct cpu_list cpu_list[] =
-{
-#define CPU_LIST_ENTRY(__str, __num) { __str, sizeof (__str) - 1, __num }
-  CPU_LIST_ENTRY ("kunpeng920",     0x481FD010),
-  CPU_LIST_ENTRY ("kunpeng950",     0x480FD060),
-  CPU_LIST_ENTRY ("a64fx",          0x460F0010),
-  CPU_LIST_ENTRY ("generic",        0x0),
+static const uint64_t cpu_list_midr[] = {
+  0x481FD010,
+  0x480FD060,
+  0x460F0010,
+  0x0,
 };
 
 static uint64_t
 get_midr_from_mcpu (const struct tunable_str_t *mcpu)
 {
-  for (int i = 0; i < array_length (cpu_list); i++)
-    if (tunable_strcmp (mcpu, cpu_list[i].name, cpu_list[i].len))
-      return cpu_list[i].midr;
-
+  const char *name = cpu_list_name;
+  size_t offset = 0;
+  for (int i = 0; i < array_length (cpu_list_midr); i++)
+    {
+      size_t len = strlen (name);
+      if (tunable_strcmp (mcpu, cpu_list_name + offset, len))
+	return cpu_list_midr[i];
+      offset += len;
+    }
   return UINT64_MAX;
 }
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c b/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c
new file mode 100644
index 0000000000..561eaf3bdb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-cpu-tunable-static-pie.c
@@ -0,0 +1,26 @@
+/* Test that the glibc.cpu.name tunable is parsed correctly during early
+   startup of a static PIE binary (bug 34205).
+   Copyright (C) 2026 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/>.  */
+
+static int
+do_test (void)
+{
+  return 0;
+}
+
+#include <support/test-driver.c>