Skip to content

Commit 337c0b3

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 11d49ca commit 337c0b3

File tree

5 files changed

+175
-1
lines changed

5 files changed

+175
-1
lines changed

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

Lines changed: 24 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,28 @@ 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+
79+
/* clean up */
80+
xor t0, t0, t0
81+
xor t1, t1, t1
82+
.Lskip_ss:
83+
#endif
84+
6185
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
6286
li a3, _NSIG8
6387
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: 58 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,46 @@ 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, .Lstack_switch
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+
.Lstack_switch:
78+
/* Create restore token */
79+
sspush ra
80+
/* Validate target restore token */
81+
ssamoswap.d a3, x0, (a1)
82+
addi a1, a1, 8
83+
bne a3, a1, 99f
84+
/* Switch stack: update ssp and base */
85+
csrw ssp, a1
86+
REG_S t1, SSP_BASE_OFFSET(tp)
87+
.Lfin:
88+
#endif
89+
4890
#ifndef __riscv_float_abi_soft
4991
lw t1, MCONTEXT_FSR(t0)
5092

@@ -66,7 +108,11 @@ LEAF (__setcontext)
66108

67109
/* Note the contents of argument registers will be random
68110
unless makecontext() has been called. */
111+
#ifdef __riscv_landing_pad
112+
RESTORE_INT_REG (t2, 0, t0)
113+
#else
69114
RESTORE_INT_REG (t1, 0, t0)
115+
#endif
70116
RESTORE_INT_REG_CFI (ra, 1, t0)
71117
RESTORE_INT_REG (sp, 2, t0)
72118
RESTORE_INT_REG_CFI (s0, 8, t0)
@@ -90,7 +136,12 @@ LEAF (__setcontext)
90136
RESTORE_INT_REG_CFI (s10, 26, t0)
91137
RESTORE_INT_REG_CFI (s11, 27, t0)
92138

139+
#ifdef __riscv_landing_pad
140+
/* We need to use software-guared jump */
141+
jr t2
142+
#else
93143
jr t1
144+
#endif
94145

95146
99: tail __syscall_error
96147

@@ -99,12 +150,19 @@ libc_hidden_def (__setcontext)
99150
weak_alias (__setcontext, setcontext)
100151

101152
LEAF (__start_context)
153+
LPAD
102154

103155
/* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */
104156
cfi_register (ra, s0)
105157

106158
/* Call the function passed to makecontext. */
159+
#ifdef __riscv_landing_pad
160+
/* We need to use software-guared jump */
161+
mv t2, s1
162+
jalr t2
163+
#else
107164
jalr s1
165+
#endif
108166

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

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

Lines changed: 73 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,10 @@ LEAF (__swapcontext)
5961
sw a1, MCONTEXT_FSR(a0)
6062
#endif /* __riscv_float_abi_soft */
6163

64+
#ifdef __riscv_shadow_stack
65+
mv t1, a0 /* Save oucp into t1. */
66+
#endif
67+
6268
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
6369
li a3, _NSIG8
6470
add a2, a0, UCONTEXT_SIGMASK
@@ -70,6 +76,64 @@ LEAF (__swapcontext)
7076

7177
bltz a0, 99f
7278

79+
#ifdef __riscv_shadow_stack
80+
/* Skip if shadow stack is not enabled */
81+
ssrdp ra
82+
beqz ra, .Lfin
83+
84+
/* Read ssp_base from TLS */
85+
ld t2, SSP_BASE_OFFSET(tp)
86+
bnez t2, .Lbase_saved
87+
88+
/* if not found, use current ssp as the marker */
89+
mv t2, ra
90+
sd t2, SSP_BASE_OFFSET(tp)
91+
92+
.Lbase_saved:
93+
/* Save caller's ssp and base marker to oucp */
94+
REG_S t2, UCONTEXT_SSP_BASE(t1)
95+
96+
/* Load ss information from ucp */
97+
REG_L a0, UCONTEXT_SSP_BASE(t0)
98+
REG_L a1, UCONTEXT_SSP(t0)
99+
REG_L a2, SSP_BASE_OFFSET(tp)
100+
bne a0, a2, .Lstack_switch
101+
102+
.Lunwind:
103+
/* Save ssp to oucp */
104+
REG_S ra, UCONTEXT_SSP(t1)
105+
bleu a1, ra, .Lfin
106+
/* increase ssp by at most a page size to ensure always run into
107+
a guard page before accidentally point to another legal shadow
108+
stack page */
109+
/* ra = (a1 - ra >= 4096) ? ra + 4096 : a1 */
110+
lui t2, 1
111+
add ra, ra, t2
112+
bleu ra, a1, 1f
113+
mv ra, a1
114+
1:
115+
csrw ssp, ra
116+
/* Test if the location pointed by ssp is legal */
117+
sspush ra
118+
sspopchk ra
119+
j .Lunwind
120+
121+
.Lstack_switch:
122+
/* Create restore token */
123+
sspush ra
124+
/* Reload and save ssp to oucp after adjustion */
125+
ssrdp ra
126+
REG_S ra, UCONTEXT_SSP(t1)
127+
/* Validate target restore token */
128+
ssamoswap.d a3, x0, (a1)
129+
addi a1, a1, 8
130+
bne a3, a1, 99f
131+
/* Switch stack: update ssp and base */
132+
csrw ssp, a1
133+
REG_S a0, SSP_BASE_OFFSET(tp)
134+
.Lfin:
135+
#endif
136+
73137
#ifndef __riscv_float_abi_soft
74138
lw t1, MCONTEXT_FSR(t0)
75139

@@ -91,7 +155,11 @@ LEAF (__swapcontext)
91155

92156
/* Note the contents of argument registers will be random
93157
unless makecontext() has been called. */
158+
#ifdef __riscv_landing_pad
159+
RESTORE_INT_REG (t2, 0, t0)
160+
#else
94161
RESTORE_INT_REG (t1, 0, t0)
162+
#endif
95163
RESTORE_INT_REG (ra, 1, t0)
96164
RESTORE_INT_REG (sp, 2, t0)
97165
RESTORE_INT_REG (s0, 8, t0)
@@ -115,8 +183,12 @@ LEAF (__swapcontext)
115183
RESTORE_INT_REG (s10, 26, t0)
116184
RESTORE_INT_REG (s11, 27, t0)
117185

186+
#ifdef __riscv_landing_pad
187+
/* We need to use software-guared jump */
188+
jr t2
189+
#else
118190
jr t1
119-
191+
#endif
120192

121193
99: tail __syscall_error
122194

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)