xref: /xnu-11215.41.3/osfmk/kern/exclaves_tests.c (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1 /*
2  * Copyright (c) 2023 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #if CONFIG_EXCLAVES
30 
31 #if DEVELOPMENT || DEBUG
32 
33 #include <kern/kalloc.h>
34 #include <kern/locks.h>
35 
36 #include "exclaves_debug.h"
37 #include "exclaves_resource.h"
38 
39 /* External & generated headers */
40 #include <xrt_hosted_types/types.h>
41 #include <xnuproxy/messages.h>
42 
43 #include "exclaves_resource.h"
44 #include "exclaves_xnuproxy.h"
45 
46 #if __has_include(<Tightbeam/tightbeam.h>)
47 
48 #include <Tightbeam/tightbeam.h>
49 #include <Tightbeam/tightbeam_private.h>
50 #include "kern/exclaves.tightbeam.h"
51 
52 #define EXCLAVES_ID_HELLO_EXCLAVE_EP                 \
53     (exclaves_service_lookup(EXCLAVES_DOMAIN_KERNEL, \
54     "com.apple.service.ExclavesCHelloServer"))
55 
56 static int
exclaves_hello_exclave_test(__unused int64_t in,int64_t * out)57 exclaves_hello_exclave_test(__unused int64_t in, int64_t *out)
58 {
59 	tb_error_t tb_result;
60 	exclaveschelloserver_tests_s client;
61 
62 	if (exclaves_get_status() != EXCLAVES_STATUS_AVAILABLE) {
63 		exclaves_debug_printf(show_test_output,
64 		    "%s: SKIPPED: Exclaves not available\n", __func__);
65 		*out = -1;
66 		return 0;
67 	}
68 
69 	exclaves_debug_printf(show_test_output, "%s: STARTING\n", __func__);
70 
71 	tb_endpoint_t ep = tb_endpoint_create_with_value(TB_TRANSPORT_TYPE_XNU,
72 	    EXCLAVES_ID_HELLO_EXCLAVE_EP, TB_ENDPOINT_OPTIONS_NONE);
73 
74 	tb_result = exclaveschelloserver_tests__init(&client, ep);
75 	assert3u(tb_result, ==, TB_ERROR_SUCCESS);
76 
77 	tb_result = exclaveschelloserver_tests_default_hello(&client, ^(uint64_t result) {
78 		assert3u(tb_result, ==, TB_ERROR_SUCCESS);
79 		assert3u((uint16_t)(result), ==, 0x1338);
80 	});
81 
82 	exclaves_debug_printf(show_test_output, "%s: SUCCESS\n", __func__);
83 	*out = 1;
84 
85 	return KERN_SUCCESS;
86 }
87 SYSCTL_TEST_REGISTER(exclaves_hello_exclave_test, exclaves_hello_exclave_test);
88 
89 static int
exclaves_panic_exclave_test(__unused int64_t in,int64_t * out)90 exclaves_panic_exclave_test(__unused int64_t in, int64_t *out)
91 {
92 	tb_error_t tb_result;
93 	exclaveschelloserver_tests_s client;
94 
95 	if (exclaves_get_status() != EXCLAVES_STATUS_AVAILABLE) {
96 		exclaves_debug_printf(show_test_output,
97 		    "%s: SKIPPED: Exclaves not available\n", __func__);
98 		*out = -1;
99 		return 0;
100 	}
101 
102 	exclaves_debug_printf(show_test_output, "%s: STARTING\n", __func__);
103 
104 	tb_endpoint_t ep = tb_endpoint_create_with_value(TB_TRANSPORT_TYPE_XNU,
105 	    EXCLAVES_ID_HELLO_EXCLAVE_EP, TB_ENDPOINT_OPTIONS_NONE);
106 
107 	tb_result = exclaveschelloserver_tests__init(&client, ep);
108 	assert3u(tb_result, ==, TB_ERROR_SUCCESS);
109 
110 	tb_result = exclaveschelloserver_tests_panic_exclave_example(&client);
111 
112 	/* This should not be reachable. Hence, failed. */
113 	exclaves_debug_printf(show_test_output, "%s: FAILED\n", __func__);
114 	*out = -1;
115 
116 	return KERN_SUCCESS;
117 }
118 SYSCTL_TEST_REGISTER(exclaves_panic_exclave_test, exclaves_panic_exclave_test);
119 
120 #endif /* __has_include(<Tightbeam/tightbeam.h>) */
121 
122 static int
exclaves_sensor_kpi_test(int64_t in,int64_t * out)123 exclaves_sensor_kpi_test(int64_t in, int64_t *out)
124 {
125 #pragma unused(in)
126 #define SENSOR_TEST(x) \
127     if (!(x)) { \
128 	        exclaves_debug_printf(show_errors, \
129 	            "%s: FAILURE -- %s:%d\n", __func__, __FILE__, __LINE__); \
130 	success = false; \
131 	goto out; \
132     }
133 
134 	bool success = true;
135 	exclaves_debug_printf(show_test_output, "%s: STARTING\n", __func__);
136 
137 	exclaves_sensor_type_t sensors[] = {
138 		EXCLAVES_SENSOR_CAM,
139 		EXCLAVES_SENSOR_MIC,
140 		EXCLAVES_SENSOR_CAM_ALT_FACEID,
141 	};
142 	unsigned num_sensors = sizeof(sensors) / sizeof(sensors[0]);
143 	exclaves_sensor_status_t sensor_status = EXCLAVES_SENSOR_STATUS_DENIED;
144 	exclaves_sensor_type_t bad =
145 	    (exclaves_sensor_type_t) (unsigned) (EXCLAVES_SENSOR_MAX + 1);
146 	kern_return_t kr;
147 
148 	/* invalid sensor */
149 	kr = exclaves_sensor_stop(bad, 0, &sensor_status);
150 	SENSOR_TEST(kr == KERN_INVALID_ARGUMENT);
151 
152 	kr = exclaves_sensor_start(bad, 0, &sensor_status);
153 	SENSOR_TEST(kr == KERN_INVALID_ARGUMENT);
154 
155 	kr = exclaves_sensor_status(bad, 0, &sensor_status);
156 	SENSOR_TEST(kr == KERN_INVALID_ARGUMENT);
157 
158 	/* stop before start */
159 	for (unsigned i = 0; i < num_sensors; i++) {
160 		kr = exclaves_sensor_stop(sensors[i], 0, &sensor_status);
161 		SENSOR_TEST(kr == KERN_INVALID_ARGUMENT);
162 	}
163 
164 	/* start status is denied */
165 	for (unsigned i = 0; i < num_sensors; i++) {
166 		kr = exclaves_sensor_status(sensors[i], 0, &sensor_status);
167 		SENSOR_TEST(kr == KERN_SUCCESS);
168 		SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED); /* Not enforced */
169 	}
170 
171 	/* ALLOWED after at least 1 start */
172 	unsigned const n = 5;
173 	for (unsigned i = 0; i < num_sensors; i++) {
174 		for (unsigned j = 0; j < n; j++) {
175 			kr = exclaves_sensor_start(sensors[i], 0, &sensor_status);
176 			SENSOR_TEST(kr == KERN_SUCCESS);
177 			SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED);
178 			kr = exclaves_sensor_status(sensors[i], 0, &sensor_status);
179 			SENSOR_TEST(kr == KERN_SUCCESS);
180 			SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED);
181 		}
182 	}
183 
184 	/* ALLOWED after n-1 stops */
185 	for (unsigned i = 0; i < num_sensors; i++) {
186 		for (unsigned j = 0; j < n - 1; j++) {
187 			kr = exclaves_sensor_stop(sensors[i], 0, &sensor_status);
188 			SENSOR_TEST(kr == KERN_SUCCESS);
189 			SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED);
190 			kr = exclaves_sensor_status(sensors[i], 0, &sensor_status);
191 			SENSOR_TEST(kr == KERN_SUCCESS);
192 			SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED);
193 		}
194 	}
195 
196 	/* DENIED after final stop */
197 	for (unsigned i = 0; i < num_sensors; i++) {
198 		kr = exclaves_sensor_stop(sensors[i], 0, &sensor_status);
199 		SENSOR_TEST(kr == KERN_SUCCESS);
200 		SENSOR_TEST(sensor_status == EXCLAVES_SENSOR_STATUS_ALLOWED); /* Not enforced */
201 	}
202 
203 	/* exclaves_display_healthcheck_rate does something */
204 	kr = exclaves_display_healthcheck_rate(NSEC_PER_SEC / 60);
205 	SENSOR_TEST(kr == KERN_SUCCESS);
206 
207 #undef SENSOR_TEST
208 out:
209 	if (success) {
210 		exclaves_debug_printf(show_test_output,
211 		    "%s: SUCCESS\n", __func__);
212 		*out = 1;
213 	} else {
214 		exclaves_debug_printf(show_errors, "%s: FAILED\n", __func__);
215 		*out = 0;
216 	}
217 	return 0;
218 }
219 SYSCTL_TEST_REGISTER(exclaves_sensor_kpi_test,
220     exclaves_sensor_kpi_test);
221 
222 static int
exclaves_check_mem_usage_test(__unused int64_t in,int64_t * out)223 exclaves_check_mem_usage_test(__unused int64_t in, int64_t *out)
224 {
225 	if (exclaves_get_status() != EXCLAVES_STATUS_AVAILABLE) {
226 		exclaves_debug_printf(show_test_output,
227 		    "%s: SKIPPED: Exclaves not available\n", __func__);
228 		*out = -1;
229 		return 0;
230 	}
231 
232 	exclaves_debug_printf(show_test_output, "%s: STARTING\n", __func__);
233 
234 	kern_return_t r = exclaves_xnuproxy_pmm_usage();
235 	if (r == KERN_FAILURE) {
236 		exclaves_debug_printf(show_errors,
237 		    "Exclave Check Memory Usage failed: Kernel Failure\n");
238 		return 0;
239 	}
240 
241 	exclaves_debug_printf(show_test_output, "%s: SUCCESS\n", __func__);
242 	*out = 1;
243 
244 	return 0;
245 }
246 SYSCTL_TEST_REGISTER(exclaves_check_mem_usage_test, exclaves_check_mem_usage_test);
247 
248 
249 #endif /* DEVELOPMENT || DEBUG */
250 
251 #endif /* CONFIG_EXCLAVES */
252