public inbox for glibc-cvs@sourceware.org help / color / mirror / Atom feed
From: Szabolcs Nagy <nsz@sourceware.org> To: glibc-cvs@sourceware.org Subject: [glibc/arm/gcs] aarch64: Add GCS support for makecontext Date: Wed, 14 Feb 2024 15:06:58 +0000 (GMT) [thread overview] Message-ID: <20240214150658.73C8F3857731@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=54e90582aabdb44f010ad5dfd64ce9c3e6d33914 commit 54e90582aabdb44f010ad5dfd64ce9c3e6d33914 Author: Szabolcs Nagy <szabolcs.nagy@arm.com> Date: Tue Apr 4 10:42:21 2023 +0100 aarch64: Add GCS support for makecontext Changed the makecontext logic: previously the first setcontext jumped straight to the user callback function and the return address is set to __startcontext. This does not work when GCS is enabled as the integrity of the return address is protected, so instead the context is setup such that setcontext jumps to __startcontext which calls the user callback (passed in x20). The map_shadow_stack syscall is used to allocate a suitably sized GCS (which includes some reserved area to account for altstack signal handlers and otherwise supports maximum number of 16 byte aligned stack frames on the given stack) however the GCS is never freed as the lifetime of ucontext and related stack is user managed. Diff: --- sysdeps/unix/sysv/linux/aarch64/makecontext.c | 61 ++++++++++++++++++++++++++- sysdeps/unix/sysv/linux/aarch64/setcontext.S | 4 ++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/sysdeps/unix/sysv/linux/aarch64/makecontext.c b/sysdeps/unix/sysv/linux/aarch64/makecontext.c index 5aec182013..9e66b6761c 100644 --- a/sysdeps/unix/sysv/linux/aarch64/makecontext.c +++ b/sysdeps/unix/sysv/linux/aarch64/makecontext.c @@ -22,6 +22,52 @@ #include <stdint.h> #include <ucontext.h> +#define GCS_MAGIC 0x47435300 + +static struct _aarch64_ctx *extension (void *p) +{ + return p; +} + +#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) + /* ENOSYS, bad size or OOM. */ + abort (); + 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; +} /* makecontext sets up a stack and the registers for the user context. The stack looks like this: @@ -56,10 +102,21 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) sp = (uint64_t *) (((uintptr_t) sp) & -16L); ucp->uc_mcontext.regs[19] = (uintptr_t) ucp->uc_link; + ucp->uc_mcontext.regs[20] = (uintptr_t) func; ucp->uc_mcontext.sp = (uintptr_t) sp; - ucp->uc_mcontext.pc = (uintptr_t) func; + ucp->uc_mcontext.pc = (uintptr_t) __startcontext; ucp->uc_mcontext.regs[29] = (uintptr_t) 0; - ucp->uc_mcontext.regs[30] = (uintptr_t) &__startcontext; + ucp->uc_mcontext.regs[30] = (uintptr_t) 0; + + void *p = ucp->uc_mcontext.__reserved; + if (extension (p)->magic == FPSIMD_MAGIC) + p = (char *)p + extension (p)->size; + if (extension (p)->magic == GCS_MAGIC) + { + /* Using the kernel struct gcs_context layout. */ + struct { uint64_t x, gcspr, y, z; } *q = p; + q->gcspr = (uint64_t) alloc_makecontext_gcs (ucp->uc_stack.ss_size); + } va_start (ap, argc); for (i = 0; i < argc; ++i) diff --git a/sysdeps/unix/sysv/linux/aarch64/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/setcontext.S index c08e83ee60..6aa7236693 100644 --- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S +++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S @@ -181,7 +181,11 @@ L(gcs_done): PSEUDO_END (__setcontext) weak_alias (__setcontext, setcontext) +/* makecontext start function: receives uc_link in x19 and func in x20. + Arguments of func, x29, x30 and sp are set up by the caller. */ ENTRY (__startcontext) + cfi_undefined (x30) + blr x20 mov x0, x19 cbnz x0, __setcontext 1: b HIDDEN_JUMPTARGET (exit)
reply other threads:[~2024-02-14 15:06 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20240214150658.73C8F3857731@sourceware.org \ --to=nsz@sourceware.org \ --cc=glibc-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).