[PATCH v2 10/14] riscv/cfi: Adjust setjmp/longjmp for shadow stack to work
Deepak Gupta
debug@rivosinc.com
Tue Jul 22 21:50:32 GMT 2025
On Fri, Jul 11, 2025 at 06:52:51AM -0700, Jesse Huang wrote:
>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
Why conditionally change size of this structure?
I think we should keep size of jmp_buf static in nature as far as ssp
is concerned.
> } __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