2 * Copyright (c) 2014 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <pexpert/pexpert.h>
31 #include <sys/errno.h>
32 #include <sys/sysproto.h>
33 #include <sys/systm.h>
34 #include <sys/types.h>
36 #if CONFIG_CSR_FROM_DT
39 * New style CSR for non-x86 platforms, using Per-OS Security Policy
43 #include <libkern/section_keywords.h>
44 #include <pexpert/device_tree.h>
46 #if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR)
47 #include <arm64/amcc_rorgn.h>
50 static SECURITY_READ_ONLY_LATE(csr_config_t
) csr_config
= 0;
52 // WARNING: Used extremely early during boot. See csr_bootstrap().
54 _csr_get_dt_bool(DTEntry
*entry
, char const *name
, bool *out
)
56 const uint32_t *value
;
59 if (SecureDTGetProperty(*entry
, name
, (const void**)&value
, &size
) != kSuccess
) {
63 if (size
!= sizeof(uint32_t)) {
64 panic("unexpected size %xu for bool property '%s'", size
, name
);
71 // WARNING: Used extremely early during boot. See csr_bootstrap().
73 _csr_get_dt_uint64(DTEntry
*entry
, char const *name
, uint64_t *out
)
75 const uint64_t *value
;
78 if (SecureDTGetProperty(*entry
, name
, (const void**)&value
, &size
) != kSuccess
) {
82 if (size
!= sizeof(uint64_t)) {
83 panic("unexpected size %xu for uint64 property '%s'", size
, name
);
90 // WARNING: Used extremely early during boot. See csr_bootstrap().
92 _csr_dt_string_is_equal(DTEntry
*entry
, const char *name
, const char *str
)
98 str_size
= strlen(str
) + 1;
99 return entry
!= NULL
&&
100 SecureDTGetProperty(*entry
, name
, &value
, &size
) == kSuccess
&&
103 strncmp(str
, value
, str_size
) == 0;
107 _csr_is_recovery_environment(void)
111 return SecureDTLookupEntry(0, "/chosen", &chosen
) == kSuccess
&&
112 _csr_dt_string_is_equal(&chosen
, "osenvironment", "recoveryos");
116 _csr_is_iuou_or_iuos_device(void)
121 return (SecureDTLookupEntry(0, "/chosen", &entry
) == kSuccess
&&
122 (_csr_get_dt_bool(&entry
, "internal-use-only-unit", &bool_value
) && bool_value
)) ||
123 (SecureDTLookupEntry(0, "/chosen/manifest-properties", &entry
) == kSuccess
&&
124 (_csr_get_dt_bool(&entry
, "iuos", &bool_value
) && bool_value
));
128 _csr_should_allow_device_configuration(void)
131 * Allow CSR_ALLOW_DEVICE_CONFIGURATION if the device is running in a
132 * restore environment, or if the "csr-allow-device-configuration"
133 * property is set in the device tree.
138 return _csr_is_recovery_environment() || (
139 SecureDTLookupEntry(0, "/chosen", &chosen
) == kSuccess
&&
140 _csr_get_dt_bool(&chosen
, "csr-allow-device-configuration", &bool_value
) && bool_value
);
144 * Initialize CSR from the Device Tree.
146 * WARNING: csr_bootstrap() is called extremely early in the kernel
147 * startup process in kernel_startup_bootstrap(), which happens
148 * before even the vm or pmap layer are initialized.
150 * It is marked as STARTUP_RANK_FIRST so that it is called before panic_init(),
151 * which runs during STARTUP_RANK_MIDDLE. This is necessary because panic_init()
152 * calls csr_check() to determine whether the device is configured to allow
155 * Only do things here that don't require any dynamic memory (other
156 * than the stack). Parsing boot-args, walking the device tree and
157 * setting global variables is fine, most other things are not. Defer
158 * those other things with global variables, if necessary.
166 uint64_t uint64_value
;
167 bool config_active
= false;
170 csr_config
= 0; // start out fully restrictive
172 if (SecureDTLookupEntry(0, "/chosen/asmb", &entry
) == kSuccess
&&
173 _csr_get_dt_uint64(&entry
, "lp-sip0", &uint64_value
)) {
174 csr_config
= (uint32_t)uint64_value
; // Currently only 32 bits used.
175 config_active
= true;
179 * If the device is an Internal Use Only Unit (IUOU) or if it is running a
180 * build that is signed with the Internal Use Only Software (IUOS) tag, then
181 * allow the preservation of the CSR_ALLOW_APPLE_INTERNAL bit. Otherwise,
182 * forcefully remove the bit on boot.
184 if (!_csr_is_iuou_or_iuos_device()) {
185 csr_config
&= ~CSR_ALLOW_APPLE_INTERNAL
;
186 } else if (!config_active
) {
187 // If there is no custom configuration present, infer the AppleInternal
188 // bit on IUOU or IUOS devices.
189 csr_config
|= CSR_ALLOW_APPLE_INTERNAL
;
192 if (_csr_should_allow_device_configuration()) {
193 csr_config
|= CSR_ALLOW_DEVICE_CONFIGURATION
;
196 // The CSR_ALLOW_UNAUTHENTICATED_ROOT flag must be synthesized from sip1
197 // in the local boot policy.
198 if (_csr_get_dt_bool(&entry
, "lp-sip1", &bool_value
) && bool_value
) {
199 csr_config
|= CSR_ALLOW_UNAUTHENTICATED_ROOT
;
201 csr_config
&= ~CSR_ALLOW_UNAUTHENTICATED_ROOT
;
204 #if defined(KERNEL_INTEGRITY_KTRR) || defined(KERNEL_INTEGRITY_CTRR)
205 // Check whether we have to disable CTRR.
206 // lp-sip2 in the local boot policy is the bit driving this,
207 // which csrutil also sets implicitly when e.g. requesting kernel debugging.
208 csr_unsafe_kernel_text
= _csr_get_dt_bool(&entry
, "lp-sip2", &bool_value
) && bool_value
;
211 STARTUP(TUNABLES
, STARTUP_RANK_FIRST
, csr_bootstrap
);
214 csr_get_active_config(csr_config_t
* config
)
216 *config
= (csr_config
& CSR_VALID_FLAGS
);
222 csr_check(csr_config_t mask
)
225 int ret
= csr_get_active_config(&config
);
231 // CSR_ALLOW_KERNEL_DEBUGGER needs to be allowed when SIP is disabled
232 // to allow 3rd-party developers to debug their kexts. Use
233 // CSR_ALLOW_UNTRUSTED_KEXTS as a proxy for "SIP is disabled" on the
234 // grounds that you can do the same damage with a kernel debugger as
235 // you can with an untrusted kext.
236 if ((config
& (CSR_ALLOW_UNTRUSTED_KEXTS
| CSR_ALLOW_APPLE_INTERNAL
)) != 0) {
237 config
|= CSR_ALLOW_KERNEL_DEBUGGER
;
240 return ((config
& mask
) == mask
) ? 0 : EPERM
;
246 * Old style CSR for x86 platforms, using NVRAM values
249 #include <libkern/section_keywords.h>
251 /* enable enforcement by default */
252 static SECURITY_READ_ONLY_LATE(int) csr_allow_all
= 0;
255 * Initialize csr_allow_all from device boot state.
257 * Needs to be run before panic_init() since panic_init()
258 * calls into csr_check() and runs during STARTUP_RANK_MIDDLE.
264 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
265 if (args
->flags
& kBootArgsFlagCSRBoot
) {
266 /* special booter; allow everything */
270 STARTUP(TUNABLES
, STARTUP_RANK_FIRST
, csr_bootstrap
);
274 csr_get_active_config(csr_config_t
*config
)
276 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
277 if (args
->flags
& kBootArgsFlagCSRActiveConfig
) {
278 *config
= args
->csrActiveConfig
& CSR_VALID_FLAGS
;
287 csr_check(csr_config_t mask
)
289 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
290 if (mask
& CSR_ALLOW_DEVICE_CONFIGURATION
) {
291 return (args
->flags
& kBootArgsFlagCSRConfigMode
) ? 0 : EPERM
;
295 int ret
= csr_get_active_config(&config
);
300 // CSR_ALLOW_KERNEL_DEBUGGER needs to be allowed when SIP is disabled
301 // to allow 3rd-party developers to debug their kexts. Use
302 // CSR_ALLOW_UNTRUSTED_KEXTS as a proxy for "SIP is disabled" on the
303 // grounds that you can do the same damage with a kernel debugger as
304 // you can with an untrusted kext.
305 if ((config
& (CSR_ALLOW_UNTRUSTED_KEXTS
| CSR_ALLOW_APPLE_INTERNAL
)) != 0) {
306 config
|= CSR_ALLOW_KERNEL_DEBUGGER
;
309 ret
= ((config
& mask
) == mask
) ? 0 : EPERM
;
311 // Override the return value if booted from the BaseSystem and the mask does not contain any flag that should always be enforced.
312 if (csr_allow_all
&& (mask
& CSR_ALWAYS_ENFORCED_FLAGS
) == 0) {
320 #endif /* CONFIG_CSR_FROM_DT */
326 int syscall_csr_check(struct csrctl_args
*args
);
327 int syscall_csr_get_active_config(struct csrctl_args
*args
);
331 syscall_csr_check(struct csrctl_args
*args
)
333 csr_config_t mask
= 0;
336 if (args
->useraddr
== 0 || args
->usersize
!= sizeof(mask
)) {
340 error
= copyin(args
->useraddr
, &mask
, sizeof(mask
));
345 return csr_check(mask
);
349 syscall_csr_get_active_config(struct csrctl_args
*args
)
351 csr_config_t config
= 0;
354 if (args
->useraddr
== 0 || args
->usersize
!= sizeof(config
)) {
358 error
= csr_get_active_config(&config
);
363 return copyout(&config
, args
->useraddr
, sizeof(config
));
371 csrctl(__unused proc_t p
, struct csrctl_args
*args
, __unused
int32_t *retval
)
374 case CSR_SYSCALL_CHECK
:
375 return syscall_csr_check(args
);
376 case CSR_SYSCALL_GET_ACTIVE_CONFIG
:
377 return syscall_csr_get_active_config(args
);