@@ -17,11 +17,13 @@
<https://www.gnu.org/licenses/>. */
#include "ucontext-macros.h"
+#include "tcb-offsets.h"
/* int getcontext (ucontext_t *ucp) */
.text
LEAF (__getcontext)
+ LPAD
SAVE_INT_REG (ra, 0, a0)
SAVE_INT_REG (ra, 1, a0)
SAVE_INT_REG (sp, 2, a0)
@@ -58,6 +60,24 @@ LEAF (__getcontext)
sw a1, MCONTEXT_FSR(a0)
#endif /* __riscv_float_abi_soft */
+#ifdef __riscv_shadow_stack
+ ssrdp t0
+ beqz t0, .Lskip_ss
+ /* Read ssp_base from TLS */
+ REG_L t1, TLS_SSP_BASE_OFFSET(tp)
+
+ bnez t1, .Lbase_saved
+ /* if not found, save and use current ssp as the marker */
+ mv t1, t0
+ REG_S t1, TLS_SSP_BASE_OFFSET(tp)
+
+.Lbase_saved:
+ /* Save caller's ssp and base marker to ucontext */
+ REG_S t1, UCONTEXT_SSP_BASE(a0)
+ REG_S t0, UCONTEXT_SSP(a0)
+.Lskip_ss:
+#endif
+
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
li a3, _NSIG8
add a2, a0, UCONTEXT_SIGMASK
@@ -21,6 +21,9 @@
#include <sys/ucontext.h>
#include <stdarg.h>
#include <assert.h>
+#ifdef __riscv_shadow_stack
+#include <allocate-shadow-stack.h>
+#endif
void
__makecontext (ucontext_t *ucp, void (*func) (void), int argc,
@@ -73,6 +76,22 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc,
va_end (vl);
}
+#ifdef __riscv_shadow_stack
+ /* Allocate shadow stack for the new context */
+
+ /* shstk_size[0]: shadow stack base
+ shstk_size[1]: shadow stack size */
+ shadow_stack_size_t shstk_size[2];
+ int ret = __allocate_shadow_stack(ucp->uc_stack.ss_size, shstk_size);
+ if (ret != 0)
+ {
+ abort();
+ }
+
+ ucp->__saved.__ssp_base = shstk_size[0];
+ ucp->__saved.__ssp = shstk_size[0] + shstk_size[1] - \
+ sizeof (shstk_size[0]);
+#endif
}
weak_alias (__makecontext, makecontext)
@@ -17,6 +17,7 @@
<https://www.gnu.org/licenses/>. */
#include "ucontext-macros.h"
+#include "tcb-offsets.h"
/* int __setcontext (const ucontext_t *ucp)
@@ -29,6 +30,7 @@
.text
LEAF (__setcontext)
+ LPAD
mv t0, a0 /* Save ucp into t0. */
@@ -45,6 +47,55 @@ LEAF (__setcontext)
cfi_def_cfa (t0, 0)
+#ifdef __riscv_shadow_stack
+ /* Skip if shadow stack is not enabled */
+ ssrdp ra
+ beqz ra, .Lfin
+ /* We are safe to adjust shadow stack after the sanity check */
+ REG_L t1, UCONTEXT_SSP_BASE(t0)
+ REG_L a1, UCONTEXT_SSP(t0)
+ REG_L a2, TLS_SSP_BASE_OFFSET(tp)
+ bne t1, a2, .Ldifferent_stack
+
+.Lunwind:
+ bleu a1, ra, .Lfin
+ /* increase ssp by at most a page size to ensure always run into
+ a guard page before accidentally point to another legal shadow
+ stack page */
+ /* ra = (a1 - ra >= 4096) ? ra + 4096 : a1 */
+ lui t2, 1
+ add ra, ra, t2
+ bleu ra, a1, 1f
+ mv ra, a1
+1:
+ csrw ssp, ra
+ /* Test if the location pointed by ssp is legal */
+ sspush ra
+ sspopchk ra
+ j .Lunwind
+
+.Ldifferent_stack:
+ /* Create restore token */
+ sspush ra
+ mv a4, a1
+
+.Lfind_rstor_token:
+ /* Probe and validate target restore token */
+ ssamoswap.d a3, x0, (a4)
+ addi a2, a4, 8
+ beq a3, a2, .Lswitch_stack
+ /* Restore the shadow stack and try the next slot */
+ ssamoswap.d x0, a3, (a4)
+ addi a4, a4, -8
+ j .Lfind_rstor_token
+
+.Lswitch_stack:
+ /* Switch stack: update ssp and base */
+ csrw ssp, a1
+ REG_S t1, TLS_SSP_BASE_OFFSET(tp)
+.Lfin:
+#endif
+
#ifndef __riscv_float_abi_soft
lw t1, MCONTEXT_FSR(t0)
@@ -66,7 +117,11 @@ LEAF (__setcontext)
/* Note the contents of argument registers will be random
unless makecontext() has been called. */
+#ifdef __riscv_landing_pad
+ RESTORE_INT_REG (t2, 0, t0)
+#else
RESTORE_INT_REG (t1, 0, t0)
+#endif
RESTORE_INT_REG_CFI (ra, 1, t0)
RESTORE_INT_REG (sp, 2, t0)
RESTORE_INT_REG_CFI (s0, 8, t0)
@@ -90,7 +145,12 @@ LEAF (__setcontext)
RESTORE_INT_REG_CFI (s10, 26, t0)
RESTORE_INT_REG_CFI (s11, 27, t0)
+#ifdef __riscv_landing_pad
+ /* We need to use software-guared jump */
+ jr t2
+#else
jr t1
+#endif
99: tail __syscall_error
@@ -99,12 +159,19 @@ libc_hidden_def (__setcontext)
weak_alias (__setcontext, setcontext)
LEAF (__start_context)
+ LPAD
/* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */
cfi_register (ra, s0)
/* Call the function passed to makecontext. */
+#ifdef __riscv_landing_pad
+ /* We need to use software-guared jump */
+ mv t2, s1
+ jalr t2
+#else
jalr s1
+#endif
/* Invoke subsequent context if present, else exit(0). */
mv a0, s2
@@ -17,10 +17,12 @@
<https://www.gnu.org/licenses/>. */
#include "ucontext-macros.h"
+#include "tcb-offsets.h"
/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
LEAF (__swapcontext)
+ LPAD
mv t0, a1 /* Save ucp into t0. */
SAVE_INT_REG (ra, 0, a0)
@@ -59,6 +61,26 @@ LEAF (__swapcontext)
sw a1, MCONTEXT_FSR(a0)
#endif /* __riscv_float_abi_soft */
+#ifdef __riscv_shadow_stack
+ /* Skip if shadow stack is not enabled */
+ ssrdp ra
+ beqz ra, .Lsave_fin
+
+ /* Read ssp_base from TLS */
+ REG_L t2, TLS_SSP_BASE_OFFSET(tp)
+ bnez t2, .Lbase_saved
+
+ /* if not found, use current ssp as the marker */
+ mv t2, ra
+ REG_S t2, TLS_SSP_BASE_OFFSET(tp)
+
+.Lbase_saved:
+ /* Save caller's ssp and base marker to oucp */
+ REG_S t2, UCONTEXT_SSP_BASE(a0)
+ REG_S ra, UCONTEXT_SSP(a0)
+.Lsave_fin:
+#endif
+
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
li a3, _NSIG8
add a2, a0, UCONTEXT_SIGMASK
@@ -70,6 +92,55 @@ LEAF (__swapcontext)
bltz a0, 99f
+#ifdef __riscv_shadow_stack
+ /* Skip if shadow stack is not enabled */
+ ssrdp ra
+ beqz ra, .Lfin
+ /* Load ss information from ucp */
+ REG_L a0, UCONTEXT_SSP_BASE(t0)
+ REG_L a1, UCONTEXT_SSP(t0)
+ REG_L a2, TLS_SSP_BASE_OFFSET(tp)
+ bne a0, a2, .Ldifferent_stack
+
+.Lunwind:
+ bleu a1, ra, .Lfin
+ /* increase ssp by at most a page size to ensure always run into
+ a guard page before accidentally point to another legal shadow
+ stack page */
+ /* ra = (a1 - ra >= 4096) ? ra + 4096 : a1 */
+ lui t2, 1
+ add ra, ra, t2
+ bleu ra, a1, 1f
+ mv ra, a1
+1:
+ csrw ssp, ra
+ /* Test if the location pointed by ssp is legal */
+ sspush ra
+ sspopchk ra
+ j .Lunwind
+
+.Ldifferent_stack:
+ /* Create restore token */
+ sspush ra
+ mv a4, a1
+
+.Lfind_rstor_token:
+ /* Probe and validate target restore token */
+ ssamoswap.d a3, x0, (a4)
+ addi a2, a4, 8
+ beq a3, a2, .Lswitch_stack
+ /* Restore the shadow stack and try the next slot */
+ ssamoswap.d x0, a3, (a4)
+ addi a4, a4, -8
+ j .Lfind_rstor_token
+
+.Lswitch_stack:
+ /* Switch stack: update ssp and base */
+ csrw ssp, a1
+ REG_S a0, TLS_SSP_BASE_OFFSET(tp)
+.Lfin:
+#endif
+
#ifndef __riscv_float_abi_soft
lw t1, MCONTEXT_FSR(t0)
@@ -91,7 +162,11 @@ LEAF (__swapcontext)
/* Note the contents of argument registers will be random
unless makecontext() has been called. */
+#ifdef __riscv_landing_pad
+ RESTORE_INT_REG (t2, 0, t0)
+#else
RESTORE_INT_REG (t1, 0, t0)
+#endif
RESTORE_INT_REG (ra, 1, t0)
RESTORE_INT_REG (sp, 2, t0)
RESTORE_INT_REG (s0, 8, t0)
@@ -115,8 +190,12 @@ LEAF (__swapcontext)
RESTORE_INT_REG (s10, 26, t0)
RESTORE_INT_REG (s11, 27, t0)
+#ifdef __riscv_landing_pad
+ /* We need to use software-guared jump */
+ jr t2
+#else
jr t1
-
+#endif
99: tail __syscall_error
@@ -19,7 +19,9 @@ UCONTEXT_FLAGS ucontext (__uc_flags)
UCONTEXT_LINK ucontext (uc_link)
UCONTEXT_STACK ucontext (uc_stack)
UCONTEXT_MCONTEXT ucontext (uc_mcontext)
-UCONTEXT_SIGMASK ucontext (uc_sigmask)
+UCONTEXT_SIGMASK ucontext (__saved.__saved_mask)
+UCONTEXT_SSP ucontext (__saved.__ssp)
+UCONTEXT_SSP_BASE ucontext (__saved.__ssp_base)
STACK_SP stack (ss_sp)
STACK_SIZE stack (ss_size)