[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>