[v4,20/22] aarch64: Add GCS user-space allocation logic
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
Commit Message
From: Szabolcs Nagy <szabolcs.nagy@arm.com>
Allocate GCS based on the stack size, this can be used for coroutines
(makecontext) and thread creation (if the kernel allows user allocated
GCS).
---
sysdeps/aarch64/Makefile | 3 +-
sysdeps/aarch64/__alloc_gcs.c | 66 +++++++++++++++++++++++++++++++++++
sysdeps/aarch64/aarch64-gcs.h | 36 +++++++++++++++++++
3 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 sysdeps/aarch64/__alloc_gcs.c
create mode 100644 sysdeps/aarch64/aarch64-gcs.h
@@ -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
new file mode 100644
@@ -0,0 +1,66 @@
+/* AArch64 GCS allocation.
+ Copyright (C) 2024 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 __NR_map_shadow_stack
+# define __NR_map_shadow_stack 453
+#endif
+#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 == (void *) -1)
+ 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;
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* AArch64 GCS (Guarded Control Stack) declarations.
+ This file is part of the GNU C Library.
+ Copyright (C) 2024 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;
+
+static inline bool
+has_gcs (void)
+{
+ register unsigned long x16 asm ("x16") = 1;
+ asm ("hint 40" /* chkfeat x16 */ : "+r" (x16));
+ return x16 == 0;
+}
+
+#endif