1/* 2 * Copyright (c) 2022, Google Inc. All rights reserved 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <asm.h> 25#include <arch/asm_macros.h> 26#include <err.h> 27#include "btitest.h" 28 29.section .text 30 31/* Fault handler to return where BTI calls fail. 32 * On return from the caught Branch Target exception, PSTATE.BTYPE will still 33 * be set according to the last branch taken. Therefore we need to land on a 34 * BTI jc to be compatible with all callers - and avoid another immediate 35 * Branch Target exception. 36 */ 37.Lbtitest_callee_fault: 38 bti jc 39 mov x0, #ERR_FAULT 40 ret 41 42/** 43 * int btitest_bl(void) - Use bl to call each of the test functions 44 * 45 * This calls each of the test functions using bl and a relative offset, 46 * which should always be allowed. The functions are expected to all return 0. 47 * 48 * Returns The first non-zero return code, or 0 if all functions pass. 49 */ 50FUNCTION(btitest_bl) 51 push lr, xzr 52 bl btitest_callee_nop 53 cbnz x0, .Lerror 54 bl btitest_callee_bti 55 cbnz x0, .Lerror 56 bl btitest_callee_bti_c 57 cbnz x0, .Lerror 58 bl btitest_callee_bti_j 59 cbnz x0, .Lerror 60 bl btitest_callee_bti_jc 61 cbnz x0, .Lerror 62 bl btitest_callee_paciasp 63 cbnz x0, .Lerror 64 bl btitest_callee_pacibsp 65.Lerror: 66 pop lr, xzr 67 ret 68 69/** 70 * int btitest_blr(int) - Use blr to call the passed function 71 * 72 * Returns The called function's return value 73 */ 74FUNCTION(btitest_blr) 75 push lr, xzr 76 bl get_callee 77 blr x0 78 pop lr, xzr 79 ret 80 81/** 82 * int btitest_br(int) - Use br to call the passed function via the x0 register 83 * 84 * Returns The called function's return value 85 */ 86FUNCTION(btitest_br) 87 push lr, xzr 88 bl get_callee 89 pop lr, xzr 90 br x0 91 92/** 93 * int btitest_br_x16(int) - Use br to call the passed function via the x16 94 * register 95 * 96 * Returns The called function's return value 97 */ 98FUNCTION(btitest_br_x16) 99 push lr, xzr 100 bl get_callee 101 pop lr, xzr 102 mov x16, x0 103 br x16 104 105/** 106 * int btitest_br_x17(int) - Use br to call the passed function via the x17 107 * register 108 * 109 * Returns The called function's return value 110 */ 111FUNCTION(btitest_br_x17) 112 push lr, xzr 113 bl get_callee 114 pop lr, xzr 115 mov x17, x0 116 br x17 117 118/** 119 * int btitest_callee_nop(void) - Function with nop instruction 120 * 121 * Returns ERR_FAULT if the BTI check fails. 122 * Return 0 if the BTI check passes. 123 */ 124LOCAL_FUNCTION(btitest_callee_nop) 125 set_fault_handler .Lbtitest_callee_fault 126 nop 127 mov x0, #0 128 ret 129 130/** 131 * int btitest_callee_bti(void) - Function with bti instruction 132 * 133 * Returns ERR_FAULT if the BTI check fails. 134 * Return 0 if the BTI check passes. 135 */ 136LOCAL_FUNCTION(btitest_callee_bti) 137 set_fault_handler .Lbtitest_callee_fault 138 bti 139 mov x0, #0 140 ret 141 142/** 143 * int btitest_callee_bti_c(void) - Function with bti c instruction 144 * 145 * Returns ERR_FAULT if the BTI check fails. 146 * Return 0 if the BTI check passes. 147 */ 148LOCAL_FUNCTION(btitest_callee_bti_c) 149 set_fault_handler .Lbtitest_callee_fault 150 bti c 151 mov x0, #0 152 ret 153 154/** 155 * int btitest_callee_bti_j(void) - Function with bti j instruction 156 * 157 * Returns ERR_FAULT if the BTI check fails. 158 * Return 0 if the BTI check passes. 159 */ 160LOCAL_FUNCTION(btitest_callee_bti_j) 161 set_fault_handler .Lbtitest_callee_fault 162 bti j 163 mov x0, #0 164 ret 165 166/** 167 * int btitest_callee_bti_jc(void) - Function with bti jc instruction 168 * 169 * Returns ERR_FAULT if the BTI check fails. 170 * Return 0 if the BTI check passes. 171 */ 172LOCAL_FUNCTION(btitest_callee_bti_jc) 173 set_fault_handler .Lbtitest_callee_fault 174 bti jc 175 mov x0, #0 176 ret 177 178/** 179 * int btitest_callee_paciasp(void) - Function with paciasp instruction 180 * 181 * Returns ERR_FAULT if the BTI check fails. 182 * Return 0 if the BTI check passes. 183 */ 184LOCAL_FUNCTION(btitest_callee_paciasp) 185 set_fault_handler .Lbtitest_callee_fault 186 paciasp 187 mov x0, #0 188 autiasp 189 ret 190 191/** 192 * int btitest_callee_pacibsp(void) - Function with pacibsp instruction 193 * 194 * Returns ERR_FAULT if the BTI check fails. 195 * Return 0 if the BTI check passes. 196 */ 197LOCAL_FUNCTION(btitest_callee_pacibsp) 198 set_fault_handler .Lbtitest_callee_fault 199 pacibsp 200 mov x0, #0 201 autibsp 202 ret 203 204/** 205 * int btitest_callee_error(void) - Error function which always fails 206 * 207 * This is valid as any jump target. 208 * 209 * Returns ERR_INVALID_ARGS unconditionally. 210 */ 211LOCAL_FUNCTION(btitest_callee_error) 212 bti jc 213 mov x0, #ERR_INVALID_ARGS 214 ret 215 216/** 217 * get_callee(int) - Get the address of the callee function. 218 * 219 * Converts the passed function index into the function address. 220 * This is done here to avoid using the C compiler to get function addresses - 221 * the compiler may insert veneers or indirection under some situations (e.g. 222 * for CFI) and break the specific landing pad instructions needed to test BTI. 223 * 224 * Return 0 if the index is not recognised, otherwise the function address. 225 */ 226LOCAL_FUNCTION(get_callee) 227 cmp w0, #BTITEST_CALLEE_NOP 228 bne .Ltry_bti 229 adr x0, btitest_callee_nop 230 ret 231.Ltry_bti: 232 cmp w0, #BTITEST_CALLEE_BTI 233 bne .Ltry_bti_c 234 adr x0, btitest_callee_bti 235 ret 236.Ltry_bti_c: 237 cmp w0, #BTITEST_CALLEE_BTI_C 238 bne .Ltry_bti_j 239 adr x0, btitest_callee_bti_c 240 ret 241.Ltry_bti_j: 242 cmp w0, #BTITEST_CALLEE_BTI_J 243 bne .Ltry_bti_jc 244 adr x0, btitest_callee_bti_j 245 ret 246.Ltry_bti_jc: 247 cmp w0, #BTITEST_CALLEE_BTI_JC 248 bne .Ltry_paciasp 249 adr x0, btitest_callee_bti_jc 250 ret 251.Ltry_paciasp: 252 cmp w0, #BTITEST_CALLEE_PACIASP 253 bne .Ltry_pacibsp 254 adr x0, btitest_callee_paciasp 255 ret 256.Ltry_pacibsp: 257 cmp w0, #BTITEST_CALLEE_PACIBSP 258 bne .Lunknown 259 adr x0, btitest_callee_pacibsp 260 ret 261.Lunknown: 262 /* Return error function which unconditionally fails any test */ 263 adr x0, btitest_callee_error 264 ret 265