]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
aarch64: Add GCS user-space allocation logic
authorSzabolcs Nagy <szabolcs.nagy@arm.com>
Wed, 28 Aug 2024 10:21:19 +0000 (11:21 +0100)
committerYury Khrustalev <yury.khrustalev@arm.com>
Mon, 20 Jan 2025 09:36:19 +0000 (09:36 +0000)
Allocate GCS based on the stack size, this can be used for coroutines
(makecontext) and thread creation (if the kernel allows user allocated
GCS).

Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
sysdeps/aarch64/Makefile
sysdeps/aarch64/__alloc_gcs.c [new file with mode: 0644]
sysdeps/aarch64/aarch64-gcs.h [new file with mode: 0644]

index 74479604f2b127f58f8aec28b8e3787ea0f55540..4b7f8a5c07d8e9b32648aac340347acc6dae0da8 100644 (file)
@@ -71,7 +71,8 @@ sysdep_headers += sys/ifunc.h
 sysdep_routines += \
   __mtag_tag_zero_region \
   __mtag_tag_region \
-  __arm_za_disable
+  __arm_za_disable \
+  __alloc_gcs
 
 tests += \
   tst-sme-jmp
diff --git a/sysdeps/aarch64/__alloc_gcs.c b/sysdeps/aarch64/__alloc_gcs.c
new file mode 100644 (file)
index 0000000..e70b459
--- /dev/null
@@ -0,0 +1,63 @@
+/* AArch64 GCS allocation.
+   Copyright (C) 2024-2025 Free Software Foundation, Inc.
+
+   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 <sysdep.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#ifndef SHADOW_STACK_SET_TOKEN
+# define SHADOW_STACK_SET_TOKEN (1UL << 0)
+# define SHADOW_STACK_SET_MARKER (1UL << 1)
+#endif
+
+static void *
+map_shadow_stack (void *addr, size_t size, unsigned long flags)
+{
+  return (void *) INLINE_SYSCALL_CALL (map_shadow_stack, addr, size, flags);
+}
+
+#define GCS_MAX_SIZE (1UL << 31)
+#define GCS_ALTSTACK_RESERVE 160
+
+void *
+__alloc_gcs (size_t stack_size, void **ss_base, size_t *ss_size)
+{
+  size_t size = (stack_size / 2 + GCS_ALTSTACK_RESERVE) & -8UL;
+  if (size > GCS_MAX_SIZE)
+    size = GCS_MAX_SIZE;
+
+  unsigned long flags = SHADOW_STACK_SET_MARKER | SHADOW_STACK_SET_TOKEN;
+  void *base = map_shadow_stack (NULL, size, flags);
+  if (base == MAP_FAILED)
+    return NULL;
+
+  *ss_base = base;
+  *ss_size = size;
+
+  uint64_t *gcsp = (uint64_t *) ((char *) base + size);
+  /* Skip end of GCS token.  */
+  gcsp--;
+  /* Verify GCS cap token.  */
+  gcsp--;
+  if (((uint64_t)gcsp & 0xfffffffffffff000) + 1 != *gcsp)
+    {
+      __munmap (base, size);
+      return NULL;
+    }
+  /* Return the target GCS pointer for context switch.  */
+  return gcsp + 1;
+}
diff --git a/sysdeps/aarch64/aarch64-gcs.h b/sysdeps/aarch64/aarch64-gcs.h
new file mode 100644 (file)
index 0000000..162ef18
--- /dev/null
@@ -0,0 +1,28 @@
+/* AArch64 GCS (Guarded Control Stack) declarations.
+   This file is part of the GNU C Library.
+   Copyright (C) 2024-2025 Free Software Foundation, Inc.
+   Copyright The GNU Toolchain Authors.
+
+   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/>.  */
+
+#ifndef _AARCH64_GCS_H
+#define _AARCH64_GCS_H
+
+#include <stddef.h>
+#include <stdbool.h>
+
+void *__alloc_gcs (size_t, void **, size_t *) attribute_hidden;
+
+#endif