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