[PATCH v2 13/14] riscv/cfi: Add __allocate_shadow_stack for mapping new shadow stack
Jesse Huang
jesse.huang@sifive.com
Fri Jul 11 13:52:54 GMT 2025
---
sysdeps/unix/sysv/linux/riscv/Makefile | 1 +
.../sysv/linux/riscv/allocate-shadow-stack.c | 55 +++++++++++++++++++
.../sysv/linux/riscv/allocate-shadow-stack.h | 24 ++++++++
sysdeps/unix/sysv/linux/riscv/bits/mman.h | 30 ++++++++++
sysdeps/unix/sysv/linux/riscv/sysdep.h | 2 +
5 files changed, 112 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
diff --git a/sysdeps/unix/sysv/linux/riscv/Makefile b/sysdeps/unix/sysv/linux/riscv/Makefile
index 04abf226ad..7e81cc078a 100644
--- a/sysdeps/unix/sysv/linux/riscv/Makefile
+++ b/sysdeps/unix/sysv/linux/riscv/Makefile
@@ -7,6 +7,7 @@ sysdep_headers += \
sysdep_routines += \
flush-icache \
hwprobe \
+ allocate-shadow-stack \
# sysdep_routines
endif
diff --git a/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.c b/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.c
new file mode 100644
index 0000000000..7e060e1fe3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.c
@@ -0,0 +1,55 @@
+/* Helper function to allocate shadow stack.
+ Copyright (C) 2023-2025 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>
+
+/* 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 == MAP_FAILED)
+ 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
+}
diff --git a/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.h b/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.h
new file mode 100644
index 0000000000..af5f0f1dda
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/allocate-shadow-stack.h
@@ -0,0 +1,24 @@
+/* Helper function to allocate shadow stack.
+ Copyright (C) 2023-2025 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>
+
+typedef __typeof (((ucontext_t *) 0)->uc_ssp) shadow_stack_size_t;
+
+extern long int __allocate_shadow_stack (size_t, shadow_stack_size_t *)
+ attribute_hidden;
diff --git a/sysdeps/unix/sysv/linux/riscv/bits/mman.h b/sysdeps/unix/sysv/linux/riscv/bits/mman.h
new file mode 100644
index 0000000000..683d45b72e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/riscv/bits/mman.h
@@ -0,0 +1,30 @@
+/* Definitions for POSIX memory map interface. Linux/risc-v version.
+ Copyright (C) 1997-2025 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
+
+#ifdef __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>
diff --git a/sysdeps/unix/sysv/linux/riscv/sysdep.h b/sysdeps/unix/sysv/linux/riscv/sysdep.h
index 14a1f3a647..da28831655 100644
--- a/sysdeps/unix/sysv/linux/riscv/sysdep.h
+++ b/sysdeps/unix/sysv/linux/riscv/sysdep.h
@@ -207,6 +207,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
--
2.39.3
More information about the Libc-alpha
mailing list