[v4,14/17] riscv/cfi: Add __allocate_shadow_stack for mapping new shadow stack
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-arm |
success
|
Build passed
|
| 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_check--master-arm |
success
|
Test passed
|
Commit Message
Co-authored-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
Co-authored-by: Jerry Zhang Jian <jerry.zhangjian@sifive.com>
---
sysdeps/unix/sysv/linux/riscv/Makefile | 1 +
.../sysv/linux/riscv/allocate-shadow-stack.c | 59 +++++++++++++++++++
.../sysv/linux/riscv/allocate-shadow-stack.h | 31 ++++++++++
sysdeps/unix/sysv/linux/riscv/bits/mman.h | 30 ++++++++++
sysdeps/unix/sysv/linux/riscv/sysdep.h | 2 +
5 files changed, 123 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.c
create mode 100644 sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.h
create mode 100644 sysdeps/unix/sysv/linux/riscv/bits/mman.h
@@ -5,6 +5,7 @@ sysdep_headers += \
# sysdep_headers
sysdep_routines += \
+ allocate-shadow-stack \
flush-icache \
hwprobe \
# sysdep_routines
new file mode 100644
@@ -0,0 +1,59 @@
+/* Helper function to allocate shadow stack.
+ Copyright (C) 2023-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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 <stdint.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <libc-pointer-arith.h>
+#include <allocate-shadow-stack.h>
+
+#ifndef SHADOW_STACK_SET_TOKEN
+# define SHADOW_STACK_SET_TOKEN 0
+#endif
+
+/* NB: This can be treated as a syscall by caller. */
+
+long int
+__allocate_shadow_stack (size_t stack_size,
+ shadow_stack_size_t *child_stack)
+{
+#ifdef __NR_map_shadow_stack
+ size_t shadow_stack_size
+ = stack_size >> STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT;
+ /* Align shadow stack to 8 bytes. */
+ shadow_stack_size = ALIGN_UP (shadow_stack_size, 8);
+ /* Since sigaltstack shares shadow stack with the current context in
+ the thread, add extra 20 stack frames in shadow stack for signal
+ handlers. */
+ shadow_stack_size += 20 * 8;
+ void *shadow_stack = (void *)INLINE_SYSCALL_CALL
+ (map_shadow_stack, NULL, shadow_stack_size, SHADOW_STACK_SET_TOKEN);
+ /* Report the map_shadow_stack error. */
+ if (shadow_stack < 0)
+ return -errno;
+
+ /* Save the shadow stack base and size on child stack. */
+ child_stack[0] = (uintptr_t) shadow_stack;
+ child_stack[1] = shadow_stack_size;
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
+}
new file mode 100644
@@ -0,0 +1,31 @@
+/* Helper function to allocate shadow stack.
+ Copyright (C) 2023-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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 <sys/ucontext.h>
+
+#ifdef __riscv_shadow_stack
+/* When shadow stack is enabled, derive the storage type from ucontext. */
+typedef __typeof (((ucontext_t *) 0)->__saved.__ssp) \
+ shadow_stack_size_t;
+#else
+/* Without shadow stack support, use an unsigned long placeholder type. */
+typedef unsigned long int shadow_stack_size_t;
+#endif
+
+extern long int __allocate_shadow_stack (size_t, shadow_stack_size_t *)
+ attribute_hidden;
new file mode 100644
@@ -0,0 +1,30 @@
+/* Definitions for POSIX memory map interface. Linux/risc-v version.
+ Copyright (C) 1997-2026 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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 _SYS_MMAN_H
+# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
+#endif
+
+#if defined __USE_MISC && defined __riscv_shadow_stack
+# define SHADOW_STACK_SET_TOKEN 0x1
+#endif
+
+#include <bits/mman-map-flags-generic.h>
+
+/* Include generic Linux declarations. */
+#include <bits/mman-linux.h>
@@ -206,6 +206,8 @@ GNU_PROPERTY (FEATURE_1_AND, __VALUE_FOR_FEATURE_1_AND)
#else /* !__ASSEMBLER__ */
+# define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
+
# if __WORDSIZE == 64
# define VDSO_NAME "LINUX_4.15"
# define VDSO_HASH 182943605