diff options
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/linux/aarch64/makecontext.c | 41 |
1 files changed, 6 insertions, 35 deletions
diff --git a/sysdeps/unix/sysv/linux/aarch64/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/makecontext.c index 779f7e55aa..33824ae614 100644 --- a/sysdeps/unix/sysv/linux/aarch64/makecontext.c +++ b/sysdeps/unix/sysv/linux/aarch64/makecontext.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <ucontext.h> #include <sys/mman.h> +#include "aarch64-gcs.h" #define GCS_MAGIC 0x47435300 @@ -72,47 +73,17 @@ __libc_aarch64_thread_freeres (void) free_gcs_list (); } -#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 - static void * alloc_makecontext_gcs (size_t stack_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) + void *base; + size_t size; + void *gcsp = __alloc_gcs (stack_size, &base, &size); + if (gcsp == NULL) /* ENOSYS, bad size or OOM. */ abort (); - record_gcs (base, 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) - abort (); - /* Return the target GCS pointer for context switch. */ - return gcsp + 1; + return gcsp; } void |