Skip to content

Commit 0a049e1

Browse files
jaidTwcinll5312
andcommitted
riscv/cfi: Support ucontext under CFI
This patches only make the ucontext library work while CFI is enabled. enabled. All security checks are skipped and should be implemented if correspoding interface are landed into the kernel. SSP is stored in the unused t3 slot in the sigcontext structure to avoid breaking the current structure. Co-authored-by: Nia Su <[email protected]>
1 parent d6a6338 commit 0a049e1

File tree

5 files changed

+183
-1
lines changed

5 files changed

+183
-1
lines changed

sysdeps/unix/sysv/linux/riscv/getcontext.S

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
<https://www.gnu.org/licenses/>. */
1818

1919
#include "ucontext-macros.h"
20+
#include "tcb-offsets.h"
2021

2122
/* int getcontext (ucontext_t *ucp) */
2223

2324
.text
2425
LEAF (__getcontext)
26+
LPAD
2527
SAVE_INT_REG (ra, 0, a0)
2628
SAVE_INT_REG (ra, 1, a0)
2729
SAVE_INT_REG (sp, 2, a0)
@@ -58,6 +60,24 @@ LEAF (__getcontext)
5860
sw a1, MCONTEXT_FSR(a0)
5961
#endif /* __riscv_float_abi_soft */
6062

63+
#ifdef __riscv_shadow_stack
64+
ssrdp t0
65+
beqz t0, .Lskip_ss
66+
/* Read ssp_base from TLS */
67+
ld t1, SSP_BASE_OFFSET(tp)
68+
69+
bnez t1, .Lbase_saved
70+
/* if not found, use current ssp as the marker */
71+
mv t1, t0
72+
sd t1, SSP_BASE_OFFSET(tp)
73+
74+
.Lbase_saved:
75+
/* Save caller's ssp and base marker to ucontext */
76+
REG_S t1, UCONTEXT_SSP_BASE(a0)
77+
REG_S t0, UCONTEXT_SSP(a0)
78+
.Lskip_ss:
79+
#endif
80+
6181
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
6282
li a3, _NSIG8
6383
add a2, a0, UCONTEXT_SIGMASK

sysdeps/unix/sysv/linux/riscv/makecontext.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sys/ucontext.h>
2222
#include <stdarg.h>
2323
#include <assert.h>
24+
#include <sys/mman.h>
2425

2526
void
2627
__makecontext (ucontext_t *ucp, void (*func) (void), int argc,
@@ -73,6 +74,23 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc,
7374

7475
va_end (vl);
7576
}
77+
#ifdef __riscv_shadow_stack
78+
/* Allocate shadow stack for the new context */
79+
/* FIXME: we use user space as a temporary solution until
80+
kernel provides such interface */
81+
82+
unsigned long ss_size = ucp->uc_stack.ss_size >>
83+
STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT;
84+
unsigned long ss_page = (ss_size + 4096 - 1) / 4096 + 2;
85+
ss_size = (ss_page - 2) * 4096;
86+
void *ss_start = __mmap (NULL, ss_page * 4096, PROT_NONE,
87+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
88+
ucp->uc_ssp_base = (unsigned long long) ss_start + 4096;
89+
ucp->uc_ssp = ucp->uc_ssp_base + ss_size - sizeof (unsigned long long);
90+
/* shadow stack token */
91+
__mprotect ((void *) ucp->uc_ssp_base, ss_size, PROT_READ | PROT_WRITE);
92+
*(unsigned long long *)ucp->uc_ssp = ucp->uc_ssp + sizeof(unsigned long long);
93+
#endif
7694
}
7795

7896
weak_alias (__makecontext, makecontext)

sysdeps/unix/sysv/linux/riscv/setcontext.S

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<https://www.gnu.org/licenses/>. */
1818

1919
#include "ucontext-macros.h"
20+
#include "tcb-offsets.h"
2021

2122
/* int __setcontext (const ucontext_t *ucp)
2223

@@ -29,6 +30,7 @@
2930

3031
.text
3132
LEAF (__setcontext)
33+
LPAD
3234

3335
mv t0, a0 /* Save ucp into t0. */
3436

@@ -45,6 +47,55 @@ LEAF (__setcontext)
4547

4648
cfi_def_cfa (t0, 0)
4749

