[PATCH v4 4/5] aarch64: change __alloc_gcs to use shadow stack size
Yury Khrustalev
yury.khrustalev@arm.com
Fri Nov 7 09:35:08 GMT 2025
---
sysdeps/aarch64/__alloc_gcs.c | 24 ++++++++-----------
sysdeps/aarch64/aarch64-gcs.h | 11 ++++++++-
sysdeps/aarch64/libc-shadow-stack.h | 3 ++-
sysdeps/unix/sysv/linux/aarch64/makecontext.c | 3 ++-
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/sysdeps/aarch64/__alloc_gcs.c b/sysdeps/aarch64/__alloc_gcs.c
index b98e5fcdba..17491c24c9 100644
--- a/sysdeps/aarch64/__alloc_gcs.c
+++ b/sysdeps/aarch64/__alloc_gcs.c
@@ -32,37 +32,33 @@ 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, struct gcs_record *gcs)
+__alloc_gcs (size_t sh_stack_size, struct gcs_record *rec)
{
- size_t size = (stack_size / 2 + GCS_ALTSTACK_RESERVE) & -8UL;
- if (size > GCS_MAX_SIZE)
- size = GCS_MAX_SIZE;
+ if (sh_stack_size > GCS_MAX_SHADOW_STACK_SIZE)
+ sh_stack_size = GCS_MAX_SHADOW_STACK_SIZE;
unsigned long flags = SHADOW_STACK_SET_MARKER | SHADOW_STACK_SET_TOKEN;
- void *base = map_shadow_stack (NULL, size, flags);
+ void *base = map_shadow_stack (NULL, sh_stack_size, flags);
if (base == MAP_FAILED)
return NULL;
- uint64_t *gcsp = (uint64_t *) ((char *) base + size);
+ uint64_t *gcsp = (uint64_t *) ((char *) base + sh_stack_size);
/* Skip end of GCS token. */
gcsp--;
/* Verify GCS cap token. */
gcsp--;
if (((uint64_t)gcsp & 0xfffffffffffff000) + 1 != *gcsp)
{
- __munmap (base, size);
+ __munmap (base, sh_stack_size);
return NULL;
}
- if (gcs != NULL)
+ if (rec != NULL)
{
- gcs->gcs_base = base;
- gcs->gcs_token = gcsp;
- gcs->gcs_size = size;
+ rec->gcs_base = base;
+ rec->gcs_token = gcsp;
+ rec->gcs_size = sh_stack_size;
}
/* Return the target GCS pointer for context switch. */
diff --git a/sysdeps/aarch64/aarch64-gcs.h b/sysdeps/aarch64/aarch64-gcs.h
index 8e253ed32f..148532ba77 100644
--- a/sysdeps/aarch64/aarch64-gcs.h
+++ b/sysdeps/aarch64/aarch64-gcs.h
@@ -23,6 +23,9 @@
#include <stddef.h>
#include <stdbool.h>
+#define GCS_MAX_SHADOW_STACK_SIZE (1UL << 31)
+#define GCS_ALTSTACK_RESERVE 160
+
struct gcs_record
{
void *gcs_base;
@@ -30,7 +33,13 @@ struct gcs_record
size_t gcs_size;
};
-void *__alloc_gcs (size_t, struct gcs_record *) attribute_hidden;
+/* Allocate shadow stack of the given size SH_STACK_SIZE and write shadow
+ stack data in REC on success. Return shadow stack pointer or NULL if
+ unsuccessful in which case REC is not updated. The size of actually
+ allocated shadow stack may be reduced if the requested size exceeds
+ GCS_MAX_SHADOW_STACK_SIZE. */
+void *__alloc_gcs (size_t sh_stack_size, struct gcs_record *rec)
+ attribute_hidden;
static inline bool
has_gcs (void)
diff --git a/sysdeps/aarch64/libc-shadow-stack.h b/sysdeps/aarch64/libc-shadow-stack.h
index 10e6792796..b8aac4b4d6 100644
--- a/sysdeps/aarch64/libc-shadow-stack.h
+++ b/sysdeps/aarch64/libc-shadow-stack.h
@@ -81,8 +81,9 @@ thread_alloc_shadow_stack (struct pthread *pd, size_t stacksize)
}
if (atomic_load_relaxed (&clone3_has_shadow_stack) == clone3_sh_stack_off)
return 0;
+ size_t shadow_stack_size = (stacksize / 2 + GCS_ALTSTACK_RESERVE) & -8UL;
struct gcs_record gcs;
- if (__alloc_gcs (stacksize, &gcs) != NULL)
+ if (__alloc_gcs (shadow_stack_size, &gcs) != NULL)
{
pd->shadow_stack_base = gcs.gcs_base;
pd->shadow_stack_token = gcs.gcs_token;
diff --git a/sysdeps/unix/sysv/linux/aarch64/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/makecontext.c
index 4485723cfb..c9bb407e57 100644
--- a/sysdeps/unix/sysv/linux/aarch64/makecontext.c
+++ b/sysdeps/unix/sysv/linux/aarch64/makecontext.c
@@ -36,7 +36,8 @@ static struct _aarch64_ctx *extension (void *p)
static void *
alloc_makecontext_gcs (size_t stack_size)
{
- void *gcsp = __alloc_gcs (stack_size, NULL);
+ size_t shadow_stack_size = (stack_size / 2 + GCS_ALTSTACK_RESERVE) & -8UL;
+ void *gcsp = __alloc_gcs (shadow_stack_size, NULL);
if (gcsp == NULL)
/* ENOSYS, bad size or OOM. */
abort ();
--
2.47.3
More information about the Libc-alpha
mailing list