[PATCH v2 10/14] riscv/cfi: Adjust setjmp/longjmp for shadow stack to work
Jesse Huang
jesse.huang@sifive.com
Fri Jul 11 13:52:51 GMT 2025
Since longjmp to a previous setjmp'ed state could change the stack
frame and involves stack frame unwinding, shadow stacks is also required
to be unwinded.
The unwinding is implemented according to the zicfiss spec by increasing
the ssp by a page size (4K) at most, to prevent from accidentally point
to another legal shadow stack page after the adjustment.
---
sysdeps/riscv/__longjmp.S | 28 ++++++++++++++++++++++++++++
sysdeps/riscv/bits/setjmp.h | 4 ++++
sysdeps/riscv/setjmp.S | 10 ++++++++++
3 files changed, 42 insertions(+)
diff --git a/sysdeps/riscv/__longjmp.S b/sysdeps/riscv/__longjmp.S
index 47ff3aa09e..1aa8a235d7 100644
--- a/sysdeps/riscv/__longjmp.S
+++ b/sysdeps/riscv/__longjmp.S
@@ -51,6 +51,34 @@ ENTRY (__longjmp)
FREG_L fs11,14*SZREG+11*SZFREG(a0)
#endif
+#ifdef __riscv_shadow_stack
+ /* skip unwinding if ss is not enabled */
+ ssrdp t0
+ beqz t0, .Lunwind_fin
+# ifndef __riscv_float_abi_soft
+ REG_L t1, 14*SZREG+12*SZFREG(a0)
+# else
+ REG_L t1, 14*SZREG(a0)
+# endif
+.Lunwind:
+ bleu t1, t0, .Lunwind_fin
+ /* 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 */
+ /* t0 = (t1 - t0 >= 4096) ? t0 + 4096 : t1 */
+ lui a0, 1
+ add t0, t0, a0
+ bleu t0, t1, 1f
+ mv t0, t1
+1:
+ csrw ssp, t0
+ /* Test if the location pointed by ssp is legal */
+ sspush x5
+ sspopchk x5
+ j .Lunwind
+.Lunwind_fin:
+#endif
+
seqz a0, a1
add a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
ret
diff --git a/sysdeps/riscv/bits/setjmp.h b/sysdeps/riscv/bits/setjmp.h
index 5ebbec393a..5cbc12fa3d 100644
--- a/sysdeps/riscv/bits/setjmp.h
+++ b/sysdeps/riscv/bits/setjmp.h
@@ -33,6 +33,10 @@ typedef struct __jmp_buf_internal_tag
double __fpregs[12];
#elif !defined __riscv_float_abi_soft
# error unsupported FLEN
+#endif
+#ifdef __riscv_shadow_stack
+ /* Shadow stack pointer. */
+ long int __ssp;
#endif
} __jmp_buf[1];
diff --git a/sysdeps/riscv/setjmp.S b/sysdeps/riscv/setjmp.S
index df048cb544..f547bc0238 100644
--- a/sysdeps/riscv/setjmp.S
+++ b/sysdeps/riscv/setjmp.S
@@ -61,6 +61,16 @@ ENTRY (__sigsetjmp)
FREG_S fs11,14*SZREG+11*SZFREG(a0)
#endif
+#ifdef __riscv_shadow_stack
+ /* read ssp into t0 */
+ ssrdp t0
+# ifndef __riscv_float_abi_soft
+ REG_S t0, 14*SZREG+12*SZFREG(a0)
+# else
+ REG_S t0, 14*SZREG(a0)
+# endif
+#endif
+
#if !IS_IN (libc) && IS_IN (rtld)
/* In ld.so we never save the signal mask. */
li a0, 0
--
2.39.3
More information about the Libc-alpha
mailing list