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