1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (c) 2021, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker *
12*344aa361SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker *
15*344aa361SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker */
23*344aa361SAndroid Build Coastguard Worker
24*344aa361SAndroid Build Coastguard Worker #include <err.h>
25*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
26*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/mmutest/mmutest.h>
28*344aa361SAndroid Build Coastguard Worker #include <lib/trusty/trusty_app.h>
29*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
30*344aa361SAndroid Build Coastguard Worker
31*344aa361SAndroid Build Coastguard Worker #if USER_SCS_ENABLED
32*344aa361SAndroid Build Coastguard Worker #define FEATURE_GATED_TEST_NAME(name) name
33*344aa361SAndroid Build Coastguard Worker
34*344aa361SAndroid Build Coastguard Worker /**
35*344aa361SAndroid Build Coastguard Worker * translate_uspace_ptr() - Translate userspace pointer to shadow stack
36*344aa361SAndroid Build Coastguard Worker * @uspace: An address space of a trust app
37*344aa361SAndroid Build Coastguard Worker * @uspace_ptr: Pointer into above user space.
38*344aa361SAndroid Build Coastguard Worker * @kspace_ptr_out: Pointer translated into the kernel's address space. The
39*344aa361SAndroid Build Coastguard Worker * value of this output parameter should not be consumed
40*344aa361SAndroid Build Coastguard Worker * if this function returned a negative error code.
41*344aa361SAndroid Build Coastguard Worker *
42*344aa361SAndroid Build Coastguard Worker * Attempt to translate userspace pointer into its kernel equivalent. We
43*344aa361SAndroid Build Coastguard Worker * cannot simply dereference a userspace pointer because the TLB isn't
44*344aa361SAndroid Build Coastguard Worker * loaded with the correct page table. Instead, we translate the pointer
45*344aa361SAndroid Build Coastguard Worker * to physical memory and then into the kernel virtual address space.
46*344aa361SAndroid Build Coastguard Worker * Translation can fail the userspace address is not backed by physical
47*344aa361SAndroid Build Coastguard Worker * memory; this is the case for guard pages.
48*344aa361SAndroid Build Coastguard Worker *
49*344aa361SAndroid Build Coastguard Worker * Return:
50*344aa361SAndroid Build Coastguard Worker * * NO_ERROR - if translation succeeded
51*344aa361SAndroid Build Coastguard Worker * * ERR_OUT_OF_RANGE - if address translation failed
52*344aa361SAndroid Build Coastguard Worker * * ERR_NOT_FOUND - if pointer is not backed by physical memory
53*344aa361SAndroid Build Coastguard Worker * * ERR_INVALID_ARGS - if kspace_ptr_out is NULL
54*344aa361SAndroid Build Coastguard Worker */
translate_uspace_ptr(struct vmm_aspace * uspace,vaddr_t uspace_ptr,vaddr_t * kspace_ptr_out)55*344aa361SAndroid Build Coastguard Worker static int translate_uspace_ptr(struct vmm_aspace* uspace,
56*344aa361SAndroid Build Coastguard Worker vaddr_t uspace_ptr,
57*344aa361SAndroid Build Coastguard Worker vaddr_t* kspace_ptr_out) {
58*344aa361SAndroid Build Coastguard Worker paddr_t phys_ptr;
59*344aa361SAndroid Build Coastguard Worker uint flags;
60*344aa361SAndroid Build Coastguard Worker
61*344aa361SAndroid Build Coastguard Worker if (kspace_ptr_out == NULL) {
62*344aa361SAndroid Build Coastguard Worker return ERR_INVALID_ARGS;
63*344aa361SAndroid Build Coastguard Worker }
64*344aa361SAndroid Build Coastguard Worker *kspace_ptr_out = 0;
65*344aa361SAndroid Build Coastguard Worker
66*344aa361SAndroid Build Coastguard Worker /* translate userspace virtual address to physical address */
67*344aa361SAndroid Build Coastguard Worker status_t res =
68*344aa361SAndroid Build Coastguard Worker arch_mmu_query(&uspace->arch_aspace, uspace_ptr, &phys_ptr, &flags);
69*344aa361SAndroid Build Coastguard Worker /*
70*344aa361SAndroid Build Coastguard Worker * failures can happen if the pointer is invalid or points to a guard page
71*344aa361SAndroid Build Coastguard Worker * not backed by physical memory (in which case res is ERR_NOT_FOUND).
72*344aa361SAndroid Build Coastguard Worker */
73*344aa361SAndroid Build Coastguard Worker if (res) {
74*344aa361SAndroid Build Coastguard Worker return res;
75*344aa361SAndroid Build Coastguard Worker }
76*344aa361SAndroid Build Coastguard Worker
77*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(flags, ARCH_MMU_FLAG_PERM_NO_EXECUTE | ARCH_MMU_FLAG_PERM_USER,
78*344aa361SAndroid Build Coastguard Worker "Shadow call stack must point to non-executable user memory");
79*344aa361SAndroid Build Coastguard Worker
80*344aa361SAndroid Build Coastguard Worker /* translate physical address to kernel virtual address */
81*344aa361SAndroid Build Coastguard Worker *kspace_ptr_out = (vaddr_t)paddr_to_kvaddr(phys_ptr);
82*344aa361SAndroid Build Coastguard Worker ASSERT_NE(0, *kspace_ptr_out,
83*344aa361SAndroid Build Coastguard Worker "Failed to map phys addr to kernel virtual addr");
84*344aa361SAndroid Build Coastguard Worker
85*344aa361SAndroid Build Coastguard Worker return NO_ERROR;
86*344aa361SAndroid Build Coastguard Worker test_abort:
87*344aa361SAndroid Build Coastguard Worker return ERR_OUT_OF_RANGE;
88*344aa361SAndroid Build Coastguard Worker }
89*344aa361SAndroid Build Coastguard Worker
90*344aa361SAndroid Build Coastguard Worker struct scs_test_status {
91*344aa361SAndroid Build Coastguard Worker uint32_t running_apps;
92*344aa361SAndroid Build Coastguard Worker uint32_t invalid_apps;
93*344aa361SAndroid Build Coastguard Worker };
94*344aa361SAndroid Build Coastguard Worker
95*344aa361SAndroid Build Coastguard Worker /**
96*344aa361SAndroid Build Coastguard Worker * trusty_app_callback() - Test that app has a valid user shadow call stack
97*344aa361SAndroid Build Coastguard Worker *
98*344aa361SAndroid Build Coastguard Worker * @ta: Application to test
99*344aa361SAndroid Build Coastguard Worker * @status: Pointer to a structure tracking the current test status.
100*344aa361SAndroid Build Coastguard Worker */
trusty_app_callback(struct trusty_app * ta,void * status)101*344aa361SAndroid Build Coastguard Worker static void trusty_app_callback(struct trusty_app* ta, void* status) {
102*344aa361SAndroid Build Coastguard Worker struct scs_test_status* status_ptr = (struct scs_test_status*)status;
103*344aa361SAndroid Build Coastguard Worker if (strcmp(ta->props.app_name, "userscs-custom") == 0) {
104*344aa361SAndroid Build Coastguard Worker /* were we able to request a custom shadow stack size? */
105*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ta->props.min_shadow_stack_size, 128);
106*344aa361SAndroid Build Coastguard Worker } else if (strcmp(ta->props.app_name, "userscs-disabled") == 0) {
107*344aa361SAndroid Build Coastguard Worker /* were we able to opt out of shadow stacks? */
108*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ta->props.min_shadow_stack_size, 0);
109*344aa361SAndroid Build Coastguard Worker /* userscs-* apps loop infinitely so they'll always have a thread */
110*344aa361SAndroid Build Coastguard Worker ASSERT_NE((void*)ta->thread, NULL, "App has thread");
111*344aa361SAndroid Build Coastguard Worker ASSERT_EQ((void*)ta->thread->shadow_stack_base, NULL,
112*344aa361SAndroid Build Coastguard Worker "Shadow call stack was disabled");
113*344aa361SAndroid Build Coastguard Worker return;
114*344aa361SAndroid Build Coastguard Worker } else if (strcmp(ta->props.app_name, "userscs-default") == 0) {
115*344aa361SAndroid Build Coastguard Worker /* did default scs app get the default shadow stack size? */
116*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ta->props.min_shadow_stack_size, DEFAULT_SHADOW_STACK_SIZE,
117*344aa361SAndroid Build Coastguard Worker "Expected shadow call stack to have the default size");
118*344aa361SAndroid Build Coastguard Worker }
119*344aa361SAndroid Build Coastguard Worker
120*344aa361SAndroid Build Coastguard Worker /* size must be a multiple of the pointer size */
121*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(0, ta->props.min_shadow_stack_size % sizeof(vaddr_t),
122*344aa361SAndroid Build Coastguard Worker "Shadow call stack size is not a multiple of the pointer size");
123*344aa361SAndroid Build Coastguard Worker
124*344aa361SAndroid Build Coastguard Worker /*
125*344aa361SAndroid Build Coastguard Worker * Apps that aren't running may not have a thread allocated. Moreover,
126*344aa361SAndroid Build Coastguard Worker * apps that opt out of shadow call stacks need no further inspection.
127*344aa361SAndroid Build Coastguard Worker */
128*344aa361SAndroid Build Coastguard Worker if (ta->state != APP_RUNNING || ta->props.min_shadow_stack_size == 0) {
129*344aa361SAndroid Build Coastguard Worker return;
130*344aa361SAndroid Build Coastguard Worker }
131*344aa361SAndroid Build Coastguard Worker status_ptr->running_apps++;
132*344aa361SAndroid Build Coastguard Worker
133*344aa361SAndroid Build Coastguard Worker struct trusty_thread* tt = ta->thread;
134*344aa361SAndroid Build Coastguard Worker ASSERT_NE((void*)tt, NULL, "Running trusty app must have a valid thread");
135*344aa361SAndroid Build Coastguard Worker ASSERT_NE((void*)tt->shadow_stack_base, NULL,
136*344aa361SAndroid Build Coastguard Worker "Shadow call stack must point to allocation");
137*344aa361SAndroid Build Coastguard Worker
138*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(false, is_kernel_address(tt->shadow_stack_base),
139*344aa361SAndroid Build Coastguard Worker "Shadow stack on user thread points to kernel memory");
140*344aa361SAndroid Build Coastguard Worker
141*344aa361SAndroid Build Coastguard Worker ASSERT_NE(tt->stack_start, tt->shadow_stack_base,
142*344aa361SAndroid Build Coastguard Worker "Shadow stack on user thread aliases the regular stack");
143*344aa361SAndroid Build Coastguard Worker
144*344aa361SAndroid Build Coastguard Worker /*
145*344aa361SAndroid Build Coastguard Worker * Check the shadow stack size by examining the last element and one past
146*344aa361SAndroid Build Coastguard Worker * the last element. Note that these pointers are valid in the address
147*344aa361SAndroid Build Coastguard Worker * space of the trusty app, not in the current address space of a kernel
148*344aa361SAndroid Build Coastguard Worker * app. Therefore, we translate from the app's address space to the kernel
149*344aa361SAndroid Build Coastguard Worker * addres space before dereferencing lest we generate an access violation.
150*344aa361SAndroid Build Coastguard Worker */
151*344aa361SAndroid Build Coastguard Worker
152*344aa361SAndroid Build Coastguard Worker vaddr_t past_last = (vaddr_t)tt->shadow_stack_base + tt->shadow_stack_size;
153*344aa361SAndroid Build Coastguard Worker vaddr_t last_elem = past_last - sizeof(vaddr_t);
154*344aa361SAndroid Build Coastguard Worker /* a whole number of pages is allocated no matter the shadow stack size */
155*344aa361SAndroid Build Coastguard Worker vaddr_t pre_first = last_elem - round_up(tt->shadow_stack_size, PAGE_SIZE);
156*344aa361SAndroid Build Coastguard Worker vaddr_t elem_translated, ignored;
157*344aa361SAndroid Build Coastguard Worker
158*344aa361SAndroid Build Coastguard Worker struct vmm_aspace* uspace = ta->aspace;
159*344aa361SAndroid Build Coastguard Worker
160*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR,
161*344aa361SAndroid Build Coastguard Worker translate_uspace_ptr(uspace, last_elem, &elem_translated),
162*344aa361SAndroid Build Coastguard Worker "Actual size of shadow stack differs from recorded size");
163*344aa361SAndroid Build Coastguard Worker /*
164*344aa361SAndroid Build Coastguard Worker * Check that test app uses its shadow stack as expected. The shadow call
165*344aa361SAndroid Build Coastguard Worker * stack is zero-initialized and once a stack slot is used it can never
166*344aa361SAndroid Build Coastguard Worker * become zero again.
167*344aa361SAndroid Build Coastguard Worker */
168*344aa361SAndroid Build Coastguard Worker if (strcmp(ta->props.app_name, "userscs-default") == 0) {
169*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(0, *(vaddr_t*)elem_translated,
170*344aa361SAndroid Build Coastguard Worker "Expected last element of shadow stack to be zero "
171*344aa361SAndroid Build Coastguard Worker "(unused)");
172*344aa361SAndroid Build Coastguard Worker
173*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, translate_uspace_ptr(uspace, tt->shadow_stack_base,
174*344aa361SAndroid Build Coastguard Worker &elem_translated));
175*344aa361SAndroid Build Coastguard Worker /*
176*344aa361SAndroid Build Coastguard Worker * The link register is initially zero so when shadow call stacks are
177*344aa361SAndroid Build Coastguard Worker * enabled for libc, the second element holds the first non-zero entry
178*344aa361SAndroid Build Coastguard Worker */
179*344aa361SAndroid Build Coastguard Worker EXPECT_NE(0, *(vaddr_t*)elem_translated + sizeof(vaddr_t),
180*344aa361SAndroid Build Coastguard Worker "Expected second element of shadow stack to be non-zero "
181*344aa361SAndroid Build Coastguard Worker "(used)");
182*344aa361SAndroid Build Coastguard Worker }
183*344aa361SAndroid Build Coastguard Worker
184*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NOT_FOUND, translate_uspace_ptr(uspace, past_last, &ignored),
185*344aa361SAndroid Build Coastguard Worker "Expected guard page after shadow stack on user thread");
186*344aa361SAndroid Build Coastguard Worker
187*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NOT_FOUND, translate_uspace_ptr(uspace, pre_first, &ignored),
188*344aa361SAndroid Build Coastguard Worker "Expected guard page before shadow stack on user thread");
189*344aa361SAndroid Build Coastguard Worker
190*344aa361SAndroid Build Coastguard Worker return;
191*344aa361SAndroid Build Coastguard Worker test_abort:
192*344aa361SAndroid Build Coastguard Worker status_ptr->invalid_apps++;
193*344aa361SAndroid Build Coastguard Worker }
194*344aa361SAndroid Build Coastguard Worker
inspect_trusty_threads(void)195*344aa361SAndroid Build Coastguard Worker static int inspect_trusty_threads(void) {
196*344aa361SAndroid Build Coastguard Worker struct scs_test_status status = {0};
197*344aa361SAndroid Build Coastguard Worker trusty_app_forall(trusty_app_callback, &status);
198*344aa361SAndroid Build Coastguard Worker ASSERT_NE(0, status.running_apps);
199*344aa361SAndroid Build Coastguard Worker return status.invalid_apps;
200*344aa361SAndroid Build Coastguard Worker test_abort:
201*344aa361SAndroid Build Coastguard Worker return -1;
202*344aa361SAndroid Build Coastguard Worker }
203*344aa361SAndroid Build Coastguard Worker #else
204*344aa361SAndroid Build Coastguard Worker #define FEATURE_GATED_TEST_NAME(name) DISABLED_##name
205*344aa361SAndroid Build Coastguard Worker
inspect_trusty_threads(void)206*344aa361SAndroid Build Coastguard Worker static int inspect_trusty_threads(void) {
207*344aa361SAndroid Build Coastguard Worker return 0;
208*344aa361SAndroid Build Coastguard Worker }
209*344aa361SAndroid Build Coastguard Worker
210*344aa361SAndroid Build Coastguard Worker #endif
211*344aa361SAndroid Build Coastguard Worker
TEST(userscstest,FEATURE_GATED_TEST_NAME (user_threads_have_scs))212*344aa361SAndroid Build Coastguard Worker TEST(userscstest, FEATURE_GATED_TEST_NAME(user_threads_have_scs)) {
213*344aa361SAndroid Build Coastguard Worker int res = inspect_trusty_threads();
214*344aa361SAndroid Build Coastguard Worker EXPECT_NE(-1, res, "There were no running apps with threads to inspect");
215*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(0, res,
216*344aa361SAndroid Build Coastguard Worker "One or more apps did not have the expected shadow call stack");
217*344aa361SAndroid Build Coastguard Worker }
218*344aa361SAndroid Build Coastguard Worker
219*344aa361SAndroid Build Coastguard Worker PORT_TEST(userscstest, "com.android.kernel.userscstest");
220