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 /* Tests for ARM64 FEAT_BTI (Branch Target Identification) 25 * This is a mandatory CPU feature at ARM-A v8.5. Prior to that level, the 26 * BTI instructions are treated as NOPs and there is no enforcement. 27 * The test here will check either case, based on build configuration and 28 * runtime target support. 29 * Since this is an ARM64 feature, this should not be built for other arches. 30 */ 31 #ifndef ARCH_ARM64 32 #error BTI is an ARM64 feature 33 #endif 34 35 #include "btitest.h" 36 #include <arch/ops.h> 37 #include <err.h> 38 #include <lib/unittest/unittest.h> 39 #include <lk/init.h> 40 #include <stdio.h> 41 42 /** Assembly relative function call test of all BTI-relevant calls. 43 */ 44 int btitest_bl(void); 45 46 /* Assembly indirect call functions, using all BTI-relevant calls. 47 * BR via x16 and x17 is often used by linkers for veneers and has some 48 * additional handling described in the ARM Architecture Reference Manual, 49 * Table D8-36 (IYWFHD). 50 * The passed func_idx should be one of the BTITEST_CALLEE_ macros, which covers 51 * the landing pad instruction types given in the ARM Architecture Reference 52 * Manual, Table D8-37 (ICNBPL). 53 */ 54 int btitest_blr(int func_idx); 55 int btitest_br_x16(int func_idx); 56 int btitest_br_x17(int func_idx); 57 int btitest_br(int func_idx); 58 59 /* Get the expected return code when a BTI access should be trapped */ bti_trap_code(void)60 static int bti_trap_code(void) { 61 #ifdef KERNEL_BTI_ENABLED 62 if (arch_bti_supported()) { 63 return ERR_FAULT; 64 } 65 #endif 66 /* No BTI, or not enabled - faults are not detected */ 67 return 0; 68 } 69 TEST(btitest,supported)70 TEST(btitest, supported) { 71 if (!arch_bti_supported()) { 72 trusty_unittest_printf("[ INFO ] BTI is not supported\n"); 73 GTEST_SKIP(); 74 } 75 EXPECT_EQ(true, arch_bti_supported()); 76 test_abort:; 77 } 78 79 /* Smoke-test the callee functions; they should return 0 when called with BL */ TEST(btitest,smoke)80 TEST(btitest, smoke) { 81 EXPECT_EQ(0, btitest_bl()); 82 } 83 TEST(btitest,nop)84 TEST(btitest, nop) { 85 /* Fault on jump or call to non-bti target */ 86 EXPECT_EQ(bti_trap_code(), btitest_br(BTITEST_CALLEE_NOP)); 87 EXPECT_EQ(bti_trap_code(), btitest_blr(BTITEST_CALLEE_NOP)); 88 EXPECT_EQ(bti_trap_code(), btitest_br_x16(BTITEST_CALLEE_NOP)); 89 EXPECT_EQ(bti_trap_code(), btitest_br_x17(BTITEST_CALLEE_NOP)); 90 } 91 TEST(btitest,bti)92 TEST(btitest, bti) { 93 /* Fault on any jump or call to non-target bti */ 94 EXPECT_EQ(bti_trap_code(), btitest_br(BTITEST_CALLEE_BTI)); 95 EXPECT_EQ(bti_trap_code(), btitest_blr(BTITEST_CALLEE_BTI)); 96 EXPECT_EQ(bti_trap_code(), btitest_br_x16(BTITEST_CALLEE_BTI)); 97 EXPECT_EQ(bti_trap_code(), btitest_br_x17(BTITEST_CALLEE_BTI)); 98 } 99 TEST(btitest,bti_c)100 TEST(btitest, bti_c) { 101 /* Call or branch via x16/17 to a call target is valid */ 102 EXPECT_EQ(0, btitest_blr(BTITEST_CALLEE_BTI_C)); 103 EXPECT_EQ(0, btitest_br_x16(BTITEST_CALLEE_BTI_C)); 104 EXPECT_EQ(0, btitest_br_x17(BTITEST_CALLEE_BTI_C)); 105 106 /* Fault on branch to call target */ 107 EXPECT_EQ(bti_trap_code(), btitest_br(BTITEST_CALLEE_BTI_C)); 108 } 109 TEST(btitest,bti_j)110 TEST(btitest, bti_j) { 111 /* Any branch to jump target is valid */ 112 EXPECT_EQ(0, btitest_br(BTITEST_CALLEE_BTI_J)); 113 EXPECT_EQ(0, btitest_br_x16(BTITEST_CALLEE_BTI_J)); 114 EXPECT_EQ(0, btitest_br_x17(BTITEST_CALLEE_BTI_J)); 115 116 /* Fault on call to jump target */ 117 EXPECT_EQ(bti_trap_code(), btitest_blr(BTITEST_CALLEE_BTI_J)); 118 } 119 TEST(btitest,bti_jc)120 TEST(btitest, bti_jc) { 121 /* Either branch type allowed to call and jump target */ 122 EXPECT_EQ(0, btitest_br(BTITEST_CALLEE_BTI_JC)); 123 EXPECT_EQ(0, btitest_br_x16(BTITEST_CALLEE_BTI_JC)); 124 EXPECT_EQ(0, btitest_br_x17(BTITEST_CALLEE_BTI_JC)); 125 EXPECT_EQ(0, btitest_blr(BTITEST_CALLEE_BTI_JC)); 126 } 127 TEST(btitest,pacisp)128 TEST(btitest, pacisp) { 129 if (!arch_pac_address_supported()) { 130 trusty_unittest_printf("[ INFO ] PAC is not supported\n"); 131 GTEST_SKIP(); 132 } 133 134 /* PACIASP is a valid target for all branch types */ 135 EXPECT_EQ(0, btitest_br(BTITEST_CALLEE_PACIASP)); 136 EXPECT_EQ(0, btitest_br_x16(BTITEST_CALLEE_PACIASP)); 137 EXPECT_EQ(0, btitest_br_x17(BTITEST_CALLEE_PACIASP)); 138 EXPECT_EQ(0, btitest_blr(BTITEST_CALLEE_PACIASP)); 139 140 /* PACIBSP is a valid target for all branch types */ 141 EXPECT_EQ(0, btitest_br(BTITEST_CALLEE_PACIBSP)); 142 EXPECT_EQ(0, btitest_br_x16(BTITEST_CALLEE_PACIBSP)); 143 EXPECT_EQ(0, btitest_br_x17(BTITEST_CALLEE_PACIBSP)); 144 EXPECT_EQ(0, btitest_blr(BTITEST_CALLEE_PACIBSP)); 145 test_abort:; 146 } 147 148 PORT_TEST(btitest, "com.android.kernel.btitest"); 149