1 /*
2 * Copyright (c) 2014 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 #include <pexpert/pexpert.h>
30 #include <sys/csr.h>
31 #include <sys/errno.h>
32 #include <sys/sysproto.h>
33 #include <sys/systm.h>
34 #include <sys/types.h>
35
36 #if CONFIG_CSR_FROM_DT
37
38 /*
39 * New style CSR for non-x86 platforms, using Per-OS Security Policy
40 * (POSP)
41 */
42
43 #include <libkern/section_keywords.h>
44 #include <pexpert/device_tree.h>
45
46 #if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR)
47 #include <arm64/amcc_rorgn.h>
48 #endif
49
50 static SECURITY_READ_ONLY_LATE(csr_config_t) csr_config = 0;
51
52 // WARNING: Used extremely early during boot. See csr_bootstrap().
53 static bool
_csr_get_dt_bool(DTEntry * entry,char const * name,bool * out)54 _csr_get_dt_bool(DTEntry *entry, char const *name, bool *out)
55 {
56 const uint32_t *value;
57 unsigned int size;
58
59 if (SecureDTGetProperty(*entry, name, (const void**)&value, &size) != kSuccess) {
60 return false;
61 }
62
63 if (size != sizeof(uint32_t)) {
64 panic("unexpected size %xu for bool property '%s'", size, name);
65 }
66
67 *out = (bool)*value;
68 return true;
69 }
70
71 // WARNING: Used extremely early during boot. See csr_bootstrap().
72 static bool
_csr_get_dt_uint64(DTEntry * entry,char const * name,uint64_t * out)73 _csr_get_dt_uint64(DTEntry *entry, char const *name, uint64_t *out)
74 {
75 const uint64_t *value;
76 unsigned int size;
77
78 if (SecureDTGetProperty(*entry, name, (const void**)&value, &size) != kSuccess) {
79 return false;
80 }
81
82 if (size != sizeof(uint64_t)) {
83 panic("unexpected size %xu for uint64 property '%s'", size, name);
84 }
85
86 *out = *value;
87 return true;
88 }
89
90 // WARNING: Used extremely early during boot. See csr_bootstrap().
91 static bool
_csr_dt_string_is_equal(DTEntry * entry,const char * name,const char * str)92 _csr_dt_string_is_equal(DTEntry *entry, const char *name, const char *str)
93 {
94 const void *value;
95 unsigned size;
96 size_t str_size;
97
98 str_size = strlen(str) + 1;
99 return entry != NULL &&
100 SecureDTGetProperty(*entry, name, &value, &size) == kSuccess &&
101 value != NULL &&
102 size == str_size &&
103 strncmp(str, value, str_size) == 0;
104 }
105
106 static bool
_csr_is_recovery_environment(void)107 _csr_is_recovery_environment(void)
108 {
109 DTEntry chosen;
110
111 return SecureDTLookupEntry(0, "/chosen", &chosen) == kSuccess &&
112 _csr_dt_string_is_equal(&chosen, "osenvironment", "recoveryos");
113 }
114
115 static bool
_csr_is_restore_environment(void)116 _csr_is_restore_environment(void)
117 {
118 int notused;
119
120 return PE_parse_boot_argn("-restore", ¬used, sizeof(notused));
121 }
122
123 static bool
_csr_is_iuou_or_iuos_device(void)124 _csr_is_iuou_or_iuos_device(void)
125 {
126 DTEntry entry;
127 bool bool_value;
128
129 return (SecureDTLookupEntry(0, "/chosen", &entry) == kSuccess &&
130 (_csr_get_dt_bool(&entry, "internal-use-only-unit", &bool_value) && bool_value)) ||
131 (SecureDTLookupEntry(0, "/chosen/manifest-properties", &entry) == kSuccess &&
132 (_csr_get_dt_bool(&entry, "iuos", &bool_value) && bool_value));
133 }
134
135 static bool
_csr_should_allow_device_configuration(void)136 _csr_should_allow_device_configuration(void)
137 {
138 /*
139 * Allow CSR_ALLOW_DEVICE_CONFIGURATION if the device is running in a
140 * restore environment, or if the "csr-allow-device-configuration"
141 * property is set in the device tree.
142 */
143 DTEntry chosen;
144 bool bool_value;
145
146 return _csr_is_recovery_environment() || (
147 SecureDTLookupEntry(0, "/chosen", &chosen) == kSuccess &&
148 _csr_get_dt_bool(&chosen, "csr-allow-device-configuration", &bool_value) && bool_value);
149 }
150
151 /*
152 * Initialize CSR from the Device Tree.
153 *
154 * WARNING: csr_bootstrap() is called extremely early in the kernel
155 * startup process in kernel_startup_bootstrap(), which happens
156 * before even the vm or pmap layer are initialized.
157 *
158 * It is marked as STARTUP_RANK_FIRST so that it is called before panic_init(),
159 * which runs during STARTUP_RANK_MIDDLE. This is necessary because panic_init()
160 * calls csr_check() to determine whether the device is configured to allow
161 * kernel debugging.
162 *
163 * Only do things here that don't require any dynamic memory (other
164 * than the stack). Parsing boot-args, walking the device tree and
165 * setting global variables is fine, most other things are not. Defer
166 * those other things with global variables, if necessary.
167 *
168 */
169 __startup_func
170 static void
csr_bootstrap(void)171 csr_bootstrap(void)
172 {
173 DTEntry entry;
174 uint64_t uint64_value;
175 bool config_active = false;
176 bool bool_value;
177
178 csr_config = 0; // start out fully restrictive
179
180 if (SecureDTLookupEntry(0, "/chosen/asmb", &entry) == kSuccess &&
181 _csr_get_dt_uint64(&entry, "lp-sip0", &uint64_value)) {
182 csr_config = (uint32_t)uint64_value; // Currently only 32 bits used.
183 config_active = true;
184 }
185
186 /*
187 * If the device is an Internal Use Only Unit (IUOU) or if it is running a
188 * build that is signed with the Internal Use Only Software (IUOS) tag, then
189 * allow the preservation of the CSR_ALLOW_APPLE_INTERNAL bit. Otherwise,
190 * forcefully remove the bit on boot.
191 */
192 if (!_csr_is_iuou_or_iuos_device()) {
193 csr_config &= ~CSR_ALLOW_APPLE_INTERNAL;
194 } else if (!config_active) {
195 // If there is no custom configuration present, infer the AppleInternal
196 // bit on IUOU or IUOS devices.
197 csr_config |= CSR_ALLOW_APPLE_INTERNAL;
198 }
199
200 // Unrestrict filesystem access in recovery and restore OS.
201 // This is required so the MSU stack can mount/unmount the update volume
202 // during paired recovery.
203 if (_csr_is_recovery_environment() ||
204 _csr_is_restore_environment()) {
205 csr_config |= CSR_ALLOW_UNRESTRICTED_FS;
206 }
207
208 if (_csr_should_allow_device_configuration()) {
209 csr_config |= CSR_ALLOW_DEVICE_CONFIGURATION;
210 }
211
212 // The CSR_ALLOW_UNAUTHENTICATED_ROOT flag must be synthesized from sip1
213 // in the local boot policy.
214 if (_csr_get_dt_bool(&entry, "lp-sip1", &bool_value) && bool_value) {
215 csr_config |= CSR_ALLOW_UNAUTHENTICATED_ROOT;
216 } else {
217 csr_config &= ~CSR_ALLOW_UNAUTHENTICATED_ROOT;
218 }
219
220 #if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR)
221 // Check whether we have to disable CTRR.
222 // lp-sip2 in the local boot policy is the bit driving this,
223 // which csrutil also sets implicitly when e.g. requesting kernel debugging.
224 csr_unsafe_kernel_text = _csr_get_dt_bool(&entry, "lp-sip2", &bool_value) && bool_value;
225 #endif
226 }
227 STARTUP(TUNABLES, STARTUP_RANK_FIRST, csr_bootstrap);
228
229 int
csr_get_active_config(csr_config_t * config)230 csr_get_active_config(csr_config_t * config)
231 {
232 *config = (csr_config & CSR_VALID_FLAGS);
233
234 return 0;
235 }
236
237 int
csr_check(csr_config_t mask)238 csr_check(csr_config_t mask)
239 {
240 csr_config_t config;
241 int ret = csr_get_active_config(&config);
242
243 if (ret != 0) {
244 return ret;
245 }
246
247 // CSR_ALLOW_KERNEL_DEBUGGER needs to be allowed when SIP is disabled
248 // to allow 3rd-party developers to debug their kexts. Use
249 // CSR_ALLOW_UNTRUSTED_KEXTS as a proxy for "SIP is disabled" on the
250 // grounds that you can do the same damage with a kernel debugger as
251 // you can with an untrusted kext.
252 if ((config & (CSR_ALLOW_UNTRUSTED_KEXTS | CSR_ALLOW_APPLE_INTERNAL)) != 0) {
253 config |= CSR_ALLOW_KERNEL_DEBUGGER;
254 }
255
256 return ((config & mask) == mask) ? 0 : EPERM;
257 }
258
259 #else
260
261 /*
262 * Old style CSR for x86 platforms, using NVRAM values
263 */
264
265 #include <libkern/section_keywords.h>
266
267 /* enable enforcement by default */
268 static SECURITY_READ_ONLY_LATE(int) csr_allow_all = 0;
269
270 /*
271 * Initialize csr_allow_all from device boot state.
272 *
273 * Needs to be run before panic_init() since panic_init()
274 * calls into csr_check() and runs during STARTUP_RANK_MIDDLE.
275 */
276 __startup_func
277 static void
csr_bootstrap(void)278 csr_bootstrap(void)
279 {
280 boot_args *args = (boot_args *)PE_state.bootArgs;
281 if (args->flags & kBootArgsFlagCSRBoot) {
282 /* special booter; allow everything */
283 csr_allow_all = 1;
284 }
285 }
286 STARTUP(TUNABLES, STARTUP_RANK_FIRST, csr_bootstrap);
287
288
289 int
csr_get_active_config(csr_config_t * config)290 csr_get_active_config(csr_config_t *config)
291 {
292 boot_args *args = (boot_args *)PE_state.bootArgs;
293 if (args->flags & kBootArgsFlagCSRActiveConfig) {
294 *config = args->csrActiveConfig & CSR_VALID_FLAGS;
295 } else {
296 *config = 0;
297 }
298
299 return 0;
300 }
301
302 int
csr_check(csr_config_t mask)303 csr_check(csr_config_t mask)
304 {
305 boot_args *args = (boot_args *)PE_state.bootArgs;
306 if (mask & CSR_ALLOW_DEVICE_CONFIGURATION) {
307 return (args->flags & kBootArgsFlagCSRConfigMode) ? 0 : EPERM;
308 }
309
310 csr_config_t config;
311 int ret = csr_get_active_config(&config);
312 if (ret) {
313 return ret;
314 }
315
316 // CSR_ALLOW_KERNEL_DEBUGGER needs to be allowed when SIP is disabled
317 // to allow 3rd-party developers to debug their kexts. Use
318 // CSR_ALLOW_UNTRUSTED_KEXTS as a proxy for "SIP is disabled" on the
319 // grounds that you can do the same damage with a kernel debugger as
320 // you can with an untrusted kext.
321 if ((config & (CSR_ALLOW_UNTRUSTED_KEXTS | CSR_ALLOW_APPLE_INTERNAL)) != 0) {
322 config |= CSR_ALLOW_KERNEL_DEBUGGER;
323 }
324
325 ret = ((config & mask) == mask) ? 0 : EPERM;
326 if (ret == EPERM) {
327 // Override the return value if booted from the BaseSystem and the mask does not contain any flag that should always be enforced.
328 if (csr_allow_all && (mask & CSR_ALWAYS_ENFORCED_FLAGS) == 0) {
329 ret = 0;
330 }
331 }
332
333 return ret;
334 }
335
336 #endif /* CONFIG_CSR_FROM_DT */
337
338 /*
339 * Syscall stubs
340 */
341
342 int syscall_csr_check(struct csrctl_args *args);
343 int syscall_csr_get_active_config(struct csrctl_args *args);
344
345
346 int
syscall_csr_check(struct csrctl_args * args)347 syscall_csr_check(struct csrctl_args *args)
348 {
349 csr_config_t mask = 0;
350 int error = 0;
351
352 if (args->useraddr == 0 || args->usersize != sizeof(mask)) {
353 return EINVAL;
354 }
355
356 error = copyin(args->useraddr, &mask, sizeof(mask));
357 if (error) {
358 return error;
359 }
360
361 return csr_check(mask);
362 }
363
364 int
syscall_csr_get_active_config(struct csrctl_args * args)365 syscall_csr_get_active_config(struct csrctl_args *args)
366 {
367 csr_config_t config = 0;
368 int error = 0;
369
370 if (args->useraddr == 0 || args->usersize != sizeof(config)) {
371 return EINVAL;
372 }
373
374 error = csr_get_active_config(&config);
375 if (error) {
376 return error;
377 }
378
379 return copyout(&config, args->useraddr, sizeof(config));
380 }
381
382 /*
383 * Syscall entrypoint
384 */
385
386 int
csrctl(__unused proc_t p,struct csrctl_args * args,__unused int32_t * retval)387 csrctl(__unused proc_t p, struct csrctl_args *args, __unused int32_t *retval)
388 {
389 switch (args->op) {
390 case CSR_SYSCALL_CHECK:
391 return syscall_csr_check(args);
392 case CSR_SYSCALL_GET_ACTIVE_CONFIG:
393 return syscall_csr_get_active_config(args);
394 default:
395 return ENOSYS;
396 }
397 }
398