1 /*
2  * Copyright (c) 2021, 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 <err.h>
25 #include <kernel/thread.h>
26 #include <kernel/vm.h>
27 #include <lib/unittest/unittest.h>
28 #include <lib/mmutest/mmutest.h>
29 
30 #if KERNEL_SCS_ENABLED
31 #define FEATURE_GATED_TEST_NAME(name) name
32 
33 /**
34  * inspect_thread() - Inspect the shadow stack of a thread
35  *
36  * @t: thread to test
37  * @ss_sz: expected shadow stack size
38  */
inspect_thread(thread_t * t,size_t ss_sz)39 static void inspect_thread(thread_t *t, size_t ss_sz) {
40     /* all threads have a shadow stack when the feature is enabled */
41     ASSERT_NE(NULL, t->shadow_stack, "Shadow call stack missing");
42     ASSERT_EQ(true, is_kernel_address((vaddr_t)t->shadow_stack),
43               "Shadow call stack does not point to kernel memory");
44     EXPECT_EQ(t->shadow_stack_size,
45               round_up(t->shadow_stack_size, sizeof(vaddr_t)),
46               "Shadow call stack size was not rounded to the pointer size");
47     EXPECT_NE(t->stack, t->shadow_stack,
48               "Shadow call stack aliases the regular stack");
49     EXPECT_EQ(ss_sz, t->shadow_stack_size,
50               "Shadow call stack did not have the expected size");
51 
52     /* check the shadow stack size by inverting the last element */
53     void* last_elem = t->shadow_stack + t->shadow_stack_size - sizeof(vaddr_t);
54     EXPECT_EQ(NO_ERROR,
55               mmutest_arch_store_uint32((uint32_t*)last_elem, false),
56               "Actual size of shadow call stack differs from recorded size");
57     /* restore last_elem by calling mmutest_arch_store_uint32 a second time */
58     EXPECT_EQ(NO_ERROR,
59               mmutest_arch_store_uint32((uint32_t*)last_elem, false),
60               "Restoring last element of shadow stack failed");
61 
62     const size_t extra_space = round_up(t->shadow_stack_size, PAGE_SIZE) -
63                                t->shadow_stack_size;
64     void *const guard_region = t->shadow_stack - extra_space;
65     EXPECT_EQ(0, (vaddr_t)guard_region & (PAGE_SIZE - 1),
66               "Shadow call stack guard region is not page aligned");
67 
68     /* check for guard page before the shadow stack */
69     void* before_guard_end = guard_region - sizeof(uint32_t);
70     ASSERT_EQ(ERR_GENERIC,
71               mmutest_arch_store_uint32((uint32_t*)before_guard_end, false),
72               "Expected guard page after shadow call stack");
73 
74     /* check for guard page after the shadow stack */
75     void *after_guard_begin = t->shadow_stack + t->shadow_stack_size;
76     ASSERT_EQ(ERR_GENERIC,
77               mmutest_arch_store_uint32((uint32_t*)after_guard_begin, false),
78               "Expected guard page after shadow call stack");
79 
80     /*
81      * this test will not run on idle threads which are the only
82      * threads that do not have the free shadow stack flag set.
83      */
84     ASSERT_EQ(0, t->flags & THREAD_FLAG_IDLE, "Thread is an idle thread");
85     EXPECT_NE(0, t->flags & THREAD_FLAG_FREE_SHADOW_STACK,
86               "Shadow call stack did not have the free flag set");
87 
88     /*
89      * Shadow stacks grow up. Test that the shadow stack is set up such that
90      * we'll hit the guard page once we use the number of bytes corresponding
91      * to the shadow stack size even if more bytes were allocated. We do so
92      * by checking that all bytes are zero (i.e., unused) in the interval
93      * [guard_region...t->shadow_stack).
94      */
95     vaddr_t *slot = (vaddr_t *)guard_region;
96     while (slot <  (vaddr_t*)t->shadow_stack) {
97         ASSERT_EQ(0, *slot++, "Expected unused shadow call stack slot");
98     }
99 
100     /* shadow stack slots are either unused or point to kernel memory */
101     while (slot < (vaddr_t*)after_guard_begin) {
102         vaddr_t ret_addr = *slot++;
103         if (!ret_addr)
104             continue; /* slot is unused */
105         ASSERT_EQ(true, is_kernel_address(ret_addr),
106                   "Expected pointer to kernel memory");
107     }
108 
109 test_abort:;
110 }
111 #else
112 #define FEATURE_GATED_TEST_NAME(name) DISABLED_##name
113 
inspect_thread(thread_t * t,size_t ss_sz)114 static void inspect_thread(thread_t *t, size_t ss_sz) { }
115 #endif
116 
TEST(scstest,FEATURE_GATED_TEST_NAME (current_kernel_thread_has_scs))117 TEST(scstest, FEATURE_GATED_TEST_NAME(current_kernel_thread_has_scs)) {
118     thread_t *curr_thread = get_current_thread();
119     inspect_thread(curr_thread, DEFAULT_SHADOW_STACK_SIZE);
120 }
121 
new_thread_func(void * arg)122 static int new_thread_func(void* arg) {
123     size_t expected_shadow_stack_size = *(size_t*)arg;
124     thread_t *curr_thread = get_current_thread();
125     inspect_thread(curr_thread, expected_shadow_stack_size);
126     return 0;
127 }
128 
TEST(scstest,FEATURE_GATED_TEST_NAME (new_kernel_thread_has_scs))129 TEST(scstest, FEATURE_GATED_TEST_NAME(new_kernel_thread_has_scs)) {
130     int test_thread_ret;
131     size_t shadow_stack_size = DEFAULT_SHADOW_STACK_SIZE;
132     thread_t* test_thread =
133             thread_create("scstest_thread", new_thread_func,
134                           &shadow_stack_size, DEFAULT_PRIORITY,
135                           DEFAULT_STACK_SIZE);
136     ASSERT_NE(NULL, test_thread, "Failed to create test thread");
137 
138     ASSERT_EQ(NO_ERROR, thread_resume(test_thread), "Failed to start thread");
139 
140     ASSERT_EQ(NO_ERROR,
141               thread_join(test_thread, &test_thread_ret, INFINITE_TIME),
142               "Failed to wait on test thread");
143     /* test_thread is deallocated here, do inspection in new_thread_func */
144 
145 test_abort:;
146 }
147 
TEST(scstest,FEATURE_GATED_TEST_NAME (new_kernel_thread_has_custom_size))148 TEST(scstest, FEATURE_GATED_TEST_NAME(new_kernel_thread_has_custom_size)) {
149     int test_thread_ret;
150     size_t expected_shadow_stack_size = 128;
151     thread_t* test_thread =
152             thread_create_etc(NULL, "scstest_thread", new_thread_func,
153                               &expected_shadow_stack_size, DEFAULT_PRIORITY,
154                               NULL, DEFAULT_STACK_SIZE,
155                               expected_shadow_stack_size);
156     ASSERT_NE(NULL, test_thread, "Failed to create test thread");
157 
158     ASSERT_EQ(NO_ERROR, thread_resume(test_thread), "Failed to start thread");
159 
160     ASSERT_EQ(NO_ERROR,
161               thread_join(test_thread, &test_thread_ret, INFINITE_TIME),
162               "Failed to wait on test thread");
163 
164 test_abort:;
165 }
166 
167 PORT_TEST(scstest, "com.android.kernel.scstest");
168