From 99e9c5d1ca14cc2a336462258b26f3ab85027147 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Tue, 28 Jul 2026 18:13:21 -0300 Subject: [PATCH] Fix assert during static startup (BZ 33326) The BZ#33326 testcase triggers an assertion during process startup, which results in a segmentation fault instead of an error message and process termination with a SIGABRT. The assert issues __libc_message_impl, which in turn might call string functions depending on the ABI (strchrnul, strlen, memcpy/mempcpy), system calls (writev and mmap), and finally the abort call. The dl-symbol-redir-ifunc.h is also expanded to cover strchrnul on x86_64, s390, powerpc64 (both endianness) and loongarch, mempcpy on powerpc64be, and memcpy on aarch64. On s390 the redirection is only issued if the ifunc variant is built, since strchrnul-c.c only renames the C implementation to STRCHRNUL_DEFAULT when HAVE_STRCHRNUL_IFUNC is set. The buffer that backs up the assert message is now allocated through _dl_mmap, which issues the syscall directly instead of calling __mmap (setting errno on failure requires the thread pointer). The abort call now issues __raise_direct instead of raise (the Hurd port aliases __raise_direct to raise). On i386, syscalls should not use the vDSO during program startup because the thread pointer is not yet initialized. This requires __raise_direct, _dl_writev, and _dl_mmap to be built with I386_USE_SYSENTER set to 0. Creating a test case is challenging. For static-pie, the assert is only called for ill-formed ELF files on elf_get_dynamic_info and by some targets on ELF_DYNAMIC_RELOCATE (although not all targets use assert in their dl-machine.h). Some targets also issue __libc_fatal on ARCH_SETUP_IREL, but also only for ill-formatted ELF files. The test employs a different strategy and overrides the __tunables_init symbol, which is invoked immediately before self-relocation and TLS setup. The test is built with -Wl,-z,muldefs to avoid linker issues. I checked on aarch64, x86_64, i686, s390x (qemu), sparc (qemu), mips64el (qemu), armhf, riscv, and powerpc. Reviewed-by: Florian Weimer --- assert/Makefile | 5 +++ elf/Makefile | 12 ++++++ elf/tst-assert-startup-static.c | 43 +++++++++++++++++++ libio/Makefile | 5 +++ stdlib/Makefile | 5 +++ stdlib/abort.c | 2 +- string/Makefile | 22 +++++++--- .../aarch64/multiarch/dl-symbol-redir-ifunc.h | 2 +- sysdeps/aarch64/multiarch/memcpy_generic.S | 4 ++ sysdeps/generic/dl-mmap.h | 37 ++++++++++++++++ sysdeps/htl/raise.c | 2 + .../lp64/multiarch/dl-symbol-redir-ifunc.h | 1 + sysdeps/posix/libc_fatal.c | 12 ++++-- .../powerpc32/power4/multiarch/Makefile | 5 +++ .../be/multiarch/dl-symbol-redir-ifunc.h | 27 ++++++++++++ .../le/multiarch/dl-symbol-redir-ifunc.h | 1 + sysdeps/powerpc/powerpc64/multiarch/Makefile | 5 ++- sysdeps/s390/Makefile | 5 +++ .../s390/multiarch/dl-symbol-redir-ifunc.h | 5 +++ sysdeps/s390/string-bitops.h | 28 ++++++++++++ sysdeps/unix/sysv/linux/Makefile | 12 ++++++ sysdeps/unix/sysv/linux/dl-mmap.h | 40 +++++++++++++++++ sysdeps/unix/sysv/linux/i386/Makefile | 14 ++++++ sysdeps/unix/sysv/linux/i386/dl-mmap.c | 38 ++++++++++++++++ sysdeps/unix/sysv/linux/i386/dl-mmap.h | 27 ++++++++++++ sysdeps/unix/sysv/linux/i386/dl-writev.c | 32 ++++++++++++++ sysdeps/unix/sysv/linux/i386/dl-writev.h | 15 ++++--- sysdeps/unix/sysv/linux/i386/raise_direct.c | 26 +++++++++++ .../unix/sysv/linux/riscv/multiarch/Makefile | 12 ++++-- .../x86_64/multiarch/dl-symbol-redir-ifunc.h | 18 ++++++-- 30 files changed, 437 insertions(+), 25 deletions(-) create mode 100644 elf/tst-assert-startup-static.c create mode 100644 sysdeps/generic/dl-mmap.h create mode 100644 sysdeps/powerpc/powerpc64/be/multiarch/dl-symbol-redir-ifunc.h create mode 100644 sysdeps/s390/string-bitops.h create mode 100644 sysdeps/unix/sysv/linux/dl-mmap.h create mode 100644 sysdeps/unix/sysv/linux/i386/dl-mmap.c create mode 100644 sysdeps/unix/sysv/linux/i386/dl-mmap.h create mode 100644 sysdeps/unix/sysv/linux/i386/dl-writev.c create mode 100644 sysdeps/unix/sysv/linux/i386/raise_direct.c diff --git a/assert/Makefile b/assert/Makefile index 4c253a344a..541929c3b6 100644 --- a/assert/Makefile +++ b/assert/Makefile @@ -33,6 +33,11 @@ routines := \ assert-perr \ # routines +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-__libc_assert_fail.o = $(no-stack-protector) +CFLAGS-__libc_assert_fail.op = $(no-stack-protector) + tests := \ test-assert \ test-assert-2 \ diff --git a/elf/Makefile b/elf/Makefile index 9ed57f1c29..8cd80b25f4 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -280,6 +280,7 @@ tests-static-normal := \ # tests-static-normal tests-static-internal := \ + tst-assert-startup-static \ tst-atrandom-scrub-static \ tst-dl-printf-static \ tst-dl_find_object-static \ @@ -3778,3 +3779,14 @@ $(objpfx)tst-dl-debug-exclude.out: tst-dl-debug-exclude.sh \ $(objpfx)tst-recursive-tls > $@; \ $(evaluate-test) endif + +CFLAGS-tst-assert-startup-static.c += $(no-stack-protector) +LDFLAGS-tst-assert-startup-static += -Wl,-z,muldefs + +$(objpfx)tst-assert-startup-static.out: $(objpfx)tst-assert-startup-static + $(test-program-cmd-before-env) \ + $(run-program-env) \ + $< > $@ 2>&1; echo "status: $$?" >> $@; \ + grep -q 'Fatal glibc error: tst-assert-startup-static' $@ \ + && grep -q '^status: 134$$' $@; \ + $(evaluate-test) diff --git a/elf/tst-assert-startup-static.c b/elf/tst-assert-startup-static.c new file mode 100644 index 0000000000..e8f9a4b990 --- /dev/null +++ b/elf/tst-assert-startup-static.c @@ -0,0 +1,43 @@ +/* Check if assert works during program startup. + 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 + . */ + +#include +#include + +/* The __libc_assert_fail is used internally for assert() calls. */ +extern _Noreturn __typeof (__assert_fail) __libc_assert_fail; + +/* The __tunables_init is called just before self-relocation and TLS setup, + so overriding it is a way to reach the assert code at that point. */ +void +__tunables_init (char **env, char **argv) +{ + /* Inside libc, assert() is redirected to __libc_assert_fail. This test is + not built as part of libc, so a plain assert() here would call the public + __assert_fail instead, which uses __progname and the translation routines + and thus is not what the startup code issues. Call the internal routine + directly. */ + __libc_assert_fail ("error", __FILE__, __LINE__, __func__); +} + +int +main (void) +{ + /* Fail with a different error code than abort. */ + exit (EXIT_FAILURE); +} diff --git a/libio/Makefile b/libio/Makefile index 616107ee10..09b1b907dc 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -195,6 +195,11 @@ endif CPPFLAGS += $(libio-mtsafe) +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-libc_fatal.o = $(no-stack-protector) +CFLAGS-libc_fatal.op = $(no-stack-protector) + # Support for exception handling. CFLAGS-fileops.c += -fexceptions CFLAGS-fputc.c += -fexceptions diff --git a/stdlib/Makefile b/stdlib/Makefile index 16948eb512..ca38aaecaf 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -531,6 +531,11 @@ generated += \ tst-putenvmod.so \ # generated +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-abort.o = $(no-stack-protector) +CFLAGS-abort.op = $(no-stack-protector) + CFLAGS-bsearch.c += $(uses-callbacks) CFLAGS-qsort.c += $(uses-callbacks) CFLAGS-system.c += -fexceptions diff --git a/stdlib/abort.c b/stdlib/abort.c index cf6eb3eb99..c868635fe9 100644 --- a/stdlib/abort.c +++ b/stdlib/abort.c @@ -74,7 +74,7 @@ __abort_lock_unlock (const internal_sigset_t *set) _Noreturn void abort (void) { - raise (SIGABRT); + __raise_direct (SIGABRT); /* There is a SIGABRT handle installed and it returned, or SIGABRT was blocked or ignored. In this case use a AS-safe lock to prevent sigaction diff --git a/string/Makefile b/string/Makefile index 503d32e037..46087828da 100644 --- a/string/Makefile +++ b/string/Makefile @@ -286,13 +286,21 @@ CFLAGS-test-endian-sign-conversion.c += -Werror -Wsign-conversion LDFLAGS-tst-xbzero-opt = -z now LDFLAGS-tst-xmemset-opt = -z now -# Called during TLS initialization. -CFLAGS-memcpy.c += $(no-stack-protector) -CFLAGS-wordcopy.c += $(no-stack-protector) -# Called during static initialization -CFLAGS-strncmp.c += $(no-stack-protector) -CFLAGS-memset.c += $(no-stack-protector) -CFLAGS-strlen.c += $(no-stack-protector) +# Called during TLS initialization, and during static library initialization. +CFLAGS-memcpy.o = $(no-stack-protector) +CFLAGS-memcpy.op = $(no-stack-protector) +CFLAGS-wordcopy.o = $(no-stack-protector) +CFLAGS-wordcopy.op = $(no-stack-protector) +CFLAGS-strncmp.o = $(no-stack-protector) +CFLAGS-strncmp.op = $(no-stack-protector) +CFLAGS-memset.o = $(no-stack-protector) +CFLAGS-memset.op = $(no-stack-protector) +CFLAGS-strlen.o = $(no-stack-protector) +CFLAGS-strlen.op = $(no-stack-protector) +CFLAGS-strchrnul.o = $(no-stack-protector) +CFLAGS-strchrnul.op = $(no-stack-protector) +CFLAGS-mempcpy.o = $(no-stack-protector) +CFLAGS-mempcpy.op = $(no-stack-protector) ifeq ($(run-built-tests),yes) $(objpfx)tst-svc-cmp.out: tst-svc.expect $(objpfx)tst-svc.out diff --git a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h index 0910e321d2..dcf2d5fb62 100644 --- a/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h +++ b/sysdeps/aarch64/multiarch/dl-symbol-redir-ifunc.h @@ -19,10 +19,10 @@ #ifndef _DL_IFUNC_GENERIC_H #define _DL_IFUNC_GENERIC_H +asm ("memcpy = __memcpy_generic"); asm ("memset = __memset_generic"); asm ("strlen = __strlen_generic"); #ifndef SHARED -asm ("memcpy = __memcpy_generic"); asm ("memmove = __memmove_generic"); asm ("memcmp = __memcmp_generic"); #endif diff --git a/sysdeps/aarch64/multiarch/memcpy_generic.S b/sysdeps/aarch64/multiarch/memcpy_generic.S index c6d09081f4..d622268305 100644 --- a/sysdeps/aarch64/multiarch/memcpy_generic.S +++ b/sysdeps/aarch64/multiarch/memcpy_generic.S @@ -42,3 +42,7 @@ #endif #include "../memcpy.S" + +#if IS_IN (rtld) +strong_alias (memcpy, __memcpy_generic) +#endif diff --git a/sysdeps/generic/dl-mmap.h b/sysdeps/generic/dl-mmap.h new file mode 100644 index 0000000000..b578d56ce4 --- /dev/null +++ b/sysdeps/generic/dl-mmap.h @@ -0,0 +1,37 @@ +/* mmap wrapper for early static startup. + 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 + . */ + +#ifndef _DL_MMAP_H +#define _DL_MMAP_H + +#include + +/* This mmap call is used to allocate some memory to backup assert() messages + before TLS setup is done (which setup the thread pointer used by some ABIs + to issue syscalls). There is no portable way to issue the syscall without + going through the errno setting, so a port that needs to run this before + the thread pointer is available has to override this header (as Linux + does). */ + +static inline void * +_dl_mmap (void *addr, size_t len, int prot, int flags) +{ + return __mmap (addr, len, prot, flags, -1, 0); +} + +#endif diff --git a/sysdeps/htl/raise.c b/sysdeps/htl/raise.c index 3200f91634..a369ca17f6 100644 --- a/sysdeps/htl/raise.c +++ b/sysdeps/htl/raise.c @@ -54,3 +54,5 @@ raise (int signo) libc_hidden_def (raise) weak_alias (raise, gsignal) + +strong_alias (raise, __raise_direct) diff --git a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h index 1cd204c2f6..d2c875533a 100644 --- a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h +++ b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h @@ -22,6 +22,7 @@ #ifndef SHARED asm ("memset = __memset_aligned"); asm ("memcmp = __memcmp_aligned"); +asm ("__strchrnul = __strchrnul_aligned"); asm ("strlen = __strlen_aligned"); asm ("memcpy = __memcpy_unaligned"); asm ("memmove = __memmove_unaligned"); diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c index 3f0e302b5e..1ff20d4feb 100644 --- a/sysdeps/posix/libc_fatal.c +++ b/sysdeps/posix/libc_fatal.c @@ -16,7 +16,12 @@ License along with the GNU C Library; if not, see . */ +/* Mark symbols hidden in static PIE for early self relocation to work. */ +#if BUILD_PIE_DEFAULT +# pragma GCC visibility push(hidden) +#endif #include +#include #include #include #include @@ -24,6 +29,7 @@ #include #include #include +#include #ifdef FATAL_PREPARE_INCLUDE #include FATAL_PREPARE_INCLUDE @@ -113,9 +119,9 @@ __libc_message_impl (const char *vma_name, const char *fmt, ...) total = ALIGN_UP (total + sizeof (struct abort_msg_s) + 1, GLRO(dl_pagesize)); - struct abort_msg_s *buf = __mmap (NULL, total, - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); + struct abort_msg_s *buf = _dl_mmap (NULL, total, + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE); if (__glibc_likely (buf != MAP_FAILED)) { buf->size = total; diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/Makefile b/sysdeps/powerpc/powerpc32/power4/multiarch/Makefile index 3a49b855ca..60ba2e50d2 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/Makefile +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/Makefile @@ -11,4 +11,9 @@ sysdep_routines += memcpy-power7 memcpy-a2 memcpy-power6 memcpy-cell \ strchr-power7 strchr-ppc32 \ wordcopy-power7 wordcopy-ppc32 \ memmove-power7 memmove-ppc + +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-strchrnul-ppc32.o = $(no-stack-protector) +CFLAGS-strchrnul-ppc32.op = $(no-stack-protector) endif diff --git a/sysdeps/powerpc/powerpc64/be/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/powerpc/powerpc64/be/multiarch/dl-symbol-redir-ifunc.h new file mode 100644 index 0000000000..75bd82eab3 --- /dev/null +++ b/sysdeps/powerpc/powerpc64/be/multiarch/dl-symbol-redir-ifunc.h @@ -0,0 +1,27 @@ +/* Symbol redirection for loader/static initialization code. + 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 + . */ + +#ifndef _DL_IFUNC_GENERIC_H +#define _DL_IFUNC_GENERIC_H + +#ifndef SHARED +asm ("__mempcpy = __mempcpy_ppc"); +asm ("__strchrnul = __strchrnul_ppc"); +#endif + +#endif diff --git a/sysdeps/powerpc/powerpc64/le/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/powerpc/powerpc64/le/multiarch/dl-symbol-redir-ifunc.h index 4680092cd8..03f6f12032 100644 --- a/sysdeps/powerpc/powerpc64/le/multiarch/dl-symbol-redir-ifunc.h +++ b/sysdeps/powerpc/powerpc64/le/multiarch/dl-symbol-redir-ifunc.h @@ -21,5 +21,6 @@ asm ("memset = __memset_power8"); asm ("__mempcpy = __mempcpy_power7"); +asm ("__strchrnul = __strchrnul_power8"); #endif diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile index ca09203b29..94e99646a4 100644 --- a/sysdeps/powerpc/powerpc64/multiarch/Makefile +++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile @@ -39,4 +39,7 @@ endif endif # Called during static initialization -CFLAGS-strncmp-ppc64.c += $(no-stack-protector) +CFLAGS-strncmp-ppc64.o = $(no-stack-protector) +CFLAGS-strncmp-ppc64.op = $(no-stack-protector) +CFLAGS-strchrnul-ppc64.o = $(no-stack-protector) +CFLAGS-strchrnul-ppc64.op = $(no-stack-protector) diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile index 309425c7e1..c45c690986 100644 --- a/sysdeps/s390/Makefile +++ b/sysdeps/s390/Makefile @@ -259,6 +259,11 @@ routines_no_fortify += \ strcat-c \ strncat-c \ # routines_no_fortify + +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-strchrnul-c.o = $(no-stack-protector) +CFLAGS-strchrnul-c.op = $(no-stack-protector) endif ifeq ($(subdir),wcsmbs) diff --git a/sysdeps/s390/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/s390/multiarch/dl-symbol-redir-ifunc.h index a128cd05bd..b2ddcac421 100644 --- a/sysdeps/s390/multiarch/dl-symbol-redir-ifunc.h +++ b/sysdeps/s390/multiarch/dl-symbol-redir-ifunc.h @@ -21,6 +21,7 @@ #include #include +#include #define IFUNC_SYMBOL_STR1(s) #s #define IFUNC_SYMBOL_STR(s) IFUNC_SYMBOL_STR1(s) @@ -28,4 +29,8 @@ asm ("memset = " IFUNC_SYMBOL_STR(MEMSET_DEFAULT)); asm ("memcmp = " IFUNC_SYMBOL_STR(MEMCMP_DEFAULT)); +#if HAVE_STRCHRNUL_IFUNC +asm ("__strchrnul = " IFUNC_SYMBOL_STR(STRCHRNUL_DEFAULT)); +#endif + #endif diff --git a/sysdeps/s390/string-bitops.h b/sysdeps/s390/string-bitops.h new file mode 100644 index 0000000000..e81126c807 --- /dev/null +++ b/sysdeps/s390/string-bitops.h @@ -0,0 +1,28 @@ +/* Zero byte detection, define whether to use stdbit.h s390 version. + 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 + . */ + +/* s390x supports static-pie, and the libgcc implementation for + __builtin_clzl/__builtin_ctzl (__clzdi2) accesses extern data (__clz_tab) + that is not marked as hidden, which creates an additional GOT access. The + generic strchrnul is used before self-relocation, so the GOT entry can not + be resolved yet. */ +#if __ARCH__ > 6 +# define HAVE_BITOPTS_WORKING 1 +#else +# define HAVE_BITOPTS_WORKING 0 +#endif diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 4e49b367c4..1b15cdc53e 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -115,6 +115,11 @@ sysdep_routines += \ xstat64 \ # sysdep_routines +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-setvmaname.o = $(no-stack-protector) +CFLAGS-setvmaname.op = $(no-stack-protector) + CFLAGS-gethostid.c = -fexceptions CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-vmsplice.c = -fexceptions -fasynchronous-unwind-tables @@ -459,6 +464,13 @@ sysdep_routines += \ raise_direct \ # sysdep_routines +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-raise.o = $(no-stack-protector) +CFLAGS-raise.op = $(no-stack-protector) +CFLAGS-raise_direct.o = $(no-stack-protector) +CFLAGS-raise_direct.op = $(no-stack-protector) + tests-special += \ $(objpfx)tst-signal-numbers.out \ # tests-special diff --git a/sysdeps/unix/sysv/linux/dl-mmap.h b/sysdeps/unix/sysv/linux/dl-mmap.h new file mode 100644 index 0000000000..c78a124900 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-mmap.h @@ -0,0 +1,40 @@ +/* mmap wrapper for early static startup. Linux version. + 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 + . */ + +#ifndef _DL_MMAP_H +#define _DL_MMAP_H + +#include +#include +#include + +static inline void * +_dl_mmap (void *addr, size_t len, int prot, int flags) +{ + long int ret; +#ifdef __NR_mmap2 + ret = MMAP_CALL_INTERNAL (mmap2, addr, len, prot, flags, -1, 0); +#else + ret = MMAP_CALL_INTERNAL (mmap, addr, len, prot, flags, -1, 0); +#endif + if (INTERNAL_SYSCALL_ERROR_P (ret)) + return MAP_FAILED; + return (void *) ret; +} + +#endif diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index f1f8c3f44c..9a70905df8 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -28,3 +28,17 @@ ifeq ($(subdir),rt) librt-routines += sysdep librt-shared-only-routines += sysdep endif + +ifeq ($(subdir),elf) +sysdep_routines += \ + dl-mmap \ + dl-writev \ + # sysdep-routines + +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-dl-mmap.o = $(no-stack-protector) +CFLAGS-dl-mmap.op = $(no-stack-protector) +CFLAGS-dl-writev.o = $(no-stack-protector) +CFLAGS-dl-writev.op = $(no-stack-protector) +endif diff --git a/sysdeps/unix/sysv/linux/i386/dl-mmap.c b/sysdeps/unix/sysv/linux/i386/dl-mmap.c new file mode 100644 index 0000000000..b3510b1b20 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/dl-mmap.c @@ -0,0 +1,38 @@ +/* mmap wrapper for early static startup. Linux/i386 version. + 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 + . */ + +/* This mmap call is used to allocate some memory to backup assert() messages + before TLS setup is done, so it cannot use "call *%gs:SYSINFO_OFFSET" + during startup in static PIE. */ +#if BUILD_PIE_DEFAULT +# define I386_USE_SYSENTER 0 +#endif + +#include +#include +#include +#include + +void * +_dl_mmap (void *addr, size_t len, int prot, int flags) +{ + long int ret = MMAP_CALL_INTERNAL (mmap2, addr, len, prot, flags, -1, 0); + if (INTERNAL_SYSCALL_ERROR_P (ret)) + return MAP_FAILED; + return (void *) ret; +} diff --git a/sysdeps/unix/sysv/linux/i386/dl-mmap.h b/sysdeps/unix/sysv/linux/i386/dl-mmap.h new file mode 100644 index 0000000000..9eb0892ff5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/dl-mmap.h @@ -0,0 +1,27 @@ +/* mmap wrapper for early static startup. Linux/i386 version. + 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 + . */ + +#ifndef _DL_MMAP_H +#define _DL_MMAP_H + +/* i386 requires out-of-line implementation because it sets + I386_USE_SYSENTER to 0 to avoid use the vDSO. */ +void * _dl_mmap (void *addr, size_t len, int prot, int flags) + attribute_hidden; + +#endif diff --git a/sysdeps/unix/sysv/linux/i386/dl-writev.c b/sysdeps/unix/sysv/linux/i386/dl-writev.c new file mode 100644 index 0000000000..728e78e849 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/dl-writev.c @@ -0,0 +1,32 @@ +/* writev wrapper for the dynamic linker. Linux/i386 version. + 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 + . */ + +/* This writev call is used to assert() before TLS setup is done, so it can + not use "call *%gs:SYSINFO_OFFSET" during startup in static PIE. */ +#if BUILD_PIE_DEFAULT +# define I386_USE_SYSENTER 0 +#endif + +#include +#include + +ssize_t +_dl_writev (int fd, const struct iovec *iov, size_t niov) +{ + return INTERNAL_SYSCALL_CALL (writev, fd, iov, niov); +} diff --git a/sysdeps/unix/sysv/linux/i386/dl-writev.h b/sysdeps/unix/sysv/linux/i386/dl-writev.h index 8327d32374..d92c74d712 100644 --- a/sysdeps/unix/sysv/linux/i386/dl-writev.h +++ b/sysdeps/unix/sysv/linux/i386/dl-writev.h @@ -16,9 +16,14 @@ License along with the GNU C Library; if not, see . */ -#if BUILD_PIE_DEFAULT -/* Can't use "call *%gs:SYSINFO_OFFSET" during startup in static PIE. */ -# define I386_USE_SYSENTER 0 -#endif +#ifndef _DL_WRITEV_H +#define _DL_WRITEV_H -#include +#include + +/* i386 requires out-of-line implementation because it sets + I386_USE_SYSENTER to 0 to avoid use the vDSO. */ +ssize_t _dl_writev (int fd, const struct iovec *iov, size_t niov) + attribute_hidden; + +#endif diff --git a/sysdeps/unix/sysv/linux/i386/raise_direct.c b/sysdeps/unix/sysv/linux/i386/raise_direct.c new file mode 100644 index 0000000000..375ed80b58 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/raise_direct.c @@ -0,0 +1,26 @@ +/* Internal function to send a signal to itself. Linux/i386 version. + 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 + . */ + +/* This is called from abort() (issued by assert()) before TLS setup is done, + so it cannot use "call *%gs:SYSINFO_OFFSET" during startup in static + PIE. */ +#if BUILD_PIE_DEFAULT +# define I386_USE_SYSENTER 0 +#endif + +#include diff --git a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile index 4991466369..bdbd12a2b6 100644 --- a/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile +++ b/sysdeps/unix/sysv/linux/riscv/multiarch/Makefile @@ -48,8 +48,14 @@ sysdep_routines += \ strrchr-vector \ # sysdep_routines +# Called during static library initialization, so turn stack-protection +# off for non-shared builds. +CFLAGS-memset-generic.o = $(no-stack-protector) +CFLAGS-memset-generic.op = $(no-stack-protector) +CFLAGS-memcpy-generic.o = $(no-stack-protector) +CFLAGS-memcpy-generic.op = $(no-stack-protector) +CFLAGS-strlen-generic.o = $(no-stack-protector) +CFLAGS-strlen-generic.op = $(no-stack-protector) + CFLAGS-memcpy_noalignment.c += -mno-strict-align -# Called during static initialization -CFLAGS-memset-generic.c += $(no-stack-protector) -CFLAGS-memcpy-generic.c += $(no-stack-protector) endif diff --git a/sysdeps/x86_64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/x86_64/multiarch/dl-symbol-redir-ifunc.h index 1f3ca20307..ac59ca8ea8 100644 --- a/sysdeps/x86_64/multiarch/dl-symbol-redir-ifunc.h +++ b/sysdeps/x86_64/multiarch/dl-symbol-redir-ifunc.h @@ -45,14 +45,14 @@ asm ("memset = " HAVE_MEMSET_IFUNC_GENERIC); asm ("memcmp = " HAVE_MEMCMP_IFUNC_GENERIC); #if MINIMUM_X86_ISA_LEVEL >= 4 -# define HAVE_STRCMP_IFUNC_GENERIC "__strlen_evex" +# define HAVE_STRLEN_IFUNC_GENERIC "__strlen_evex" #elif MINIMUM_X86_ISA_LEVEL == 3 -# define HAVE_STRCMP_IFUNC_GENERIC "__strlen_avx2" +# define HAVE_STRLEN_IFUNC_GENERIC "__strlen_avx2" #else -# define HAVE_STRCMP_IFUNC_GENERIC "__strlen_sse2" +# define HAVE_STRLEN_IFUNC_GENERIC "__strlen_sse2" #endif -asm ("strlen = " HAVE_STRCMP_IFUNC_GENERIC); +asm ("strlen = " HAVE_STRLEN_IFUNC_GENERIC); #if MINIMUM_X86_ISA_LEVEL >= 4 # define HAVE_MEMCPY_IFUNC_GENERIC "__memcpy_evex_unaligned" @@ -73,6 +73,16 @@ asm ("memmove = " HAVE_MEMMOVE_IFUNC_GENERIC); asm ("mempcpy = " HAVE_MEMPCPY_IFUNC_GENERIC); asm ("__mempcpy = " HAVE_MEMPCPY_IFUNC_GENERIC); +#if MINIMUM_X86_ISA_LEVEL >= 4 +# define HAVE_STRCHRNUL_IFUNC_GENERIC "__strchrnul_evex" +#elif MINIMUM_X86_ISA_LEVEL == 3 +# define HAVE_STRCHRNUL_IFUNC_GENERIC "__strchrnul_avx2" +#else +# define HAVE_STRCHRNUL_IFUNC_GENERIC "__strchrnul_sse2" +#endif + +asm ("__strchrnul = " HAVE_STRCHRNUL_IFUNC_GENERIC); + #endif /* SHARED */ #endif