50+
#ifdef __riscv_shadow_stack
51+
/* Skip if shadow stack is not enabled */
52+
ssrdp ra
53+
beqz ra, .Lfin
54+
/* We are safe to adjust shadow stack after the sanity check */
55+
REG_L t1, UCONTEXT_SSP_BASE(t0)
56+
REG_L a1, UCONTEXT_SSP(t0)
57+
REG_L a2, SSP_BASE_OFFSET(tp)
58+
bne t1, a2, .Ldifferent_stack
59+
60+
.Lunwind:
61+
bleu a1, ra, .Lfin
62+
/* increase ssp by at most a page size to ensure always run into
63+
a guard page before accidentally point to another legal shadow
64+
stack page */
65+
/* ra = (a1 - ra >= 4096) ? ra + 4096 : a1 */
66+
lui t2, 1
67+
add ra, ra, t2
68+
bleu ra, a1, 1f
69+
mv ra, a1
70+
1:
71+
csrw ssp, ra
72+
/* Test if the location pointed by ssp is legal */
73+
sspush ra
74+
sspopchk ra
75+
j .Lunwind
76+
77+
.Ldifferent_stack:
78+
/* Create restore token */
79+
sspush ra
80+
mv a4, a1
81+
82+
.Lfind_rstor_token:
83+
/* Probe and validate target restore token */
84+
ssamoswap.d a3, x0, (a4)
85+
addi a2, a4, 8
86+
beq a3, a2, .Lswitch_stack
87+
/* Restore the shadow stack and try the next slot */
88+
ssamoswap.d x0, a3, (a4)
89+
addi a4, a4, -8
90+
j .Lfind_rstor_token
91+
92+
.Lswitch_stack:
93+
/* Switch stack: update ssp and base */
94+
csrw ssp, a1
95+
REG_S t1, SSP_BASE_OFFSET(tp)
96+
.Lfin:
97+
#endif
98+
4899
#ifndef __riscv_float_abi_soft
49100
lw t1, MCONTEXT_FSR(t0)
50101

@@ -66,7 +117,11 @@ LEAF (__setcontext)
66117

67118
/* Note the contents of argument registers will be random
68119
unless makecontext() has been called. */
120+
#ifdef __riscv_landing_pad
121+
RESTORE_INT_REG (t2, 0, t0)
122+
#else
69123
RESTORE_INT_REG (t1, 0, t0)
124+
#endif
70125
RESTORE_INT_REG_CFI (ra, 1, t0)
71126
RESTORE_INT_REG (sp, 2, t0)
72127
RESTORE_INT_REG_CFI (s0, 8, t0)
@@ -90,7 +145,12 @@ LEAF (__setcontext)
90145
RESTORE_INT_REG_CFI (s10, 26, t0)
91146
RESTORE_INT_REG_CFI (s11, 27, t0)
92147

148+
#ifdef __riscv_landing_pad
149+
/* We need to use software-guared jump */
150+
jr t2
151+
#else
93152
jr t1
153+
#endif
94154

95155
99: tail __syscall_error
96156

@@ -99,12 +159,19 @@ libc_hidden_def (__setcontext)
99159
weak_alias (__setcontext, setcontext)
100160

101161
LEAF (__start_context)
162+
LPAD
102163

103164
/* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */
104165
cfi_register (ra, s0)
105166

106167
/* Call the function passed to makecontext. */
168+
#ifdef __riscv_landing_pad
169+
/* We need to use software-guared jump */
170+
mv t2, s1
171+
jalr t2
172+
#else
107173
jalr s1
174+
#endif
108175

109176
/* Invoke subsequent context if present, else exit(0). */
110177
mv a0, s2

sysdeps/unix/sysv/linux/riscv/swapcontext.S

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
<https://www.gnu.org/licenses/>. */
1818

1919
#include "ucontext-macros.h"
20+
#include "tcb-offsets.h"
2021

2122
/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
2223

2324
LEAF (__swapcontext)
25+
LPAD
2426
mv t0, a1 /* Save ucp into t0. */
2527

2628
SAVE_INT_REG (ra, 0, a0)
@@ -59,6 +61,25 @@ LEAF (__swapcontext)
5961
sw a1, MCONTEXT_FSR(a0)
6062
#endif /* __riscv_float_abi_soft */
6163

