77//
88// Also at this time this file is heavily based off the x86_64 file , so you'll
99// probably want to read th at one as well.
10+ //
11+ // Finally , control flow integrity hardening has been applied to the code using
12+ // the Pointer Authentication (PAuth) and Branch Target Identification (BTI)
13+ // technologies from the Arm instruction set architecture:
14+ // * All callable functions start with either the `BTI c` or `PACIASP`/`PACIBSP`
15+ // instructions
16+ // * Return addresses are signed and authenticated using the stack pointer
17+ // value as a modifier (similarly to the salt in a HMAC operation) ; the
18+ // `DW_CFA_AARCH64_negate_ra_state` DWARF operation (aliased with the
19+ // `.cfi_window_save` assembler directive) informs an unwinder about this
1020
1121#include "header.h"
1222
23+ #ifndef CFG_TARGET_OS_macos
24+ // We need to tell whatever loads the following code (e.g. the dynamic linker)
25+ // th at it is compatible with BTI , so th at the corresponding executable memory
26+ // pages have the necessary attribute set (if supported by the environment). To
27+ // this end , we follow the ELF for the Arm® 64 - bit Architecture standard , and
28+ // use a special metadata section. Further details are in section 6 . 2 of the
29+ // specification:
30+ //
31+ // https://github.com/ARM - software/abi - aa/blob/2022Q1/aaelf64/aaelf64.rst#program - property
32+ //
33+ // We also set the PAuth (PAC) property , even though it is optional , for the
34+ // sake of completeness.
35+ .pushsection .note.gnu.property , "a" ;
36+ .p2align 3 ;
37+ . word 4 ;
38+ . word 16 ;
39+ . word 5 ;
40+ .asciz "GNU" ;
41+ . word 0xc0000000 ; // GNU_PROPERTY_AARCH64_FEATURE_1_AND
42+ . word 4 ;
43+ . word 3 ; // GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC
44+ . word 0 ;
45+ .popsection
46+ #endif
47+
1348// fn(top_of_stack(%x0): * mut u8)
1449HIDDEN(wasmtime_fiber_switch)
1550GLOBL(wasmtime_fiber_switch)
1651.p2align 2
1752TYPE(wasmtime_fiber_switch)
1853FUNCTION(wasmtime_fiber_switch):
54+ .cfi_startproc
55+ #ifndef CFG_TARGET_OS_macos
56+ hint # 25 // paciasp
57+ .cfi_window_save
58+ #endif
1959 // Save all callee - saved registers on the stack since we're assuming
2060 // they're clobbered as a result of the stack switch.
21- stp lr , fp , [ sp , - 16 ] !
61+ stp x29 , x30 , [ sp , - 16 ] !
2262 stp x20 , x19 , [ sp , - 16 ] !
2363 stp x22 , x21 , [ sp , - 16 ] !
2464 stp x24 , x23 , [ sp , - 16 ] !
@@ -47,8 +87,13 @@ FUNCTION(wasmtime_fiber_switch):
4787 ldp x24 , x23 , [ sp ], 16
4888 ldp x22 , x21 , [ sp ], 16
4989 ldp x20 , x19 , [ sp ], 16
50- ldp lr , fp , [ sp ], 16
90+ ldp x29 , x30 , [ sp ], 16
91+ #ifndef CFG_TARGET_OS_macos
92+ hint # 29 // autiasp
93+ .cfi_window_save
94+ #endif
5195 ret
96+ .cfi_endproc
5297SIZE(wasmtime_fiber_switch)
5398
5499// fn(
@@ -61,15 +106,39 @@ GLOBL(wasmtime_fiber_init)
61106.p2align 2
62107TYPE(wasmtime_fiber_init)
63108FUNCTION(wasmtime_fiber_init):
64- adr x8 , FUNCTION(wasmtime_fiber_start)
65- stp x0 , x8 , [ x0 , - 0x28 ] // x0 => x19 , x8 => lr
109+ .cfi_startproc
110+ hint # 34 // bti c
111+ // We set up the newly initialized fiber , so th at it resumes execution from
112+ // wasmtime_fiber_start(). As a result , we need a signed address of this
113+ // function , so there are 2 requirements:
114+ // * The fiber stack pointer value th at is used by the signing operation
115+ // must match the value when the pointer is authenticated inside
116+ // wasmtime_fiber_switch() , otherwise the latter would fault
117+ // * We would like to use an instruction th at is executed as a no - op by
118+ // processors th at do not support PAuth , so th at the code is backward -
119+ // compatible and there is no duplication ; `PACIA1716` is a suitable
120+ // one , which has the following operand register conventions:
121+ // * X17 contains the pointer value to sign
122+ // * X16 contains the modifier value
123+ //
124+ // TODO: Use the PACGA instruction to authenticate the saved register state ,
125+ // which avoids creating signed pointers to wasmtime_fiber_start() , and
126+ // provides wider coverage.
127+ sub x16 , x0 , # 16
128+ adr x17 , FUNCTION(wasmtime_fiber_start)
129+ #ifndef CFG_TARGET_OS_macos
130+ hint # 8 // pacia1716
131+ #endif
132+ str x17 , [ x16 , - 0x8 ] // x17 => lr
133+ str x0 , [ x16 , - 0x18 ] // x0 => x19
66134 stp x2 , x1 , [ x0 , - 0x38 ] // x1 => x20 , x2 => x21
67135
68136 // `wasmtime_fiber_switch` has an 0xa0 byte stack , and we add 0x10 more for
69137 // the original reserved 16 bytes.
70138 add x8 , x0 , - 0xb0
71139 str x8 , [ x0 , - 0x10 ]
72140 ret
141+ .cfi_endproc
73142SIZE(wasmtime_fiber_init)
74143
75144.p2align 2
@@ -86,8 +155,11 @@ FUNCTION(wasmtime_fiber_start):
86155 0x06 , / * DW_OP_deref * / \
87156 0x23 , 0xa0 , 0x1 / * DW_OP_plus_uconst 0xa0 * /
88157
89- .cfi_rel_offset x29 , - 0x08
90- .cfi_rel_offset lr , - 0x10
158+ .cfi_rel_offset x29 , - 0x10
159+ #ifndef CFG_TARGET_OS_macos
160+ .cfi_window_save
161+ #endif
162+ .cfi_rel_offset x30 , - 0x08
91163 .cfi_rel_offset x19 , - 0x18
92164 .cfi_rel_offset x20 , - 0x20
93165 .cfi_rel_offset x21 , - 0x28
0 commit comments