Skip to content

Commit 5b22ebf

Browse files
committed
riscv/cfi: Adjust setjmp/longjmp for shadow stack to work
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.
1 parent 25b9179 commit 5b22ebf

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

sysdeps/riscv/__longjmp.S

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,36 @@ ENTRY (__longjmp)
5151
FREG_L fs11,14*SZREG+11*SZFREG(a0)
5252
#endif
5353

54+
#ifdef __riscv_zicfiss
55+
/* read ssp into t0 */
56+
ssrdp t0
57+
/* skip unwinding if ss is not enabled */
58+
beqz t0, .Lunwind_fin
59+
# ifndef __riscv_float_abi_soft
60+
REG_L t1, 14*SZREG+12*SZFREG(a0)
61+
# else
62+
REG_L t1, 14*SZREG(a0)
63+
# endif
64+
.Lunwind:
65+
/* should not be taken in normal condition */
66+
bleu t1, t0, .Lunwind_fin
67+
/* The unwinding algorithm came from the zicfiss spec, increase ssp
68+
by at most a page size to ensure always run into a guard page
69+
before accidentally point to another legal shadow stack page */
70+
/* t0 = (t1 - t0 >= 4096) ? t0 + 4096 : t1 */
71+
lui a0, 1
72+
add t0, t0, a0
73+
bleu t0, t1, 1f
74+
mv t0, t1
75+
1:
76+
csrw ssp, t0
77+
/* Test if the location pointed by ssp is legal */
78+
sspush x5
79+
sspopchk x5
80+
j .Lunwind
81+
.Lunwind_fin:
82+
#endif
83+
5484
seqz a0, a1
5585
add a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
5686
ret

sysdeps/riscv/bits/setjmp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ typedef struct __jmp_buf_internal_tag
3333
double __fpregs[12];
3434
#elif !defined __riscv_float_abi_soft
3535
# error unsupported FLEN
36+
#endif
37+
#ifdef __riscv_zicfiss
38+
/* Shadow stack pointer. */
39+
long int __ssp;
3640
#endif
3741
} __jmp_buf[1];
3842

sysdeps/riscv/setjmp.S

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ ENTRY (__sigsetjmp)
6161
FREG_S fs11,14*SZREG+11*SZFREG(a0)
6262
#endif
6363

64+
#ifdef __riscv_zicfiss
65+
/* read ssp into t0 */
66+
ssrdp t0
67+
# ifndef __riscv_float_abi_soft
68+
REG_S t0, 14*SZREG+12*SZFREG(a0)
69+
# else
70+
REG_S t0, 14*SZREG(a0)
71+
# endif
72+
#endif
73+
6474
#if !IS_IN (libc) && IS_IN (rtld)
6575
/* In ld.so we never save the signal mask. */
6676
li a0, 0

0 commit comments

Comments
 (0)