64+
#ifdef __riscv_shadow_stack
65+
/* Skip if shadow stack is not enabled */
66+
ssrdp ra
67+
beqz ra, .Lfin
68+
69+
/* Read ssp_base from TLS */
70+
ld t2, SSP_BASE_OFFSET(tp)
71+
bnez t2, .Lbase_saved
72+
73+
/* if not found, use current ssp as the marker */
74+
mv t2, ra
75+
sd t2, SSP_BASE_OFFSET(tp)
76+
77+
.Lbase_saved:
78+
/* Save caller's ssp and base marker to oucp */
79+
REG_S t2, UCONTEXT_SSP_BASE(a0)
80+
REG_S ra, UCONTEXT_SSP(a0)
81+
#endif
82+
6283
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
6384
li a3, _NSIG8
6485
add a2, a0, UCONTEXT_SIGMASK
@@ -70,6 +91,52 @@ LEAF (__swapcontext)
7091

7192
bltz a0, 99f
7293

94+
#ifdef __riscv_shadow_stack
95+
/* Load ss information from ucp */
96+
REG_L a0, UCONTEXT_SSP_BASE(t0)
97+
REG_L a1, UCONTEXT_SSP(t0)
98+
REG_L a2, SSP_BASE_OFFSET(tp)
99+
bne a0, a2, .Ldifferent_stack
100+
101+
.Lunwind:
102+
bleu a1, ra, .Lfin
103+
/* increase ssp by at most a page size to ensure always run into
104+
a guard page before accidentally point to another legal shadow
105+
stack page */
106+
/* ra = (a1 - ra >= 4096) ? ra + 4096 : a1 */
107+
lui t2, 1
108+
add ra, ra, t2
109+
bleu ra, a1, 1f
110+
mv ra, a1
111+
1:
112+
csrw ssp, ra
113+
/* Test if the location pointed by ssp is legal */
114+
sspush ra
115+
sspopchk ra
116+
j .Lunwind
117+
118+
.Ldifferent_stack:
119+
/* Create restore token */
120+
sspush ra
121+
mv a4, a1
122+
123+
.Lfind_rstor_token:
124+
/* Probe and validate target restore token */
125+
ssamoswap.d a3, x0, (a4)
126+
addi a2, a4, 8
127+
beq a3, a2, .Lswitch_stack
128+
/* Restore the shadow stack and try the next slot */
129+
ssamoswap.d x0, a3, (a4)
130+
addi a4, a4, -8
131+
j .Lfind_rstor_token
132+
133+
.Lswitch_stack:
134+
/* Switch stack: update ssp and base */
135+
csrw ssp, a1
136+
REG_S a0, SSP_BASE_OFFSET(tp)
137+
.Lfin:
138+
#endif
139+
73140
#ifndef __riscv_float_abi_soft
74141
lw t1, MCONTEXT_FSR(t0)
75142

@@ -91,7 +158,11 @@ LEAF (__swapcontext)
91158

92159
/* Note the contents of argument registers will be random
93160
unless makecontext() has been called. */
161+
#ifdef __riscv_landing_pad
162+
RESTORE_INT_REG (t2, 0, t0)
163+
#else
94164
RESTORE_INT_REG (t1, 0, t0)
165+
#endif
95166
RESTORE_INT_REG (ra, 1, t0)
96167
RESTORE_INT_REG (sp, 2, t0)
97168
RESTORE_INT_REG (s0, 8, t0)
@@ -115,8 +186,12 @@ LEAF (__swapcontext)
115186
RESTORE_INT_REG (s10, 26, t0)
116187
RESTORE_INT_REG (s11, 27, t0)
117188

189+
#ifdef __riscv_landing_pad
190+
/* We need to use software-guared jump */
191+
jr t2
192+
#else
118193
jr t1
119-
194+
#endif
120195

121196
99: tail __syscall_error
122197

sysdeps/unix/sysv/linux/riscv/sysdep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ GNU_PROPERTY (FEATURE_1_AND, __VALUE_FOR_FEATURE_1_AND)
207207

208208
#else /* !__ASSEMBLER__ */
209209

210+
# define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
211+
210212
# if __WORDSIZE == 64
211213
# define VDSO_NAME "LINUX_4.15"
212214
# define VDSO_HASH 182943605

0 commit comments

Comments
 (0)