aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-03-28 14:27:45 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-03-31 10:08:06 -0300
commit4352e2cc934b2874dba37397157bf890fcee455a (patch)
tree5bcc9ff6e6cef71333269d05bca4627f6d568c24 /sysdeps/unix
parent145097dff170507fe73190e8e41194f5b5f7e6bf (diff)
downloadglibc-4352e2cc934b2874dba37397157bf890fcee455a.zip
glibc-4352e2cc934b2874dba37397157bf890fcee455a.tar.gz
glibc-4352e2cc934b2874dba37397157bf890fcee455a.tar.bz2
aarch64: Fix _dl_tlsdesc_dynamic unwind for pac-ret (BZ 32612)
When libgcc is built with pac-ret, it requires to autenticate the unwinding frame based on CFI information. The _dl_tlsdesc_dynamic uses a custom calling convention, where it is responsible to save and restore all registers it might use (even volatile). The pac-ret support added by 1be3d6eb823d8b952fa54b7bbc90cbecb8981380 was added only on the slow-path, but the fast path also adds DWARF Register Rule Instruction (cfi_adjust_cfa_offset) since it requires to save/restore some auxiliary register. It seems that this is not fully supported neither by libgcc nor AArch64 ABI [1]. Instead, move paciasp/autiasp to function prologue/epilogue to be used on both fast and slow paths. I also corrected the _dl_tlsdesc_dynamic comment description, it was copied from i386 implementation without any adjustment. Checked on aarch64-linux-gnu with a toolchain built with --enable-standard-branch-protection on a system with pac-ret support. [1] https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst#id1 Reviewed-by: Yury Khrustalev <yury.khrustalev@arm.com>
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/Makefile13
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac-mod.c27
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac.c48
3 files changed, 88 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index 0839f0b..15a2b44 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -1,3 +1,16 @@
+ifeq ($(subdir),elf)
+tests += \
+ tst-tlsdesc-pac \
+ # tests
+modules-names += \
+ tst-tlsdesc-pac-mod \
+ # modules-names
+
+LDFLAGS-tst-tlsdesc-pac = -rdynamic
+
+$(objpfx)tst-tlsdesc-pac.out: $(objpfx)tst-tlsdesc-pac-mod.so
+endif
+
ifeq ($(subdir),misc)
sysdep_headers += sys/elf.h
tests += \
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac-mod.c b/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac-mod.c
new file mode 100644
index 0000000..d34c8be
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac-mod.c
@@ -0,0 +1,27 @@
+/* AArch64 tests for unwinding TLSDESC (BZ 32612)
+ Copyright (C) 2025 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/>. */
+
+_Thread_local int foo;
+/* Make the TLS segment large enough to trigger _dl_tlsdesc_dynamic. */
+_Thread_local int foobar[1000];
+
+void
+bar (void)
+{
+ foo = 1;
+}
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac.c b/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac.c
new file mode 100644
index 0000000..24d656a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-tlsdesc-pac.c
@@ -0,0 +1,48 @@
+/* AArch64 tests for unwinding TLSDESC (BZ 32612)
+ Copyright (C) 2025 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 <stdlib.h>
+#include <unwind.h>
+#include <support/xdlfcn.h>
+
+static _Unwind_Reason_Code
+unwind_callback (struct _Unwind_Context* context, void* closure)
+{
+ return _URC_NO_REASON;
+}
+
+/* Assume that TLS variable from tst-tlsdesc-pac-mod.so will trigger
+ the slow-path that allocates the required memory with malloc. */
+void *
+malloc (size_t s)
+{
+ _Unwind_Backtrace (unwind_callback, NULL);
+ return calloc (1, s);
+}
+
+static int
+do_test (void)
+{
+ void *h = xdlopen ("tst-tlsdesc-pac-mod.so", RTLD_LAZY);
+ void (*func)(void) = xdlsym (h, "bar");
+ func ();
+
+ return 0;
+}
+
+#include <support/test-driver.c>