xref: /xnu-11417.121.6/bsd/kern/code_signing/txm.c (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1*a1e26a70SApple OSS Distributions /*
2*a1e26a70SApple OSS Distributions  * Copyright (c) 2022 Apple Computer, Inc. All rights reserved.
3*a1e26a70SApple OSS Distributions  *
4*a1e26a70SApple OSS Distributions  * @APPLE_LICENSE_HEADER_START@
5*a1e26a70SApple OSS Distributions  *
6*a1e26a70SApple OSS Distributions  * The contents of this file constitute Original Code as defined in and
7*a1e26a70SApple OSS Distributions  * are subject to the Apple Public Source License Version 1.1 (the
8*a1e26a70SApple OSS Distributions  * "License").  You may not use this file except in compliance with the
9*a1e26a70SApple OSS Distributions  * License.  Please obtain a copy of the License at
10*a1e26a70SApple OSS Distributions  * http://www.apple.com/publicsource and read it before using this file.
11*a1e26a70SApple OSS Distributions  *
12*a1e26a70SApple OSS Distributions  * This Original Code and all software distributed under the License are
13*a1e26a70SApple OSS Distributions  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14*a1e26a70SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15*a1e26a70SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16*a1e26a70SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17*a1e26a70SApple OSS Distributions  * License for the specific language governing rights and limitations
18*a1e26a70SApple OSS Distributions  * under the License.
19*a1e26a70SApple OSS Distributions  *
20*a1e26a70SApple OSS Distributions  * @APPLE_LICENSE_HEADER_END@
21*a1e26a70SApple OSS Distributions  */
22*a1e26a70SApple OSS Distributions 
23*a1e26a70SApple OSS Distributions #include <stdarg.h>
24*a1e26a70SApple OSS Distributions #include <stdatomic.h>
25*a1e26a70SApple OSS Distributions #include <os/overflow.h>
26*a1e26a70SApple OSS Distributions #include <os/atomic_private.h>
27*a1e26a70SApple OSS Distributions #include <machine/atomic.h>
28*a1e26a70SApple OSS Distributions #include <mach/vm_param.h>
29*a1e26a70SApple OSS Distributions #include <mach/vm_map.h>
30*a1e26a70SApple OSS Distributions #include <mach/shared_region.h>
31*a1e26a70SApple OSS Distributions #include <vm/vm_kern_xnu.h>
32*a1e26a70SApple OSS Distributions #include <kern/zalloc.h>
33*a1e26a70SApple OSS Distributions #include <kern/kalloc.h>
34*a1e26a70SApple OSS Distributions #include <kern/assert.h>
35*a1e26a70SApple OSS Distributions #include <kern/locks.h>
36*a1e26a70SApple OSS Distributions #include <kern/recount.h>
37*a1e26a70SApple OSS Distributions #include <kern/sched_prim.h>
38*a1e26a70SApple OSS Distributions #include <kern/lock_rw.h>
39*a1e26a70SApple OSS Distributions #include <libkern/libkern.h>
40*a1e26a70SApple OSS Distributions #include <libkern/section_keywords.h>
41*a1e26a70SApple OSS Distributions #include <libkern/coretrust/coretrust.h>
42*a1e26a70SApple OSS Distributions #include <libkern/amfi/amfi.h>
43*a1e26a70SApple OSS Distributions #include <pexpert/pexpert.h>
44*a1e26a70SApple OSS Distributions #include <sys/vm.h>
45*a1e26a70SApple OSS Distributions #include <sys/proc.h>
46*a1e26a70SApple OSS Distributions #include <sys/codesign.h>
47*a1e26a70SApple OSS Distributions #include <sys/code_signing.h>
48*a1e26a70SApple OSS Distributions #include <sys/trust_caches.h>
49*a1e26a70SApple OSS Distributions #include <sys/sysctl.h>
50*a1e26a70SApple OSS Distributions #include <sys/reboot.h>
51*a1e26a70SApple OSS Distributions #include <uuid/uuid.h>
52*a1e26a70SApple OSS Distributions #include <IOKit/IOLib.h>
53*a1e26a70SApple OSS Distributions #include <IOKit/IOBSD.h>
54*a1e26a70SApple OSS Distributions 
55*a1e26a70SApple OSS Distributions #if CONFIG_SPTM
56*a1e26a70SApple OSS Distributions /*
57*a1e26a70SApple OSS Distributions  * The TrustedExecutionMonitor environment works in tandem with the SPTM to provide code
58*a1e26a70SApple OSS Distributions  * signing and memory isolation enforcement for data structures critical to ensuring that
59*a1e26a70SApple OSS Distributions  * all code executed on the system is authorized to do so.
60*a1e26a70SApple OSS Distributions  *
61*a1e26a70SApple OSS Distributions  * Unless the data is managed by TXM itself, XNU needs to page-align everything, make the
62*a1e26a70SApple OSS Distributions  * relevant type transfer, and then reference the memory as read-only.
63*a1e26a70SApple OSS Distributions  *
64*a1e26a70SApple OSS Distributions  * TXM enforces concurrency on its side, but through the use of try-locks. Upon a failure
65*a1e26a70SApple OSS Distributions  * in acquiring the lock, TXM will panic. As a result, in order to ensure single-threaded
66*a1e26a70SApple OSS Distributions  * behavior, the kernel also has to take some locks on its side befor calling into TXM.
67*a1e26a70SApple OSS Distributions  */
68*a1e26a70SApple OSS Distributions #include <sys/trusted_execution_monitor.h>
69*a1e26a70SApple OSS Distributions #include <pexpert/arm64/board_config.h>
70*a1e26a70SApple OSS Distributions 
71*a1e26a70SApple OSS Distributions /* Lock group used for all locks within the kernel for TXM */
72*a1e26a70SApple OSS Distributions LCK_GRP_DECLARE(txm_lck_grp, "txm_code_signing_lck_grp");
73*a1e26a70SApple OSS Distributions 
74*a1e26a70SApple OSS Distributions #pragma mark Utilities
75*a1e26a70SApple OSS Distributions 
76*a1e26a70SApple OSS Distributions /* Number of thread stacks is known at build-time */
77*a1e26a70SApple OSS Distributions #define NUM_TXM_THREAD_STACKS (MAX_CPUS)
78*a1e26a70SApple OSS Distributions txm_thread_stack_t thread_stacks[NUM_TXM_THREAD_STACKS] = {0};
79*a1e26a70SApple OSS Distributions 
80*a1e26a70SApple OSS Distributions /* Singly-linked-list head for thread stacks */
81*a1e26a70SApple OSS Distributions SLIST_HEAD(thread_stack_head, _txm_thread_stack) thread_stacks_head =
82*a1e26a70SApple OSS Distributions     SLIST_HEAD_INITIALIZER(thread_stacks_head);
83*a1e26a70SApple OSS Distributions 
84*a1e26a70SApple OSS Distributions static decl_lck_mtx_data(, thread_stacks_lock);
85*a1e26a70SApple OSS Distributions static void *thread_stack_event = NULL;
86*a1e26a70SApple OSS Distributions 
87*a1e26a70SApple OSS Distributions static void
setup_thread_stacks(void)88*a1e26a70SApple OSS Distributions setup_thread_stacks(void)
89*a1e26a70SApple OSS Distributions {
90*a1e26a70SApple OSS Distributions 	extern const sptm_bootstrap_args_xnu_t *SPTMArgs;
91*a1e26a70SApple OSS Distributions 	txm_thread_stack_t *thread_stack = NULL;
92*a1e26a70SApple OSS Distributions 
93*a1e26a70SApple OSS Distributions 	/* Initialize each thread stack and add it to the list */
94*a1e26a70SApple OSS Distributions 	for (uint32_t i = 0; i < NUM_TXM_THREAD_STACKS; i++) {
95*a1e26a70SApple OSS Distributions 		thread_stack = &thread_stacks[i];
96*a1e26a70SApple OSS Distributions 
97*a1e26a70SApple OSS Distributions 		/* Acquire the thread stack virtual mapping */
98*a1e26a70SApple OSS Distributions 		thread_stack->thread_stack_papt = SPTMArgs->txm_thread_stacks[i];
99*a1e26a70SApple OSS Distributions 
100*a1e26a70SApple OSS Distributions 		/* Acquire the thread stack physical page */
101*a1e26a70SApple OSS Distributions 		thread_stack->thread_stack_phys = (uintptr_t)kvtophys_nofail(
102*a1e26a70SApple OSS Distributions 			thread_stack->thread_stack_papt);
103*a1e26a70SApple OSS Distributions 
104*a1e26a70SApple OSS Distributions 		/* Resolve the pointer to the thread stack data */
105*a1e26a70SApple OSS Distributions 		thread_stack->thread_stack_data =
106*a1e26a70SApple OSS Distributions 		    (TXMThreadStack_t*)(thread_stack->thread_stack_papt + (PAGE_SIZE - 1024));
107*a1e26a70SApple OSS Distributions 
108*a1e26a70SApple OSS Distributions 		/* Add thread stack to the list head */
109*a1e26a70SApple OSS Distributions 		SLIST_INSERT_HEAD(&thread_stacks_head, thread_stack, link);
110*a1e26a70SApple OSS Distributions 	}
111*a1e26a70SApple OSS Distributions 
112*a1e26a70SApple OSS Distributions 	/* Initialize the thread stacks lock */
113*a1e26a70SApple OSS Distributions 	lck_mtx_init(&thread_stacks_lock, &txm_lck_grp, 0);
114*a1e26a70SApple OSS Distributions }
115*a1e26a70SApple OSS Distributions 
116*a1e26a70SApple OSS Distributions static txm_thread_stack_t*
acquire_thread_stack(void)117*a1e26a70SApple OSS Distributions acquire_thread_stack(void)
118*a1e26a70SApple OSS Distributions {
119*a1e26a70SApple OSS Distributions 	txm_thread_stack_t *thread_stack = NULL;
120*a1e26a70SApple OSS Distributions 
121*a1e26a70SApple OSS Distributions 	/* Lock the thread stack list */
122*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&thread_stacks_lock);
123*a1e26a70SApple OSS Distributions 
124*a1e26a70SApple OSS Distributions 	while (SLIST_EMPTY(&thread_stacks_head) == true) {
125*a1e26a70SApple OSS Distributions 		lck_mtx_sleep(
126*a1e26a70SApple OSS Distributions 			&thread_stacks_lock,
127*a1e26a70SApple OSS Distributions 			LCK_SLEEP_DEFAULT,
128*a1e26a70SApple OSS Distributions 			&thread_stack_event,
129*a1e26a70SApple OSS Distributions 			THREAD_UNINT);
130*a1e26a70SApple OSS Distributions 	}
131*a1e26a70SApple OSS Distributions 
132*a1e26a70SApple OSS Distributions 	if (SLIST_EMPTY(&thread_stacks_head) == true) {
133*a1e26a70SApple OSS Distributions 		panic("unable to acquire a thread stack for TXM");
134*a1e26a70SApple OSS Distributions 	}
135*a1e26a70SApple OSS Distributions 
136*a1e26a70SApple OSS Distributions 	/* Use the first available thread stack */
137*a1e26a70SApple OSS Distributions 	thread_stack = SLIST_FIRST(&thread_stacks_head);
138*a1e26a70SApple OSS Distributions 
139*a1e26a70SApple OSS Distributions 	/* Remove the thread stack from the list */
140*a1e26a70SApple OSS Distributions 	SLIST_REMOVE_HEAD(&thread_stacks_head, link);
141*a1e26a70SApple OSS Distributions 
142*a1e26a70SApple OSS Distributions 	/* Unlock the thread stack list */
143*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&thread_stacks_lock);
144*a1e26a70SApple OSS Distributions 
145*a1e26a70SApple OSS Distributions 	/* Associate the thread stack with the current thread */
146*a1e26a70SApple OSS Distributions 	thread_associate_txm_thread_stack(thread_stack->thread_stack_phys);
147*a1e26a70SApple OSS Distributions 
148*a1e26a70SApple OSS Distributions 	return thread_stack;
149*a1e26a70SApple OSS Distributions }
150*a1e26a70SApple OSS Distributions 
151*a1e26a70SApple OSS Distributions static void
release_thread_stack(txm_thread_stack_t * thread_stack)152*a1e26a70SApple OSS Distributions release_thread_stack(
153*a1e26a70SApple OSS Distributions 	txm_thread_stack_t* thread_stack)
154*a1e26a70SApple OSS Distributions {
155*a1e26a70SApple OSS Distributions 	/* Remove the TXM thread stack association with the current thread */
156*a1e26a70SApple OSS Distributions 	thread_disassociate_txm_thread_stack(thread_stack->thread_stack_phys);
157*a1e26a70SApple OSS Distributions 
158*a1e26a70SApple OSS Distributions 	/* Lock the thread stack list */
159*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&thread_stacks_lock);
160*a1e26a70SApple OSS Distributions 
161*a1e26a70SApple OSS Distributions 	/* Add the thread stack at the list head */
162*a1e26a70SApple OSS Distributions 	SLIST_INSERT_HEAD(&thread_stacks_head, thread_stack, link);
163*a1e26a70SApple OSS Distributions 
164*a1e26a70SApple OSS Distributions 	/* Unlock the thread stack list */
165*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&thread_stacks_lock);
166*a1e26a70SApple OSS Distributions 
167*a1e26a70SApple OSS Distributions 	/* Wake up any threads waiting to acquire a thread stack */
168*a1e26a70SApple OSS Distributions 	thread_wakeup(&thread_stack_event);
169*a1e26a70SApple OSS Distributions }
170*a1e26a70SApple OSS Distributions 
171*a1e26a70SApple OSS Distributions static kern_return_t
txm_parse_return(TXMReturn_t txm_ret)172*a1e26a70SApple OSS Distributions txm_parse_return(
173*a1e26a70SApple OSS Distributions 	TXMReturn_t txm_ret)
174*a1e26a70SApple OSS Distributions {
175*a1e26a70SApple OSS Distributions 	switch (txm_ret.returnCode) {
176*a1e26a70SApple OSS Distributions 	case kTXMSuccess:
177*a1e26a70SApple OSS Distributions 		return KERN_SUCCESS;
178*a1e26a70SApple OSS Distributions 
179*a1e26a70SApple OSS Distributions 	case kTXMReturnOutOfMemory:
180*a1e26a70SApple OSS Distributions 		return KERN_RESOURCE_SHORTAGE;
181*a1e26a70SApple OSS Distributions 
182*a1e26a70SApple OSS Distributions 	case kTXMReturnNotFound:
183*a1e26a70SApple OSS Distributions 		return KERN_NOT_FOUND;
184*a1e26a70SApple OSS Distributions 
185*a1e26a70SApple OSS Distributions 	case kTXMReturnNotSupported:
186*a1e26a70SApple OSS Distributions 		return KERN_NOT_SUPPORTED;
187*a1e26a70SApple OSS Distributions 
188*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 6
189*a1e26a70SApple OSS Distributions 	case kTXMReturnTryAgain:
190*a1e26a70SApple OSS Distributions 		return KERN_OPERATION_TIMED_OUT;
191*a1e26a70SApple OSS Distributions #endif
192*a1e26a70SApple OSS Distributions 
193*a1e26a70SApple OSS Distributions 	default:
194*a1e26a70SApple OSS Distributions 		return KERN_FAILURE;
195*a1e26a70SApple OSS Distributions 	}
196*a1e26a70SApple OSS Distributions }
197*a1e26a70SApple OSS Distributions 
198*a1e26a70SApple OSS Distributions static void
txm_print_return(TXMKernelSelector_t selector,TXMReturn_t txm_ret)199*a1e26a70SApple OSS Distributions txm_print_return(
200*a1e26a70SApple OSS Distributions 	TXMKernelSelector_t selector,
201*a1e26a70SApple OSS Distributions 	TXMReturn_t txm_ret)
202*a1e26a70SApple OSS Distributions {
203*a1e26a70SApple OSS Distributions 	/*
204*a1e26a70SApple OSS Distributions 	 * We specifically use IOLog instead of printf since printf is compiled out on
205*a1e26a70SApple OSS Distributions 	 * RELEASE kernels. We want to ensure that errors from TXM are captured within
206*a1e26a70SApple OSS Distributions 	 * sysdiagnoses from the field.
207*a1e26a70SApple OSS Distributions 	 */
208*a1e26a70SApple OSS Distributions 
209*a1e26a70SApple OSS Distributions 	if (txm_ret.returnCode == kTXMSuccess) {
210*a1e26a70SApple OSS Distributions 		return;
211*a1e26a70SApple OSS Distributions 	} else if (txm_ret.returnCode == kTXMReturnTrustCache) {
212*a1e26a70SApple OSS Distributions 		IOLog("TXM [Error]: TrustCache: selector: %u | 0x%02X | 0x%02X | %u\n",
213*a1e26a70SApple OSS Distributions 		    selector, txm_ret.tcRet.component, txm_ret.tcRet.error, txm_ret.tcRet.uniqueError);
214*a1e26a70SApple OSS Distributions 	} else if (txm_ret.returnCode == kTXMReturnCodeSignature) {
215*a1e26a70SApple OSS Distributions 		IOLog("TXM [Error]: CodeSignature: selector: %u | 0x%02X | 0x%02X | %u\n",
216*a1e26a70SApple OSS Distributions 		    selector, txm_ret.csRet.component, txm_ret.csRet.error, txm_ret.csRet.uniqueError);
217*a1e26a70SApple OSS Distributions 	} else if (txm_ret.returnCode == kTXMReturnCodeErrno) {
218*a1e26a70SApple OSS Distributions 		IOLog("TXM [Error]: Errno: selector: %u | %d\n",
219*a1e26a70SApple OSS Distributions 		    selector, txm_ret.errnoRet);
220*a1e26a70SApple OSS Distributions 	} else {
221*a1e26a70SApple OSS Distributions 		IOLog("TXM [Error]: selector: %u | %u\n",
222*a1e26a70SApple OSS Distributions 		    selector, txm_ret.returnCode);
223*a1e26a70SApple OSS Distributions 	}
224*a1e26a70SApple OSS Distributions }
225*a1e26a70SApple OSS Distributions 
226*a1e26a70SApple OSS Distributions #pragma mark Page Allocation
227*a1e26a70SApple OSS Distributions 
228*a1e26a70SApple OSS Distributions static void
txm_add_page(void)229*a1e26a70SApple OSS Distributions txm_add_page(void)
230*a1e26a70SApple OSS Distributions {
231*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
232*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAddFreeListPage,
233*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
234*a1e26a70SApple OSS Distributions 		.num_input_args = 1
235*a1e26a70SApple OSS Distributions 	};
236*a1e26a70SApple OSS Distributions 
237*a1e26a70SApple OSS Distributions 	/* Allocate a page from the VM -- transfers page to TXM internally */
238*a1e26a70SApple OSS Distributions 	vm_map_address_t phys_addr = pmap_txm_allocate_page();
239*a1e26a70SApple OSS Distributions 
240*a1e26a70SApple OSS Distributions 	/* Add this page to the TXM free list */
241*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, phys_addr);
242*a1e26a70SApple OSS Distributions }
243*a1e26a70SApple OSS Distributions 
244*a1e26a70SApple OSS Distributions #pragma mark Calls
245*a1e26a70SApple OSS Distributions 
246*a1e26a70SApple OSS Distributions static void
txm_kernel_call_registers_setup(txm_call_t * parameters,sptm_call_regs_t * registers,va_list args)247*a1e26a70SApple OSS Distributions txm_kernel_call_registers_setup(
248*a1e26a70SApple OSS Distributions 	txm_call_t *parameters,
249*a1e26a70SApple OSS Distributions 	sptm_call_regs_t *registers,
250*a1e26a70SApple OSS Distributions 	va_list args)
251*a1e26a70SApple OSS Distributions {
252*a1e26a70SApple OSS Distributions 	/*
253*a1e26a70SApple OSS Distributions 	 * We are only ever allowed a maximum of 7 arguments for calling into TXM.
254*a1e26a70SApple OSS Distributions 	 * This is because the SPTM dispatch only sets up registers x0-x7 for the
255*a1e26a70SApple OSS Distributions 	 * call, and x0 is always reserved for passing in a thread stack for TXM
256*a1e26a70SApple OSS Distributions 	 * to operate on.
257*a1e26a70SApple OSS Distributions 	 */
258*a1e26a70SApple OSS Distributions 
259*a1e26a70SApple OSS Distributions 	switch (parameters->num_input_args) {
260*a1e26a70SApple OSS Distributions 	case 7:
261*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
262*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
263*a1e26a70SApple OSS Distributions 		registers->x3 = va_arg(args, uintptr_t);
264*a1e26a70SApple OSS Distributions 		registers->x4 = va_arg(args, uintptr_t);
265*a1e26a70SApple OSS Distributions 		registers->x5 = va_arg(args, uintptr_t);
266*a1e26a70SApple OSS Distributions 		registers->x6 = va_arg(args, uintptr_t);
267*a1e26a70SApple OSS Distributions 		registers->x7 = va_arg(args, uintptr_t);
268*a1e26a70SApple OSS Distributions 		break;
269*a1e26a70SApple OSS Distributions 
270*a1e26a70SApple OSS Distributions 	case 6:
271*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
272*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
273*a1e26a70SApple OSS Distributions 		registers->x3 = va_arg(args, uintptr_t);
274*a1e26a70SApple OSS Distributions 		registers->x4 = va_arg(args, uintptr_t);
275*a1e26a70SApple OSS Distributions 		registers->x5 = va_arg(args, uintptr_t);
276*a1e26a70SApple OSS Distributions 		registers->x6 = va_arg(args, uintptr_t);
277*a1e26a70SApple OSS Distributions 		break;
278*a1e26a70SApple OSS Distributions 
279*a1e26a70SApple OSS Distributions 	case 5:
280*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
281*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
282*a1e26a70SApple OSS Distributions 		registers->x3 = va_arg(args, uintptr_t);
283*a1e26a70SApple OSS Distributions 		registers->x4 = va_arg(args, uintptr_t);
284*a1e26a70SApple OSS Distributions 		registers->x5 = va_arg(args, uintptr_t);
285*a1e26a70SApple OSS Distributions 		break;
286*a1e26a70SApple OSS Distributions 
287*a1e26a70SApple OSS Distributions 	case 4:
288*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
289*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
290*a1e26a70SApple OSS Distributions 		registers->x3 = va_arg(args, uintptr_t);
291*a1e26a70SApple OSS Distributions 		registers->x4 = va_arg(args, uintptr_t);
292*a1e26a70SApple OSS Distributions 		break;
293*a1e26a70SApple OSS Distributions 
294*a1e26a70SApple OSS Distributions 	case 3:
295*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
296*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
297*a1e26a70SApple OSS Distributions 		registers->x3 = va_arg(args, uintptr_t);
298*a1e26a70SApple OSS Distributions 		break;
299*a1e26a70SApple OSS Distributions 
300*a1e26a70SApple OSS Distributions 	case 2:
301*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
302*a1e26a70SApple OSS Distributions 		registers->x2 = va_arg(args, uintptr_t);
303*a1e26a70SApple OSS Distributions 		break;
304*a1e26a70SApple OSS Distributions 
305*a1e26a70SApple OSS Distributions 	case 1:
306*a1e26a70SApple OSS Distributions 		registers->x1 = va_arg(args, uintptr_t);
307*a1e26a70SApple OSS Distributions 		break;
308*a1e26a70SApple OSS Distributions 
309*a1e26a70SApple OSS Distributions 	case 0:
310*a1e26a70SApple OSS Distributions 		break;
311*a1e26a70SApple OSS Distributions 
312*a1e26a70SApple OSS Distributions 	default:
313*a1e26a70SApple OSS Distributions 		panic("invalid number of arguments to TXM: selector: %u | %u",
314*a1e26a70SApple OSS Distributions 		    parameters->selector, parameters->num_input_args);
315*a1e26a70SApple OSS Distributions 	}
316*a1e26a70SApple OSS Distributions }
317*a1e26a70SApple OSS Distributions 
318*a1e26a70SApple OSS Distributions static TXMReturn_t
txm_kernel_call_internal(txm_call_t * parameters,va_list args)319*a1e26a70SApple OSS Distributions txm_kernel_call_internal(
320*a1e26a70SApple OSS Distributions 	txm_call_t *parameters,
321*a1e26a70SApple OSS Distributions 	va_list args)
322*a1e26a70SApple OSS Distributions {
323*a1e26a70SApple OSS Distributions 	TXMReturn_t txm_ret = (TXMReturn_t){.returnCode = kTXMReturnGeneric};
324*a1e26a70SApple OSS Distributions 	sptm_call_regs_t txm_registers = {0};
325*a1e26a70SApple OSS Distributions 	txm_thread_stack_t *thread_stack = NULL;
326*a1e26a70SApple OSS Distributions 	const TXMThreadStack_t *thread_stack_data = NULL;
327*a1e26a70SApple OSS Distributions 	const TXMSharedContextData_t *shared_context_data = NULL;
328*a1e26a70SApple OSS Distributions 
329*a1e26a70SApple OSS Distributions 	/* Obtain a stack for this call */
330*a1e26a70SApple OSS Distributions 	thread_stack = acquire_thread_stack();
331*a1e26a70SApple OSS Distributions 	thread_stack_data = thread_stack->thread_stack_data;
332*a1e26a70SApple OSS Distributions 	shared_context_data = &thread_stack_data->sharedData;
333*a1e26a70SApple OSS Distributions 
334*a1e26a70SApple OSS Distributions 	/* Setup argument registers */
335*a1e26a70SApple OSS Distributions 	txm_registers.x0 = thread_stack->thread_stack_phys;
336*a1e26a70SApple OSS Distributions 	txm_kernel_call_registers_setup(parameters, &txm_registers, args);
337*a1e26a70SApple OSS Distributions 
338*a1e26a70SApple OSS Distributions 	/* Track resource usage */
339*a1e26a70SApple OSS Distributions 	recount_enter_secure();
340*a1e26a70SApple OSS Distributions 
341*a1e26a70SApple OSS Distributions 	/* Call into TXM */
342*a1e26a70SApple OSS Distributions 	txm_enter(parameters->selector, &txm_registers);
343*a1e26a70SApple OSS Distributions 
344*a1e26a70SApple OSS Distributions 	recount_leave_secure();
345*a1e26a70SApple OSS Distributions 
346*a1e26a70SApple OSS Distributions 	txm_ret = (TXMReturn_t){.rawValue = shared_context_data->txmReturnCode};
347*a1e26a70SApple OSS Distributions 	parameters->txm_ret = txm_ret;
348*a1e26a70SApple OSS Distributions 
349*a1e26a70SApple OSS Distributions 	if (parameters->txm_ret.returnCode == kTXMSuccess) {
350*a1e26a70SApple OSS Distributions 		parameters->num_return_words = shared_context_data->txmNumReturnWords;
351*a1e26a70SApple OSS Distributions 		if (parameters->num_return_words > kTXMStackReturnWords) {
352*a1e26a70SApple OSS Distributions 			panic("received excessive return words from TXM: selector: %u | %llu",
353*a1e26a70SApple OSS Distributions 			    parameters->selector, parameters->num_return_words);
354*a1e26a70SApple OSS Distributions 		}
355*a1e26a70SApple OSS Distributions 
356*a1e26a70SApple OSS Distributions 		for (uint64_t i = 0; i < parameters->num_return_words; i++) {
357*a1e26a70SApple OSS Distributions 			parameters->return_words[i] = shared_context_data->txmReturnWords[i];
358*a1e26a70SApple OSS Distributions 		}
359*a1e26a70SApple OSS Distributions 	}
360*a1e26a70SApple OSS Distributions 
361*a1e26a70SApple OSS Distributions 	/* Release the thread stack as it is no longer needed */
362*a1e26a70SApple OSS Distributions 	release_thread_stack(thread_stack);
363*a1e26a70SApple OSS Distributions 	thread_stack_data = NULL;
364*a1e26a70SApple OSS Distributions 	shared_context_data = NULL;
365*a1e26a70SApple OSS Distributions 
366*a1e26a70SApple OSS Distributions 	return txm_ret;
367*a1e26a70SApple OSS Distributions }
368*a1e26a70SApple OSS Distributions 
369*a1e26a70SApple OSS Distributions kern_return_t
txm_kernel_call(txm_call_t * parameters,...)370*a1e26a70SApple OSS Distributions txm_kernel_call(
371*a1e26a70SApple OSS Distributions 	txm_call_t *parameters, ...)
372*a1e26a70SApple OSS Distributions {
373*a1e26a70SApple OSS Distributions 	TXMReturn_t txm_ret = (TXMReturn_t){.returnCode = kTXMReturnGeneric};
374*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
375*a1e26a70SApple OSS Distributions 	va_list args;
376*a1e26a70SApple OSS Distributions 
377*a1e26a70SApple OSS Distributions 	/* Start the variadic arguments list */
378*a1e26a70SApple OSS Distributions 	va_start(args, parameters);
379*a1e26a70SApple OSS Distributions 
380*a1e26a70SApple OSS Distributions 	do {
381*a1e26a70SApple OSS Distributions 		txm_ret = txm_kernel_call_internal(parameters, args);
382*a1e26a70SApple OSS Distributions 		if (txm_ret.returnCode == kTXMReturnOutOfMemory) {
383*a1e26a70SApple OSS Distributions 			if (parameters->selector == kTXMKernelSelectorAddFreeListPage) {
384*a1e26a70SApple OSS Distributions 				panic("received out-of-memory error when adding a free page to TXM");
385*a1e26a70SApple OSS Distributions 			}
386*a1e26a70SApple OSS Distributions 			txm_add_page();
387*a1e26a70SApple OSS Distributions 		}
388*a1e26a70SApple OSS Distributions 	} while (txm_ret.returnCode == kTXMReturnOutOfMemory);
389*a1e26a70SApple OSS Distributions 
390*a1e26a70SApple OSS Distributions 	/* Clean up the variadic arguments list */
391*a1e26a70SApple OSS Distributions 	va_end(args);
392*a1e26a70SApple OSS Distributions 
393*a1e26a70SApple OSS Distributions 	/* Print all TXM logs from the log buffer */
394*a1e26a70SApple OSS Distributions 	if (parameters->skip_logs == false) {
395*a1e26a70SApple OSS Distributions 		txm_print_logs();
396*a1e26a70SApple OSS Distributions 	}
397*a1e26a70SApple OSS Distributions 
398*a1e26a70SApple OSS Distributions 	/* Print the return code from TXM -- only prints for an error */
399*a1e26a70SApple OSS Distributions 	if (parameters->failure_silent != true) {
400*a1e26a70SApple OSS Distributions 		if (parameters->failure_code_silent != txm_ret.returnCode) {
401*a1e26a70SApple OSS Distributions 			txm_print_return(parameters->selector, txm_ret);
402*a1e26a70SApple OSS Distributions 		}
403*a1e26a70SApple OSS Distributions 	}
404*a1e26a70SApple OSS Distributions 
405*a1e26a70SApple OSS Distributions 	/*
406*a1e26a70SApple OSS Distributions 	 * To ease the process of calling into TXM, and to also reduce the number of
407*a1e26a70SApple OSS Distributions 	 * lines of code for each call site, the txm_call_t offers some properties
408*a1e26a70SApple OSS Distributions 	 * we can enforce over here. Go through these, and panic in case they aren't
409*a1e26a70SApple OSS Distributions 	 * honored.
410*a1e26a70SApple OSS Distributions 	 *
411*a1e26a70SApple OSS Distributions 	 * NOTE: We check for "<" instead of "!=" for the number of return words we
412*a1e26a70SApple OSS Distributions 	 * get back from TXM since this helps in forward development. If the kernel
413*a1e26a70SApple OSS Distributions 	 * and TXM are proceeding at different project cadences, we do not want to
414*a1e26a70SApple OSS Distributions 	 * gate adding more return words from TXM on the kernel first adopting the
415*a1e26a70SApple OSS Distributions 	 * new number of return words.
416*a1e26a70SApple OSS Distributions 	 */
417*a1e26a70SApple OSS Distributions 	ret = txm_parse_return(txm_ret);
418*a1e26a70SApple OSS Distributions 
419*a1e26a70SApple OSS Distributions 	if (parameters->failure_fatal && (ret != KERN_SUCCESS)) {
420*a1e26a70SApple OSS Distributions 		panic("received fatal error for a selector from TXM: selector: %u | 0x%0llX",
421*a1e26a70SApple OSS Distributions 		    parameters->selector, txm_ret.rawValue);
422*a1e26a70SApple OSS Distributions 	} else if (parameters->num_return_words < parameters->num_output_args) {
423*a1e26a70SApple OSS Distributions 		/* Only panic if return was a success */
424*a1e26a70SApple OSS Distributions 		if (ret == KERN_SUCCESS) {
425*a1e26a70SApple OSS Distributions 			panic("received fewer than expected return words from TXM: selector: %u | %llu",
426*a1e26a70SApple OSS Distributions 			    parameters->selector, parameters->num_return_words);
427*a1e26a70SApple OSS Distributions 		}
428*a1e26a70SApple OSS Distributions 	}
429*a1e26a70SApple OSS Distributions 
430*a1e26a70SApple OSS Distributions 	return ret;
431*a1e26a70SApple OSS Distributions }
432*a1e26a70SApple OSS Distributions 
433*a1e26a70SApple OSS Distributions void
txm_transfer_region(vm_address_t addr,vm_size_t size)434*a1e26a70SApple OSS Distributions txm_transfer_region(
435*a1e26a70SApple OSS Distributions 	vm_address_t addr,
436*a1e26a70SApple OSS Distributions 	vm_size_t size)
437*a1e26a70SApple OSS Distributions {
438*a1e26a70SApple OSS Distributions 	vm_address_t addr_end = 0;
439*a1e26a70SApple OSS Distributions 	vm_size_t size_aligned = round_page(size);
440*a1e26a70SApple OSS Distributions 
441*a1e26a70SApple OSS Distributions 	if ((addr & PAGE_MASK) != 0) {
442*a1e26a70SApple OSS Distributions 		panic("attempted to transfer non-page-aligned memory to TXM: %p", (void*)addr);
443*a1e26a70SApple OSS Distributions 	} else if (os_add_overflow(addr, size_aligned, &addr_end)) {
444*a1e26a70SApple OSS Distributions 		panic("overflow on range to be transferred to TXM: %p | %lu",
445*a1e26a70SApple OSS Distributions 		    (void*)addr, size);
446*a1e26a70SApple OSS Distributions 	}
447*a1e26a70SApple OSS Distributions 
448*a1e26a70SApple OSS Distributions 	/* Make the memory read-only first (transfer will panic otherwise) */
449*a1e26a70SApple OSS Distributions 	vm_protect(kernel_map, addr, size_aligned, false, VM_PROT_READ);
450*a1e26a70SApple OSS Distributions 
451*a1e26a70SApple OSS Distributions 	/* Transfer each physical page to be TXM_DEFAULT */
452*a1e26a70SApple OSS Distributions 	for (vm_address_t page = addr; page < addr_end; page += PAGE_SIZE) {
453*a1e26a70SApple OSS Distributions 		pmap_txm_transfer_page(page);
454*a1e26a70SApple OSS Distributions 	}
455*a1e26a70SApple OSS Distributions }
456*a1e26a70SApple OSS Distributions 
457*a1e26a70SApple OSS Distributions void
txm_reclaim_region(vm_address_t addr,vm_size_t size)458*a1e26a70SApple OSS Distributions txm_reclaim_region(
459*a1e26a70SApple OSS Distributions 	vm_address_t addr,
460*a1e26a70SApple OSS Distributions 	vm_size_t size)
461*a1e26a70SApple OSS Distributions {
462*a1e26a70SApple OSS Distributions 	vm_address_t addr_end = 0;
463*a1e26a70SApple OSS Distributions 	vm_size_t size_aligned = round_page(size);
464*a1e26a70SApple OSS Distributions 
465*a1e26a70SApple OSS Distributions 	if ((addr & PAGE_MASK) != 0) {
466*a1e26a70SApple OSS Distributions 		panic("attempted to reclaim non-page-aligned memory from TXM: %p", (void*)addr);
467*a1e26a70SApple OSS Distributions 	} else if (os_add_overflow(addr, size_aligned, &addr_end)) {
468*a1e26a70SApple OSS Distributions 		panic("overflow on range to be reclaimed from TXM: %p | %lu",
469*a1e26a70SApple OSS Distributions 		    (void*)addr, size);
470*a1e26a70SApple OSS Distributions 	}
471*a1e26a70SApple OSS Distributions 
472*a1e26a70SApple OSS Distributions 	/*
473*a1e26a70SApple OSS Distributions 	 * We can only reclaim once TXM has transferred the memory range back to the
474*a1e26a70SApple OSS Distributions 	 * kernel. Hence, we simply try and switch permissions to read-write. If TXM
475*a1e26a70SApple OSS Distributions 	 * hasn't transferred pages, this then should panic.
476*a1e26a70SApple OSS Distributions 	 */
477*a1e26a70SApple OSS Distributions 	vm_protect(kernel_map, addr, size_aligned, false, VM_PROT_READ | VM_PROT_WRITE);
478*a1e26a70SApple OSS Distributions }
479*a1e26a70SApple OSS Distributions 
480*a1e26a70SApple OSS Distributions static SECURITY_READ_ONLY_LATE(const char*) txm_log_page = NULL;
481*a1e26a70SApple OSS Distributions static SECURITY_READ_ONLY_LATE(const uint32_t*) txm_log_head = NULL;
482*a1e26a70SApple OSS Distributions static SECURITY_READ_ONLY_LATE(const uint32_t*) txm_log_sync = NULL;
483*a1e26a70SApple OSS Distributions 
484*a1e26a70SApple OSS Distributions static decl_lck_mtx_data(, log_lock);
485*a1e26a70SApple OSS Distributions static uint32_t log_head = 0;
486*a1e26a70SApple OSS Distributions 
487*a1e26a70SApple OSS Distributions void
txm_print_logs(void)488*a1e26a70SApple OSS Distributions txm_print_logs(void)
489*a1e26a70SApple OSS Distributions {
490*a1e26a70SApple OSS Distributions 	uint32_t start_index = 0;
491*a1e26a70SApple OSS Distributions 	uint32_t end_index = 0;
492*a1e26a70SApple OSS Distributions 
493*a1e26a70SApple OSS Distributions 	/*
494*a1e26a70SApple OSS Distributions 	 * The design here is very simple. TXM keeps adding slots to its circular buffer
495*a1e26a70SApple OSS Distributions 	 * and the kernel attempts to read each one and print it, maintaining its own head
496*a1e26a70SApple OSS Distributions 	 * for the log.
497*a1e26a70SApple OSS Distributions 	 *
498*a1e26a70SApple OSS Distributions 	 * This design is by nature lazy. TXM doesn't know or care if the kernel has gone
499*a1e26a70SApple OSS Distributions 	 * through and printed any of the logs, so it'll just keep writing into its buffer
500*a1e26a70SApple OSS Distributions 	 * and then circle around when it becomes full.
501*a1e26a70SApple OSS Distributions 	 *
502*a1e26a70SApple OSS Distributions 	 * This is fine most of the time since there are a decent amount of slots in the
503*a1e26a70SApple OSS Distributions 	 * log buffer. We mostly have an issue when TXM is adding so many logs so quickly
504*a1e26a70SApple OSS Distributions 	 * such that it wraps around and starts overwriting logs which haven't been seen
505*a1e26a70SApple OSS Distributions 	 * by the kernel. If this were to happen, TXM's log head may circle around the
506*a1e26a70SApple OSS Distributions 	 * head maintained by the kernel, causing a lot of logs to be missed, since the
507*a1e26a70SApple OSS Distributions 	 * kernel only attempts the number of logs in-between the two heads.
508*a1e26a70SApple OSS Distributions 	 *
509*a1e26a70SApple OSS Distributions 	 * The fix for that is complicated, and until we see an actual impact, we're going
510*a1e26a70SApple OSS Distributions 	 * to keep the simpler design in place.
511*a1e26a70SApple OSS Distributions 	 */
512*a1e26a70SApple OSS Distributions 
513*a1e26a70SApple OSS Distributions 	/* Return if the logging hasn't been setup yet */
514*a1e26a70SApple OSS Distributions 	if (txm_log_sync == NULL) {
515*a1e26a70SApple OSS Distributions 		return;
516*a1e26a70SApple OSS Distributions 	}
517*a1e26a70SApple OSS Distributions 
518*a1e26a70SApple OSS Distributions 	/*
519*a1e26a70SApple OSS Distributions 	 * Holding the log lock and printing can cause lots of issues since printing can
520*a1e26a70SApple OSS Distributions 	 * be rather slow. While we make it a point to keep the logging buffer quiet, some
521*a1e26a70SApple OSS Distributions 	 * actions (such as loading trust caches) are still very chatty.
522*a1e26a70SApple OSS Distributions 	 *
523*a1e26a70SApple OSS Distributions 	 * As a result, we optimize this routine to ensure that the lock itself isn't held
524*a1e26a70SApple OSS Distributions 	 * for very long. All we need to do within the critical section is calculate the
525*a1e26a70SApple OSS Distributions 	 * starting and ending index of the log buffer. The actual printing doesn't need
526*a1e26a70SApple OSS Distributions 	 * to be done with the lock held.
527*a1e26a70SApple OSS Distributions 	 */
528*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&log_lock);
529*a1e26a70SApple OSS Distributions 
530*a1e26a70SApple OSS Distributions 	start_index = log_head;
531*a1e26a70SApple OSS Distributions 	end_index = os_atomic_load(txm_log_head, relaxed) % kTXMLogSlots;
532*a1e26a70SApple OSS Distributions 
533*a1e26a70SApple OSS Distributions 	/* Update the log head with the new index */
534*a1e26a70SApple OSS Distributions 	log_head = end_index;
535*a1e26a70SApple OSS Distributions 
536*a1e26a70SApple OSS Distributions 	/* Release the log lock */
537*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&log_lock);
538*a1e26a70SApple OSS Distributions 
539*a1e26a70SApple OSS Distributions 	if (start_index != end_index) {
540*a1e26a70SApple OSS Distributions 		/* Use load acquire here to sync up with all writes to the buffer */
541*a1e26a70SApple OSS Distributions 		os_atomic_load(txm_log_sync, acquire);
542*a1e26a70SApple OSS Distributions 
543*a1e26a70SApple OSS Distributions 		while (start_index != end_index) {
544*a1e26a70SApple OSS Distributions 			const char *slot = txm_log_page + (start_index * kTXMLogSlotSize);
545*a1e26a70SApple OSS Distributions 
546*a1e26a70SApple OSS Distributions 			/* We add newlines after each log statement since TXM does not */
547*a1e26a70SApple OSS Distributions 			printf("%s\n", slot);
548*a1e26a70SApple OSS Distributions 
549*a1e26a70SApple OSS Distributions 			start_index = (start_index + 1) % kTXMLogSlots;
550*a1e26a70SApple OSS Distributions 		}
551*a1e26a70SApple OSS Distributions 	}
552*a1e26a70SApple OSS Distributions }
553*a1e26a70SApple OSS Distributions 
554*a1e26a70SApple OSS Distributions #pragma mark Initialization
555*a1e26a70SApple OSS Distributions 
556*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(const TXMReadWriteData_t*) txm_rw_data = NULL;
557*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(const TXMReadOnlyData_t*) txm_ro_data = NULL;
558*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(const CSConfig_t*) txm_cs_config = NULL;
559*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(CSRestrictedModeState_t*) txm_restricted_mode_state = NULL;
560*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(const TXMMetrics_t*) txm_metrics = NULL;
561*a1e26a70SApple OSS Distributions 
562*a1e26a70SApple OSS Distributions SECURITY_READ_ONLY_LATE(bool*) developer_mode_enabled = NULL;
563*a1e26a70SApple OSS Distributions static SECURITY_READ_ONLY_LATE(bool) code_signing_enabled = true;
564*a1e26a70SApple OSS Distributions static SECURITY_READ_ONLY_LATE(uint32_t) managed_signature_size = 0;
565*a1e26a70SApple OSS Distributions 
566*a1e26a70SApple OSS Distributions static decl_lck_mtx_data(, compilation_service_lock);
567*a1e26a70SApple OSS Distributions static decl_lck_mtx_data(, unregister_sync_lock);
568*a1e26a70SApple OSS Distributions 
569*a1e26a70SApple OSS Distributions static void
get_logging_info(void)570*a1e26a70SApple OSS Distributions get_logging_info(void)
571*a1e26a70SApple OSS Distributions {
572*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
573*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorGetLogInfo,
574*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
575*a1e26a70SApple OSS Distributions 		.num_output_args = 3
576*a1e26a70SApple OSS Distributions 	};
577*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call);
578*a1e26a70SApple OSS Distributions 
579*a1e26a70SApple OSS Distributions 	txm_log_page = (const char*)txm_call.return_words[0];
580*a1e26a70SApple OSS Distributions 	txm_log_head = (const uint32_t*)txm_call.return_words[1];
581*a1e26a70SApple OSS Distributions 	txm_log_sync = (const uint32_t*)txm_call.return_words[2];
582*a1e26a70SApple OSS Distributions }
583*a1e26a70SApple OSS Distributions 
584*a1e26a70SApple OSS Distributions static void
get_code_signing_info(void)585*a1e26a70SApple OSS Distributions get_code_signing_info(void)
586*a1e26a70SApple OSS Distributions {
587*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
588*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorGetCodeSigningInfo,
589*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
590*a1e26a70SApple OSS Distributions 		.num_output_args = 6
591*a1e26a70SApple OSS Distributions 	};
592*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call);
593*a1e26a70SApple OSS Distributions 
594*a1e26a70SApple OSS Distributions 	/*
595*a1e26a70SApple OSS Distributions 	 * Not using txm_call.return_words[0] for now. This was previously the
596*a1e26a70SApple OSS Distributions 	 * code_signing_enabled field, but we've since switched to acquiring that
597*a1e26a70SApple OSS Distributions 	 * value from TXM's read-only data.
598*a1e26a70SApple OSS Distributions 	 *
599*a1e26a70SApple OSS Distributions 	 * Not using txm_call.return_words[2] for now. This was previously the
600*a1e26a70SApple OSS Distributions 	 * metrics field, but we've since switched to acquiring that value from
601*a1e26a70SApple OSS Distributions 	 * TXM's read-write data.
602*a1e26a70SApple OSS Distributions 	 *
603*a1e26a70SApple OSS Distributions 	 * Not using txm_call.return_words[4] for now. This was previously the
604*a1e26a70SApple OSS Distributions 	 * txm_cs_config field, but we've since switched to acquiring that value
605*a1e26a70SApple OSS Distributions 	 * from TXM's read-only data.
606*a1e26a70SApple OSS Distributions 	 */
607*a1e26a70SApple OSS Distributions 	txm_rw_data = (TXMReadWriteData_t*)txm_call.return_words[0];
608*a1e26a70SApple OSS Distributions 	developer_mode_enabled = (bool*)txm_call.return_words[1];
609*a1e26a70SApple OSS Distributions 	managed_signature_size = (uint32_t)txm_call.return_words[3];
610*a1e26a70SApple OSS Distributions 	txm_ro_data = (TXMReadOnlyData_t*)txm_call.return_words[5];
611*a1e26a70SApple OSS Distributions 	txm_metrics = &txm_rw_data->metrics;
612*a1e26a70SApple OSS Distributions 
613*a1e26a70SApple OSS Distributions 	/* Set code_signing_disabled based on read-only data */
614*a1e26a70SApple OSS Distributions 	code_signing_enabled = txm_ro_data->codeSigningDisabled == false;
615*a1e26a70SApple OSS Distributions 
616*a1e26a70SApple OSS Distributions 	/* Set txm_cs_config based on read-only data */
617*a1e26a70SApple OSS Distributions 	txm_cs_config = &txm_ro_data->CSConfiguration;
618*a1e26a70SApple OSS Distributions 
619*a1e26a70SApple OSS Distributions 	/* Only setup when REM is supported on the platform */
620*a1e26a70SApple OSS Distributions 	if (txm_cs_config->systemPolicy->featureSet.restrictedExecutionMode == true) {
621*a1e26a70SApple OSS Distributions 		txm_restricted_mode_state = txm_ro_data->restrictedModeState;
622*a1e26a70SApple OSS Distributions 	}
623*a1e26a70SApple OSS Distributions 
624*a1e26a70SApple OSS Distributions 	/* Setup the number of boot trust caches */
625*a1e26a70SApple OSS Distributions 	num_static_trust_caches = os_atomic_load(&txm_metrics->trustCaches.numStatic, relaxed);
626*a1e26a70SApple OSS Distributions 	num_engineering_trust_caches = os_atomic_load(&txm_metrics->trustCaches.numEngineering, relaxed);
627*a1e26a70SApple OSS Distributions }
628*a1e26a70SApple OSS Distributions 
629*a1e26a70SApple OSS Distributions static void
set_shared_region_base_address(void)630*a1e26a70SApple OSS Distributions set_shared_region_base_address(void)
631*a1e26a70SApple OSS Distributions {
632*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
633*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorSetSharedRegionBaseAddress,
634*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
635*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
636*a1e26a70SApple OSS Distributions 	};
637*a1e26a70SApple OSS Distributions 
638*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call,
639*a1e26a70SApple OSS Distributions 	    SHARED_REGION_BASE,
640*a1e26a70SApple OSS Distributions 	    SHARED_REGION_SIZE);
641*a1e26a70SApple OSS Distributions }
642*a1e26a70SApple OSS Distributions 
643*a1e26a70SApple OSS Distributions void
code_signing_init(void)644*a1e26a70SApple OSS Distributions code_signing_init(void)
645*a1e26a70SApple OSS Distributions {
646*a1e26a70SApple OSS Distributions 	printf("libTXM_KernelVersion: %u\n", libTrustedExecutionMonitor_KernelVersion);
647*a1e26a70SApple OSS Distributions 	printf("libTXM_Image4Version: %u\n", libTrustedExecutionMonitor_Image4Version);
648*a1e26a70SApple OSS Distributions 
649*a1e26a70SApple OSS Distributions 	/* Setup the thread stacks used by TXM */
650*a1e26a70SApple OSS Distributions 	setup_thread_stacks();
651*a1e26a70SApple OSS Distributions 
652*a1e26a70SApple OSS Distributions 	/* Setup the logging lock */
653*a1e26a70SApple OSS Distributions 	lck_mtx_init(&log_lock, &txm_lck_grp, 0);
654*a1e26a70SApple OSS Distributions 
655*a1e26a70SApple OSS Distributions 	/* Setup TXM logging information */
656*a1e26a70SApple OSS Distributions 	get_logging_info();
657*a1e26a70SApple OSS Distributions 
658*a1e26a70SApple OSS Distributions 	/* Setup code signing configuration */
659*a1e26a70SApple OSS Distributions 	get_code_signing_info();
660*a1e26a70SApple OSS Distributions 
661*a1e26a70SApple OSS Distributions 	/* Setup all the other locks we need */
662*a1e26a70SApple OSS Distributions 	lck_mtx_init(&compilation_service_lock, &txm_lck_grp, 0);
663*a1e26a70SApple OSS Distributions 	lck_mtx_init(&unregister_sync_lock, &txm_lck_grp, 0);
664*a1e26a70SApple OSS Distributions 
665*a1e26a70SApple OSS Distributions 	/*
666*a1e26a70SApple OSS Distributions 	 * We need to let TXM know what the shared region base address is going
667*a1e26a70SApple OSS Distributions 	 * to be for this boot.
668*a1e26a70SApple OSS Distributions 	 */
669*a1e26a70SApple OSS Distributions 	set_shared_region_base_address();
670*a1e26a70SApple OSS Distributions 
671*a1e26a70SApple OSS Distributions 	/* Require signed code when monitor is enabled */
672*a1e26a70SApple OSS Distributions 	if (code_signing_enabled == true) {
673*a1e26a70SApple OSS Distributions 		cs_debug_fail_on_unsigned_code = 1;
674*a1e26a70SApple OSS Distributions 	}
675*a1e26a70SApple OSS Distributions }
676*a1e26a70SApple OSS Distributions 
677*a1e26a70SApple OSS Distributions void
txm_enter_lockdown_mode(void)678*a1e26a70SApple OSS Distributions txm_enter_lockdown_mode(void)
679*a1e26a70SApple OSS Distributions {
680*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
681*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorEnterLockdownMode,
682*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
683*a1e26a70SApple OSS Distributions 	};
684*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call);
685*a1e26a70SApple OSS Distributions }
686*a1e26a70SApple OSS Distributions 
687*a1e26a70SApple OSS Distributions kern_return_t
txm_secure_channel_shared_page(uint64_t * secure_channel_phys,size_t * secure_channel_size)688*a1e26a70SApple OSS Distributions txm_secure_channel_shared_page(
689*a1e26a70SApple OSS Distributions 	uint64_t *secure_channel_phys,
690*a1e26a70SApple OSS Distributions 	size_t *secure_channel_size)
691*a1e26a70SApple OSS Distributions {
692*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 5
693*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
694*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorGetSecureChannelAddr,
695*a1e26a70SApple OSS Distributions 		.num_output_args = 2
696*a1e26a70SApple OSS Distributions 	};
697*a1e26a70SApple OSS Distributions 
698*a1e26a70SApple OSS Distributions 	kern_return_t ret = txm_kernel_call(&txm_call);
699*a1e26a70SApple OSS Distributions 	if (ret == KERN_NOT_SUPPORTED) {
700*a1e26a70SApple OSS Distributions 		return ret;
701*a1e26a70SApple OSS Distributions 	} else if (ret != KERN_SUCCESS) {
702*a1e26a70SApple OSS Distributions 		panic("unexpected failure for TXM secure channel: %d", ret);
703*a1e26a70SApple OSS Distributions 	}
704*a1e26a70SApple OSS Distributions 
705*a1e26a70SApple OSS Distributions 	/* Return the physical address */
706*a1e26a70SApple OSS Distributions 	if (secure_channel_phys != NULL) {
707*a1e26a70SApple OSS Distributions 		*secure_channel_phys = txm_call.return_words[0];
708*a1e26a70SApple OSS Distributions 	}
709*a1e26a70SApple OSS Distributions 
710*a1e26a70SApple OSS Distributions 	/* Return the size */
711*a1e26a70SApple OSS Distributions 	if (secure_channel_size != NULL) {
712*a1e26a70SApple OSS Distributions 		*secure_channel_size = txm_call.return_words[1];
713*a1e26a70SApple OSS Distributions 	}
714*a1e26a70SApple OSS Distributions 
715*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
716*a1e26a70SApple OSS Distributions #else
717*a1e26a70SApple OSS Distributions 	(void)secure_channel_phys;
718*a1e26a70SApple OSS Distributions 	(void)secure_channel_size;
719*a1e26a70SApple OSS Distributions 	return KERN_NOT_SUPPORTED;
720*a1e26a70SApple OSS Distributions #endif
721*a1e26a70SApple OSS Distributions }
722*a1e26a70SApple OSS Distributions 
723*a1e26a70SApple OSS Distributions #pragma mark Developer Mode
724*a1e26a70SApple OSS Distributions 
725*a1e26a70SApple OSS Distributions void
txm_toggle_developer_mode(bool state)726*a1e26a70SApple OSS Distributions txm_toggle_developer_mode(bool state)
727*a1e26a70SApple OSS Distributions {
728*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
729*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorDeveloperModeToggle,
730*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
731*a1e26a70SApple OSS Distributions 		.num_input_args = 1
732*a1e26a70SApple OSS Distributions 	};
733*a1e26a70SApple OSS Distributions 
734*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, state);
735*a1e26a70SApple OSS Distributions }
736*a1e26a70SApple OSS Distributions 
737*a1e26a70SApple OSS Distributions #pragma mark Restricted Execution Mode
738*a1e26a70SApple OSS Distributions 
739*a1e26a70SApple OSS Distributions kern_return_t
txm_rem_enable(void)740*a1e26a70SApple OSS Distributions txm_rem_enable(void)
741*a1e26a70SApple OSS Distributions {
742*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
743*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorEnableRestrictedMode
744*a1e26a70SApple OSS Distributions 	};
745*a1e26a70SApple OSS Distributions 	return txm_kernel_call(&txm_call);
746*a1e26a70SApple OSS Distributions }
747*a1e26a70SApple OSS Distributions 
748*a1e26a70SApple OSS Distributions kern_return_t
txm_rem_state(void)749*a1e26a70SApple OSS Distributions txm_rem_state(void)
750*a1e26a70SApple OSS Distributions {
751*a1e26a70SApple OSS Distributions 	if (txm_restricted_mode_state == NULL) {
752*a1e26a70SApple OSS Distributions 		return KERN_NOT_SUPPORTED;
753*a1e26a70SApple OSS Distributions 	}
754*a1e26a70SApple OSS Distributions 
755*a1e26a70SApple OSS Distributions 	CSReturn_t cs_ret = restrictedModeStatus(txm_restricted_mode_state);
756*a1e26a70SApple OSS Distributions 	if (cs_ret.error == kCSReturnSuccess) {
757*a1e26a70SApple OSS Distributions 		return KERN_SUCCESS;
758*a1e26a70SApple OSS Distributions 	}
759*a1e26a70SApple OSS Distributions 	return KERN_DENIED;
760*a1e26a70SApple OSS Distributions }
761*a1e26a70SApple OSS Distributions 
762*a1e26a70SApple OSS Distributions #pragma mark Device State
763*a1e26a70SApple OSS Distributions 
764*a1e26a70SApple OSS Distributions void
txm_update_device_state(void)765*a1e26a70SApple OSS Distributions txm_update_device_state(void)
766*a1e26a70SApple OSS Distributions {
767*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 6
768*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
769*a1e26a70SApple OSS Distributions 		.selector = kTXMSelectorUpdateDeviceState,
770*a1e26a70SApple OSS Distributions 		.failure_fatal = true
771*a1e26a70SApple OSS Distributions 	};
772*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call);
773*a1e26a70SApple OSS Distributions #endif
774*a1e26a70SApple OSS Distributions }
775*a1e26a70SApple OSS Distributions 
776*a1e26a70SApple OSS Distributions void
txm_complete_security_boot_mode(__unused uint32_t security_boot_mode)777*a1e26a70SApple OSS Distributions txm_complete_security_boot_mode(
778*a1e26a70SApple OSS Distributions 	__unused uint32_t security_boot_mode)
779*a1e26a70SApple OSS Distributions {
780*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 6
781*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
782*a1e26a70SApple OSS Distributions 		.selector = kTXMSelectorCompleteSecurityBootMode,
783*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
784*a1e26a70SApple OSS Distributions 		.failure_fatal = true
785*a1e26a70SApple OSS Distributions 	};
786*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, security_boot_mode);
787*a1e26a70SApple OSS Distributions #endif
788*a1e26a70SApple OSS Distributions }
789*a1e26a70SApple OSS Distributions 
790*a1e26a70SApple OSS Distributions #pragma mark Code Signing and Provisioning Profiles
791*a1e26a70SApple OSS Distributions 
792*a1e26a70SApple OSS Distributions bool
txm_code_signing_enabled(void)793*a1e26a70SApple OSS Distributions txm_code_signing_enabled(void)
794*a1e26a70SApple OSS Distributions {
795*a1e26a70SApple OSS Distributions 	return code_signing_enabled;
796*a1e26a70SApple OSS Distributions }
797*a1e26a70SApple OSS Distributions 
798*a1e26a70SApple OSS Distributions vm_size_t
txm_managed_code_signature_size(void)799*a1e26a70SApple OSS Distributions txm_managed_code_signature_size(void)
800*a1e26a70SApple OSS Distributions {
801*a1e26a70SApple OSS Distributions 	return managed_signature_size;
802*a1e26a70SApple OSS Distributions }
803*a1e26a70SApple OSS Distributions 
804*a1e26a70SApple OSS Distributions kern_return_t
txm_register_provisioning_profile(const void * profile_blob,const size_t profile_blob_size,void ** profile_obj)805*a1e26a70SApple OSS Distributions txm_register_provisioning_profile(
806*a1e26a70SApple OSS Distributions 	const void *profile_blob,
807*a1e26a70SApple OSS Distributions 	const size_t profile_blob_size,
808*a1e26a70SApple OSS Distributions 	void **profile_obj)
809*a1e26a70SApple OSS Distributions {
810*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
811*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorRegisterProvisioningProfile,
812*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
813*a1e26a70SApple OSS Distributions 		.num_output_args = 1
814*a1e26a70SApple OSS Distributions 	};
815*a1e26a70SApple OSS Distributions 	vm_address_t payload_addr = 0;
816*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
817*a1e26a70SApple OSS Distributions 
818*a1e26a70SApple OSS Distributions 	/* We need to allocate page-wise in order to transfer the range to TXM */
819*a1e26a70SApple OSS Distributions 	ret = kmem_alloc(kernel_map, &payload_addr, profile_blob_size,
820*a1e26a70SApple OSS Distributions 	    KMA_KOBJECT | KMA_DATA, VM_KERN_MEMORY_SECURITY);
821*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
822*a1e26a70SApple OSS Distributions 		printf("unable to allocate memory for profile payload: %d\n", ret);
823*a1e26a70SApple OSS Distributions 		goto exit;
824*a1e26a70SApple OSS Distributions 	}
825*a1e26a70SApple OSS Distributions 
826*a1e26a70SApple OSS Distributions 	/* Copy the contents into the allocation */
827*a1e26a70SApple OSS Distributions 	memcpy((void*)payload_addr, profile_blob, profile_blob_size);
828*a1e26a70SApple OSS Distributions 
829*a1e26a70SApple OSS Distributions 	/* Transfer the memory range to TXM */
830*a1e26a70SApple OSS Distributions 	txm_transfer_region(payload_addr, profile_blob_size);
831*a1e26a70SApple OSS Distributions 
832*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, payload_addr, profile_blob_size);
833*a1e26a70SApple OSS Distributions 	if (ret == KERN_SUCCESS) {
834*a1e26a70SApple OSS Distributions 		*profile_obj = (void*)txm_call.return_words[0];
835*a1e26a70SApple OSS Distributions 	}
836*a1e26a70SApple OSS Distributions 
837*a1e26a70SApple OSS Distributions exit:
838*a1e26a70SApple OSS Distributions 	if ((ret != KERN_SUCCESS) && (payload_addr != 0)) {
839*a1e26a70SApple OSS Distributions 		/* Reclaim this memory range */
840*a1e26a70SApple OSS Distributions 		txm_reclaim_region(payload_addr, profile_blob_size);
841*a1e26a70SApple OSS Distributions 
842*a1e26a70SApple OSS Distributions 		/* Free the memory range */
843*a1e26a70SApple OSS Distributions 		kmem_free(kernel_map, payload_addr, profile_blob_size);
844*a1e26a70SApple OSS Distributions 		payload_addr = 0;
845*a1e26a70SApple OSS Distributions 	}
846*a1e26a70SApple OSS Distributions 
847*a1e26a70SApple OSS Distributions 	return ret;
848*a1e26a70SApple OSS Distributions }
849*a1e26a70SApple OSS Distributions 
850*a1e26a70SApple OSS Distributions kern_return_t
txm_trust_provisioning_profile(__unused void * profile_obj,__unused const void * sig_data,__unused size_t sig_size)851*a1e26a70SApple OSS Distributions txm_trust_provisioning_profile(
852*a1e26a70SApple OSS Distributions 	__unused void *profile_obj,
853*a1e26a70SApple OSS Distributions 	__unused const void *sig_data,
854*a1e26a70SApple OSS Distributions 	__unused size_t sig_size)
855*a1e26a70SApple OSS Distributions {
856*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 7
857*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
858*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorTrustProvisioningProfile,
859*a1e26a70SApple OSS Distributions 		.num_input_args = 3
860*a1e26a70SApple OSS Distributions 	};
861*a1e26a70SApple OSS Distributions 
862*a1e26a70SApple OSS Distributions 	return txm_kernel_call(&txm_call, profile_obj, sig_data, sig_size);
863*a1e26a70SApple OSS Distributions #else
864*a1e26a70SApple OSS Distributions 	/* The TXM selector hasn't yet landed */
865*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
866*a1e26a70SApple OSS Distributions #endif
867*a1e26a70SApple OSS Distributions }
868*a1e26a70SApple OSS Distributions 
869*a1e26a70SApple OSS Distributions kern_return_t
txm_unregister_provisioning_profile(void * profile_obj)870*a1e26a70SApple OSS Distributions txm_unregister_provisioning_profile(
871*a1e26a70SApple OSS Distributions 	void *profile_obj)
872*a1e26a70SApple OSS Distributions {
873*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
874*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorUnregisterProvisioningProfile,
875*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
876*a1e26a70SApple OSS Distributions 		.num_output_args = 2
877*a1e26a70SApple OSS Distributions 	};
878*a1e26a70SApple OSS Distributions 	vm_address_t profile_addr = 0;
879*a1e26a70SApple OSS Distributions 	vm_size_t profile_size = 0;
880*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
881*a1e26a70SApple OSS Distributions 
882*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, profile_obj);
883*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
884*a1e26a70SApple OSS Distributions 		return ret;
885*a1e26a70SApple OSS Distributions 	}
886*a1e26a70SApple OSS Distributions 
887*a1e26a70SApple OSS Distributions 	profile_addr = txm_call.return_words[0];
888*a1e26a70SApple OSS Distributions 	profile_size = txm_call.return_words[1];
889*a1e26a70SApple OSS Distributions 
890*a1e26a70SApple OSS Distributions 	/* Reclaim this memory range */
891*a1e26a70SApple OSS Distributions 	txm_reclaim_region(profile_addr, profile_size);
892*a1e26a70SApple OSS Distributions 
893*a1e26a70SApple OSS Distributions 	/* Free the memory range */
894*a1e26a70SApple OSS Distributions 	kmem_free(kernel_map, profile_addr, profile_size);
895*a1e26a70SApple OSS Distributions 
896*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
897*a1e26a70SApple OSS Distributions }
898*a1e26a70SApple OSS Distributions 
899*a1e26a70SApple OSS Distributions kern_return_t
txm_associate_provisioning_profile(void * sig_obj,void * profile_obj)900*a1e26a70SApple OSS Distributions txm_associate_provisioning_profile(
901*a1e26a70SApple OSS Distributions 	void *sig_obj,
902*a1e26a70SApple OSS Distributions 	void *profile_obj)
903*a1e26a70SApple OSS Distributions {
904*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
905*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAssociateProvisioningProfile,
906*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
907*a1e26a70SApple OSS Distributions 	};
908*a1e26a70SApple OSS Distributions 
909*a1e26a70SApple OSS Distributions 	return txm_kernel_call(&txm_call, sig_obj, profile_obj);
910*a1e26a70SApple OSS Distributions }
911*a1e26a70SApple OSS Distributions 
912*a1e26a70SApple OSS Distributions kern_return_t
txm_disassociate_provisioning_profile(void * sig_obj)913*a1e26a70SApple OSS Distributions txm_disassociate_provisioning_profile(
914*a1e26a70SApple OSS Distributions 	void *sig_obj)
915*a1e26a70SApple OSS Distributions {
916*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
917*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorDisassociateProvisioningProfile,
918*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
919*a1e26a70SApple OSS Distributions 	};
920*a1e26a70SApple OSS Distributions 
921*a1e26a70SApple OSS Distributions 	/*
922*a1e26a70SApple OSS Distributions 	 * Take the unregistration sync lock.
923*a1e26a70SApple OSS Distributions 	 * For more information: rdar://99205627.
924*a1e26a70SApple OSS Distributions 	 */
925*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&unregister_sync_lock);
926*a1e26a70SApple OSS Distributions 
927*a1e26a70SApple OSS Distributions 	/* Disassociate the profile from the signature */
928*a1e26a70SApple OSS Distributions 	kern_return_t ret = txm_kernel_call(&txm_call, sig_obj);
929*a1e26a70SApple OSS Distributions 
930*a1e26a70SApple OSS Distributions 	/* Release the unregistration sync lock */
931*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&unregister_sync_lock);
932*a1e26a70SApple OSS Distributions 
933*a1e26a70SApple OSS Distributions 	return ret;
934*a1e26a70SApple OSS Distributions }
935*a1e26a70SApple OSS Distributions 
936*a1e26a70SApple OSS Distributions void
txm_set_compilation_service_cdhash(const uint8_t cdhash[CS_CDHASH_LEN])937*a1e26a70SApple OSS Distributions txm_set_compilation_service_cdhash(
938*a1e26a70SApple OSS Distributions 	const uint8_t cdhash[CS_CDHASH_LEN])
939*a1e26a70SApple OSS Distributions {
940*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
941*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAuthorizeCompilationServiceCDHash,
942*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
943*a1e26a70SApple OSS Distributions 	};
944*a1e26a70SApple OSS Distributions 
945*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&compilation_service_lock);
946*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, cdhash);
947*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&compilation_service_lock);
948*a1e26a70SApple OSS Distributions }
949*a1e26a70SApple OSS Distributions 
950*a1e26a70SApple OSS Distributions bool
txm_match_compilation_service_cdhash(const uint8_t cdhash[CS_CDHASH_LEN])951*a1e26a70SApple OSS Distributions txm_match_compilation_service_cdhash(
952*a1e26a70SApple OSS Distributions 	const uint8_t cdhash[CS_CDHASH_LEN])
953*a1e26a70SApple OSS Distributions {
954*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
955*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorMatchCompilationServiceCDHash,
956*a1e26a70SApple OSS Distributions 		.failure_silent = true,
957*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
958*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
959*a1e26a70SApple OSS Distributions 	};
960*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
961*a1e26a70SApple OSS Distributions 
962*a1e26a70SApple OSS Distributions 	/* Be safe and take the lock (avoid thread collisions) */
963*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&compilation_service_lock);
964*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, cdhash);
965*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&compilation_service_lock);
966*a1e26a70SApple OSS Distributions 
967*a1e26a70SApple OSS Distributions 	if (ret == KERN_SUCCESS) {
968*a1e26a70SApple OSS Distributions 		return true;
969*a1e26a70SApple OSS Distributions 	}
970*a1e26a70SApple OSS Distributions 	return false;
971*a1e26a70SApple OSS Distributions }
972*a1e26a70SApple OSS Distributions 
973*a1e26a70SApple OSS Distributions void
txm_set_local_signing_public_key(const uint8_t public_key[XNU_LOCAL_SIGNING_KEY_SIZE])974*a1e26a70SApple OSS Distributions txm_set_local_signing_public_key(
975*a1e26a70SApple OSS Distributions 	const uint8_t public_key[XNU_LOCAL_SIGNING_KEY_SIZE])
976*a1e26a70SApple OSS Distributions {
977*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
978*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorSetLocalSigningPublicKey,
979*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
980*a1e26a70SApple OSS Distributions 	};
981*a1e26a70SApple OSS Distributions 
982*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, public_key);
983*a1e26a70SApple OSS Distributions }
984*a1e26a70SApple OSS Distributions 
985*a1e26a70SApple OSS Distributions uint8_t*
txm_get_local_signing_public_key(void)986*a1e26a70SApple OSS Distributions txm_get_local_signing_public_key(void)
987*a1e26a70SApple OSS Distributions {
988*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
989*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorGetLocalSigningPublicKey,
990*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
991*a1e26a70SApple OSS Distributions 	};
992*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
993*a1e26a70SApple OSS Distributions 
994*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call);
995*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
996*a1e26a70SApple OSS Distributions 		return NULL;
997*a1e26a70SApple OSS Distributions 	}
998*a1e26a70SApple OSS Distributions 
999*a1e26a70SApple OSS Distributions 	return (uint8_t*)txm_call.return_words[0];
1000*a1e26a70SApple OSS Distributions }
1001*a1e26a70SApple OSS Distributions 
1002*a1e26a70SApple OSS Distributions void
txm_unrestrict_local_signing_cdhash(const uint8_t cdhash[CS_CDHASH_LEN])1003*a1e26a70SApple OSS Distributions txm_unrestrict_local_signing_cdhash(
1004*a1e26a70SApple OSS Distributions 	const uint8_t cdhash[CS_CDHASH_LEN])
1005*a1e26a70SApple OSS Distributions {
1006*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1007*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAuthorizeLocalSigningCDHash,
1008*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1009*a1e26a70SApple OSS Distributions 	};
1010*a1e26a70SApple OSS Distributions 
1011*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, cdhash);
1012*a1e26a70SApple OSS Distributions }
1013*a1e26a70SApple OSS Distributions 
1014*a1e26a70SApple OSS Distributions kern_return_t
txm_register_code_signature(const vm_address_t signature_addr,const vm_size_t signature_size,const vm_offset_t code_directory_offset,const char * signature_path,void ** sig_obj,vm_address_t * txm_signature_addr)1015*a1e26a70SApple OSS Distributions txm_register_code_signature(
1016*a1e26a70SApple OSS Distributions 	const vm_address_t signature_addr,
1017*a1e26a70SApple OSS Distributions 	const vm_size_t signature_size,
1018*a1e26a70SApple OSS Distributions 	const vm_offset_t code_directory_offset,
1019*a1e26a70SApple OSS Distributions 	const char *signature_path,
1020*a1e26a70SApple OSS Distributions 	void **sig_obj,
1021*a1e26a70SApple OSS Distributions 	vm_address_t *txm_signature_addr)
1022*a1e26a70SApple OSS Distributions {
1023*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1024*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorRegisterCodeSignature,
1025*a1e26a70SApple OSS Distributions 		.num_input_args = 3,
1026*a1e26a70SApple OSS Distributions 		.num_output_args = 2,
1027*a1e26a70SApple OSS Distributions 	};
1028*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1029*a1e26a70SApple OSS Distributions 
1030*a1e26a70SApple OSS Distributions 	/*
1031*a1e26a70SApple OSS Distributions 	 * TXM performs more exhaustive validation of the code signature and figures
1032*a1e26a70SApple OSS Distributions 	 * out the best code directory to use on its own. As a result, this offset here
1033*a1e26a70SApple OSS Distributions 	 * is not used.
1034*a1e26a70SApple OSS Distributions 	 */
1035*a1e26a70SApple OSS Distributions 	(void)code_directory_offset;
1036*a1e26a70SApple OSS Distributions 
1037*a1e26a70SApple OSS Distributions 	/*
1038*a1e26a70SApple OSS Distributions 	 * If the signature is large enough to not fit within TXM's managed signature
1039*a1e26a70SApple OSS Distributions 	 * size, then we need to transfer it over so it is owned by TXM.
1040*a1e26a70SApple OSS Distributions 	 */
1041*a1e26a70SApple OSS Distributions 	if (signature_size > txm_managed_code_signature_size()) {
1042*a1e26a70SApple OSS Distributions 		txm_transfer_region(signature_addr, signature_size);
1043*a1e26a70SApple OSS Distributions 	}
1044*a1e26a70SApple OSS Distributions 
1045*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(
1046*a1e26a70SApple OSS Distributions 		&txm_call,
1047*a1e26a70SApple OSS Distributions 		signature_addr,
1048*a1e26a70SApple OSS Distributions 		signature_size,
1049*a1e26a70SApple OSS Distributions 		signature_path);
1050*a1e26a70SApple OSS Distributions 
1051*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
1052*a1e26a70SApple OSS Distributions 		goto exit;
1053*a1e26a70SApple OSS Distributions 	}
1054*a1e26a70SApple OSS Distributions 
1055*a1e26a70SApple OSS Distributions 	*sig_obj = (void*)txm_call.return_words[0];
1056*a1e26a70SApple OSS Distributions 	*txm_signature_addr = txm_call.return_words[1];
1057*a1e26a70SApple OSS Distributions 
1058*a1e26a70SApple OSS Distributions exit:
1059*a1e26a70SApple OSS Distributions 	if ((ret != KERN_SUCCESS) && (signature_size > txm_managed_code_signature_size())) {
1060*a1e26a70SApple OSS Distributions 		txm_reclaim_region(signature_addr, signature_size);
1061*a1e26a70SApple OSS Distributions 	}
1062*a1e26a70SApple OSS Distributions 
1063*a1e26a70SApple OSS Distributions 	return ret;
1064*a1e26a70SApple OSS Distributions }
1065*a1e26a70SApple OSS Distributions 
1066*a1e26a70SApple OSS Distributions kern_return_t
txm_unregister_code_signature(void * sig_obj)1067*a1e26a70SApple OSS Distributions txm_unregister_code_signature(
1068*a1e26a70SApple OSS Distributions 	void *sig_obj)
1069*a1e26a70SApple OSS Distributions {
1070*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1071*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorUnregisterCodeSignature,
1072*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1073*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1074*a1e26a70SApple OSS Distributions 		.num_output_args = 2,
1075*a1e26a70SApple OSS Distributions 	};
1076*a1e26a70SApple OSS Distributions 	TXMCodeSignature_t *cs_obj = sig_obj;
1077*a1e26a70SApple OSS Distributions 	vm_address_t signature_addr = 0;
1078*a1e26a70SApple OSS Distributions 	vm_size_t signature_size = 0;
1079*a1e26a70SApple OSS Distributions 	bool txm_managed = false;
1080*a1e26a70SApple OSS Distributions 
1081*a1e26a70SApple OSS Distributions 	/*
1082*a1e26a70SApple OSS Distributions 	 * Unregistering a code signature can cause lock contention in TXM against a
1083*a1e26a70SApple OSS Distributions 	 * set of other functions. The unregistration operation is very common when the
1084*a1e26a70SApple OSS Distributions 	 * system is about to reboot because the VFS layer unmounts all volumes.
1085*a1e26a70SApple OSS Distributions 	 *
1086*a1e26a70SApple OSS Distributions 	 * In order to avoid this issue, we detect if the code signature in question
1087*a1e26a70SApple OSS Distributions 	 * has been mapped in other address spaces, and if so, we avoid unregistering
1088*a1e26a70SApple OSS Distributions 	 * the code signature when we're about to shut down. This leaks memory, but
1089*a1e26a70SApple OSS Distributions 	 * we're about to shut down.
1090*a1e26a70SApple OSS Distributions 	 */
1091*a1e26a70SApple OSS Distributions 	if ((cs_obj->referenceCount > 0) && (get_system_inshutdown() != 0)) {
1092*a1e26a70SApple OSS Distributions 		printf("TXM [XNU]: unregistration of signature skipped as system is in shutdown\n");
1093*a1e26a70SApple OSS Distributions 		return KERN_ABORTED;
1094*a1e26a70SApple OSS Distributions 	}
1095*a1e26a70SApple OSS Distributions 
1096*a1e26a70SApple OSS Distributions 	/* Check if the signature memory is TXM managed */
1097*a1e26a70SApple OSS Distributions 	txm_managed = cs_obj->sptmType != TXM_BULK_DATA;
1098*a1e26a70SApple OSS Distributions 
1099*a1e26a70SApple OSS Distributions 	/*
1100*a1e26a70SApple OSS Distributions 	 * Take the unregistration sync lock.
1101*a1e26a70SApple OSS Distributions 	 * For more information: rdar://99205627.
1102*a1e26a70SApple OSS Distributions 	 */
1103*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&unregister_sync_lock);
1104*a1e26a70SApple OSS Distributions 
1105*a1e26a70SApple OSS Distributions 	/* Unregister the signature from TXM -- cannot fail */
1106*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, sig_obj);
1107*a1e26a70SApple OSS Distributions 
1108*a1e26a70SApple OSS Distributions 	/* Release the unregistration sync lock */
1109*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&unregister_sync_lock);
1110*a1e26a70SApple OSS Distributions 
1111*a1e26a70SApple OSS Distributions 	signature_addr = txm_call.return_words[0];
1112*a1e26a70SApple OSS Distributions 	signature_size = txm_call.return_words[1];
1113*a1e26a70SApple OSS Distributions 
1114*a1e26a70SApple OSS Distributions 	/* Reclaim the memory range in case we need to */
1115*a1e26a70SApple OSS Distributions 	if (txm_managed == false) {
1116*a1e26a70SApple OSS Distributions 		txm_reclaim_region(signature_addr, signature_size);
1117*a1e26a70SApple OSS Distributions 	}
1118*a1e26a70SApple OSS Distributions 
1119*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1120*a1e26a70SApple OSS Distributions }
1121*a1e26a70SApple OSS Distributions 
1122*a1e26a70SApple OSS Distributions kern_return_t
txm_verify_code_signature(void * sig_obj,uint32_t * trust_level)1123*a1e26a70SApple OSS Distributions txm_verify_code_signature(
1124*a1e26a70SApple OSS Distributions 	void *sig_obj,
1125*a1e26a70SApple OSS Distributions 	uint32_t *trust_level)
1126*a1e26a70SApple OSS Distributions {
1127*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1128*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorValidateCodeSignature,
1129*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1130*a1e26a70SApple OSS Distributions 	};
1131*a1e26a70SApple OSS Distributions 	kern_return_t ret = txm_kernel_call(&txm_call, sig_obj);
1132*a1e26a70SApple OSS Distributions 
1133*a1e26a70SApple OSS Distributions 	if ((ret == KERN_SUCCESS) && (trust_level != NULL)) {
1134*a1e26a70SApple OSS Distributions 		/*
1135*a1e26a70SApple OSS Distributions 		 * Abolsutely gross, but it's not worth linking all of libCodeSignature just for
1136*a1e26a70SApple OSS Distributions 		 * this simple change. We should either return the trust level from TXM, or when
1137*a1e26a70SApple OSS Distributions 		 * we adopt libCodeSignature more broadly, then use an accessor function.
1138*a1e26a70SApple OSS Distributions 		 */
1139*a1e26a70SApple OSS Distributions 		*trust_level = ((TXMCodeSignature_t*)sig_obj)->sig.trustLevel;
1140*a1e26a70SApple OSS Distributions 	}
1141*a1e26a70SApple OSS Distributions 	return ret;
1142*a1e26a70SApple OSS Distributions }
1143*a1e26a70SApple OSS Distributions 
1144*a1e26a70SApple OSS Distributions kern_return_t
txm_reconstitute_code_signature(void * sig_obj,vm_address_t * unneeded_addr,vm_size_t * unneeded_size)1145*a1e26a70SApple OSS Distributions txm_reconstitute_code_signature(
1146*a1e26a70SApple OSS Distributions 	void *sig_obj,
1147*a1e26a70SApple OSS Distributions 	vm_address_t *unneeded_addr,
1148*a1e26a70SApple OSS Distributions 	vm_size_t *unneeded_size)
1149*a1e26a70SApple OSS Distributions {
1150*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1151*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorReconstituteCodeSignature,
1152*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1153*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1154*a1e26a70SApple OSS Distributions 		.num_output_args = 2,
1155*a1e26a70SApple OSS Distributions 	};
1156*a1e26a70SApple OSS Distributions 	vm_address_t return_addr = 0;
1157*a1e26a70SApple OSS Distributions 	vm_size_t return_size = 0;
1158*a1e26a70SApple OSS Distributions 
1159*a1e26a70SApple OSS Distributions 	/* Reconstitute the code signature -- cannot fail */
1160*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, sig_obj);
1161*a1e26a70SApple OSS Distributions 
1162*a1e26a70SApple OSS Distributions 	return_addr = txm_call.return_words[0];
1163*a1e26a70SApple OSS Distributions 	return_size = txm_call.return_words[1];
1164*a1e26a70SApple OSS Distributions 
1165*a1e26a70SApple OSS Distributions 	/* Reclaim the memory region if we need to */
1166*a1e26a70SApple OSS Distributions 	if ((return_addr != 0) && (return_size != 0)) {
1167*a1e26a70SApple OSS Distributions 		txm_reclaim_region(return_addr, return_size);
1168*a1e26a70SApple OSS Distributions 	}
1169*a1e26a70SApple OSS Distributions 
1170*a1e26a70SApple OSS Distributions 	*unneeded_addr = return_addr;
1171*a1e26a70SApple OSS Distributions 	*unneeded_size = return_size;
1172*a1e26a70SApple OSS Distributions 
1173*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1174*a1e26a70SApple OSS Distributions }
1175*a1e26a70SApple OSS Distributions 
1176*a1e26a70SApple OSS Distributions #pragma mark Address Spaces
1177*a1e26a70SApple OSS Distributions 
1178*a1e26a70SApple OSS Distributions kern_return_t
txm_register_address_space(pmap_t pmap,uint16_t addr_space_id,TXMAddressSpaceFlags_t flags)1179*a1e26a70SApple OSS Distributions txm_register_address_space(
1180*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1181*a1e26a70SApple OSS Distributions 	uint16_t addr_space_id,
1182*a1e26a70SApple OSS Distributions 	TXMAddressSpaceFlags_t flags)
1183*a1e26a70SApple OSS Distributions {
1184*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1185*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorRegisterAddressSpace,
1186*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1187*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
1188*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1189*a1e26a70SApple OSS Distributions 	};
1190*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = NULL;
1191*a1e26a70SApple OSS Distributions 
1192*a1e26a70SApple OSS Distributions 	/* Register the address space -- cannot fail */
1193*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, addr_space_id, flags);
1194*a1e26a70SApple OSS Distributions 
1195*a1e26a70SApple OSS Distributions 	/* Set the address space object within the PMAP */
1196*a1e26a70SApple OSS Distributions 	txm_addr_space = (TXMAddressSpace_t*)txm_call.return_words[0];
1197*a1e26a70SApple OSS Distributions 	pmap_txm_set_addr_space(pmap, txm_addr_space);
1198*a1e26a70SApple OSS Distributions 
1199*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1200*a1e26a70SApple OSS Distributions }
1201*a1e26a70SApple OSS Distributions 
1202*a1e26a70SApple OSS Distributions kern_return_t
txm_unregister_address_space(pmap_t pmap)1203*a1e26a70SApple OSS Distributions txm_unregister_address_space(
1204*a1e26a70SApple OSS Distributions 	pmap_t pmap)
1205*a1e26a70SApple OSS Distributions {
1206*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1207*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorUnregisterAddressSpace,
1208*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1209*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1210*a1e26a70SApple OSS Distributions 	};
1211*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1212*a1e26a70SApple OSS Distributions 
1213*a1e26a70SApple OSS Distributions 	/*
1214*a1e26a70SApple OSS Distributions 	 * Take the unregistration sync lock.
1215*a1e26a70SApple OSS Distributions 	 * For more information: rdar://99205627.
1216*a1e26a70SApple OSS Distributions 	 */
1217*a1e26a70SApple OSS Distributions 	lck_mtx_lock(&unregister_sync_lock);
1218*a1e26a70SApple OSS Distributions 
1219*a1e26a70SApple OSS Distributions 	/* Unregister the address space -- cannot fail */
1220*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, txm_addr_space);
1221*a1e26a70SApple OSS Distributions 
1222*a1e26a70SApple OSS Distributions 	/* Release the unregistration sync lock */
1223*a1e26a70SApple OSS Distributions 	lck_mtx_unlock(&unregister_sync_lock);
1224*a1e26a70SApple OSS Distributions 
1225*a1e26a70SApple OSS Distributions 	/* Remove the address space from the pmap */
1226*a1e26a70SApple OSS Distributions 	pmap_txm_set_addr_space(pmap, NULL);
1227*a1e26a70SApple OSS Distributions 
1228*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1229*a1e26a70SApple OSS Distributions }
1230*a1e26a70SApple OSS Distributions 
1231*a1e26a70SApple OSS Distributions kern_return_t
txm_associate_code_signature(pmap_t pmap,void * sig_obj,const vm_address_t region_addr,const vm_size_t region_size,const vm_offset_t region_offset)1232*a1e26a70SApple OSS Distributions txm_associate_code_signature(
1233*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1234*a1e26a70SApple OSS Distributions 	void *sig_obj,
1235*a1e26a70SApple OSS Distributions 	const vm_address_t region_addr,
1236*a1e26a70SApple OSS Distributions 	const vm_size_t region_size,
1237*a1e26a70SApple OSS Distributions 	const vm_offset_t region_offset)
1238*a1e26a70SApple OSS Distributions {
1239*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1240*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAssociateCodeSignature,
1241*a1e26a70SApple OSS Distributions 		.num_input_args = 5,
1242*a1e26a70SApple OSS Distributions 	};
1243*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1244*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1245*a1e26a70SApple OSS Distributions 
1246*a1e26a70SApple OSS Distributions 	/*
1247*a1e26a70SApple OSS Distributions 	 * Associating a code signature may require exclusive access to the TXM address
1248*a1e26a70SApple OSS Distributions 	 * space lock within TXM.
1249*a1e26a70SApple OSS Distributions 	 */
1250*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_exclusive_lock(pmap);
1251*a1e26a70SApple OSS Distributions 
1252*a1e26a70SApple OSS Distributions 	/*
1253*a1e26a70SApple OSS Distributions 	 * If the address space in question is a nested address space, then all associations
1254*a1e26a70SApple OSS Distributions 	 * need to go into the shared region base range. The VM layer is inconsistent with
1255*a1e26a70SApple OSS Distributions 	 * how it makes associations with TXM vs. how it maps pages into the shared region.
1256*a1e26a70SApple OSS Distributions 	 *
1257*a1e26a70SApple OSS Distributions 	 * For TXM, the associations are made without taking the base range into account,
1258*a1e26a70SApple OSS Distributions 	 * but when mappings are entered into the shared region, the base range is taken
1259*a1e26a70SApple OSS Distributions 	 * into account. To normalize this, we add the base range address here.
1260*a1e26a70SApple OSS Distributions 	 */
1261*a1e26a70SApple OSS Distributions 	vm_address_t adjusted_region_addr = region_addr;
1262*a1e26a70SApple OSS Distributions 	if (txm_addr_space->addrSpaceID.type == kTXMAddressSpaceIDTypeSharedRegion) {
1263*a1e26a70SApple OSS Distributions 		adjusted_region_addr += SHARED_REGION_BASE;
1264*a1e26a70SApple OSS Distributions 	}
1265*a1e26a70SApple OSS Distributions 
1266*a1e26a70SApple OSS Distributions 	/*
1267*a1e26a70SApple OSS Distributions 	 * The VM tries a bunch of weird mappings within launchd for some platform code
1268*a1e26a70SApple OSS Distributions 	 * which isn't mapped contiguously. These mappings don't succeed, but the failure
1269*a1e26a70SApple OSS Distributions 	 * is fairly harmless since everything seems to work. However, since the call to
1270*a1e26a70SApple OSS Distributions 	 * TXM fails, we make a series of logs. Hence, for launchd, we suppress failure
1271*a1e26a70SApple OSS Distributions 	 * logs.
1272*a1e26a70SApple OSS Distributions 	 */
1273*a1e26a70SApple OSS Distributions 	if (txm_addr_space->addrSpaceID.type == kTXMAddressSpaceIDTypeAddressSpace) {
1274*a1e26a70SApple OSS Distributions 		/* TXMTODO: Scope this to launchd better */
1275*a1e26a70SApple OSS Distributions 		txm_call.failure_code_silent = kTXMReturnPlatformCodeMapping;
1276*a1e26a70SApple OSS Distributions 	}
1277*a1e26a70SApple OSS Distributions 
1278*a1e26a70SApple OSS Distributions 	/* Check if the main region has been set on the address space */
1279*a1e26a70SApple OSS Distributions 	bool main_region_set = txm_addr_space->mainRegion != NULL;
1280*a1e26a70SApple OSS Distributions 	bool main_region_set_after = false;
1281*a1e26a70SApple OSS Distributions 
1282*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(
1283*a1e26a70SApple OSS Distributions 		&txm_call,
1284*a1e26a70SApple OSS Distributions 		txm_addr_space,
1285*a1e26a70SApple OSS Distributions 		sig_obj,
1286*a1e26a70SApple OSS Distributions 		adjusted_region_addr,
1287*a1e26a70SApple OSS Distributions 		region_size,
1288*a1e26a70SApple OSS Distributions 		region_offset);
1289*a1e26a70SApple OSS Distributions 
1290*a1e26a70SApple OSS Distributions 	while (ret == KERN_OPERATION_TIMED_OUT) {
1291*a1e26a70SApple OSS Distributions 		/*
1292*a1e26a70SApple OSS Distributions 		 * There is no easy method to sleep in the kernel. This operation has the
1293*a1e26a70SApple OSS Distributions 		 * potential to burn CPU cycles, but that is alright since we don't actually
1294*a1e26a70SApple OSS Distributions 		 * ever expect to enter this case on legitimately operating systems.
1295*a1e26a70SApple OSS Distributions 		 */
1296*a1e26a70SApple OSS Distributions 		ret = txm_kernel_call(
1297*a1e26a70SApple OSS Distributions 			&txm_call,
1298*a1e26a70SApple OSS Distributions 			txm_addr_space,
1299*a1e26a70SApple OSS Distributions 			sig_obj,
1300*a1e26a70SApple OSS Distributions 			adjusted_region_addr,
1301*a1e26a70SApple OSS Distributions 			region_size,
1302*a1e26a70SApple OSS Distributions 			region_offset);
1303*a1e26a70SApple OSS Distributions 	}
1304*a1e26a70SApple OSS Distributions 
1305*a1e26a70SApple OSS Distributions 	/*
1306*a1e26a70SApple OSS Distributions 	 * If the main region wasn't set on the address space before hand, but this new
1307*a1e26a70SApple OSS Distributions 	 * call into TXM was successful and sets the main region, it means this signature
1308*a1e26a70SApple OSS Distributions 	 * object is associated with the main region on the address space. With this, we
1309*a1e26a70SApple OSS Distributions 	 * can now set the appropriate trust level on the PMAP.
1310*a1e26a70SApple OSS Distributions 	 */
1311*a1e26a70SApple OSS Distributions 	if (ret == KERN_SUCCESS) {
1312*a1e26a70SApple OSS Distributions 		main_region_set_after = txm_addr_space->mainRegion != NULL;
1313*a1e26a70SApple OSS Distributions 	}
1314*a1e26a70SApple OSS Distributions 
1315*a1e26a70SApple OSS Distributions 	/* Unlock the TXM address space lock */
1316*a1e26a70SApple OSS Distributions 	pmap_txm_release_exclusive_lock(pmap);
1317*a1e26a70SApple OSS Distributions 
1318*a1e26a70SApple OSS Distributions 	/* Check if we should set the trust level on the PMAP */
1319*a1e26a70SApple OSS Distributions 	if (!main_region_set && main_region_set_after) {
1320*a1e26a70SApple OSS Distributions 		const TXMCodeSignature_t *cs_obj = sig_obj;
1321*a1e26a70SApple OSS Distributions 		const SignatureValidation_t *sig = &cs_obj->sig;
1322*a1e26a70SApple OSS Distributions 
1323*a1e26a70SApple OSS Distributions 		/*
1324*a1e26a70SApple OSS Distributions 		 * This is gross, as we're dereferencing into a private data structure type.
1325*a1e26a70SApple OSS Distributions 		 * There are 2 ways to clean this up in the future:
1326*a1e26a70SApple OSS Distributions 		 * 1. Import libCodeSignature, so we can use "codeSignatureGetTrustLevel".
1327*a1e26a70SApple OSS Distributions 		 * 2. Cache the trust level on the address space within TXM and then use it.
1328*a1e26a70SApple OSS Distributions 		 */
1329*a1e26a70SApple OSS Distributions 		pmap_txm_set_trust_level(pmap, sig->trustLevel);
1330*a1e26a70SApple OSS Distributions 	}
1331*a1e26a70SApple OSS Distributions 
1332*a1e26a70SApple OSS Distributions 	return ret;
1333*a1e26a70SApple OSS Distributions }
1334*a1e26a70SApple OSS Distributions 
1335*a1e26a70SApple OSS Distributions kern_return_t
txm_allow_jit_region(pmap_t pmap)1336*a1e26a70SApple OSS Distributions txm_allow_jit_region(
1337*a1e26a70SApple OSS Distributions 	pmap_t pmap)
1338*a1e26a70SApple OSS Distributions {
1339*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1340*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAllowJITRegion,
1341*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1342*a1e26a70SApple OSS Distributions 	};
1343*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1344*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1345*a1e26a70SApple OSS Distributions 
1346*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_shared_lock(pmap);
1347*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, txm_addr_space);
1348*a1e26a70SApple OSS Distributions 	pmap_txm_release_shared_lock(pmap);
1349*a1e26a70SApple OSS Distributions 
1350*a1e26a70SApple OSS Distributions 	return ret;
1351*a1e26a70SApple OSS Distributions }
1352*a1e26a70SApple OSS Distributions 
1353*a1e26a70SApple OSS Distributions kern_return_t
txm_associate_jit_region(pmap_t pmap,const vm_address_t region_addr,const vm_size_t region_size)1354*a1e26a70SApple OSS Distributions txm_associate_jit_region(
1355*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1356*a1e26a70SApple OSS Distributions 	const vm_address_t region_addr,
1357*a1e26a70SApple OSS Distributions 	const vm_size_t region_size)
1358*a1e26a70SApple OSS Distributions {
1359*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1360*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAssociateJITRegion,
1361*a1e26a70SApple OSS Distributions 		.num_input_args = 3,
1362*a1e26a70SApple OSS Distributions 	};
1363*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1364*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1365*a1e26a70SApple OSS Distributions 
1366*a1e26a70SApple OSS Distributions 	/*
1367*a1e26a70SApple OSS Distributions 	 * Associating a JIT region may require exclusive access to the TXM address
1368*a1e26a70SApple OSS Distributions 	 * space lock within TXM.
1369*a1e26a70SApple OSS Distributions 	 */
1370*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_exclusive_lock(pmap);
1371*a1e26a70SApple OSS Distributions 
1372*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(
1373*a1e26a70SApple OSS Distributions 		&txm_call,
1374*a1e26a70SApple OSS Distributions 		txm_addr_space,
1375*a1e26a70SApple OSS Distributions 		region_addr,
1376*a1e26a70SApple OSS Distributions 		region_size);
1377*a1e26a70SApple OSS Distributions 
1378*a1e26a70SApple OSS Distributions 	/* Unlock the TXM address space lock */
1379*a1e26a70SApple OSS Distributions 	pmap_txm_release_exclusive_lock(pmap);
1380*a1e26a70SApple OSS Distributions 
1381*a1e26a70SApple OSS Distributions 	return ret;
1382*a1e26a70SApple OSS Distributions }
1383*a1e26a70SApple OSS Distributions 
1384*a1e26a70SApple OSS Distributions kern_return_t
txm_address_space_debugged(pmap_t pmap)1385*a1e26a70SApple OSS Distributions txm_address_space_debugged(
1386*a1e26a70SApple OSS Distributions 	pmap_t pmap)
1387*a1e26a70SApple OSS Distributions {
1388*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1389*a1e26a70SApple OSS Distributions 	bool debug_regions_allowed = false;
1390*a1e26a70SApple OSS Distributions 
1391*a1e26a70SApple OSS Distributions 	/*
1392*a1e26a70SApple OSS Distributions 	 * We do not actually need to trap into the monitor for this function for
1393*a1e26a70SApple OSS Distributions 	 * now. It might be a tad bit more secure to actually trap into the monitor
1394*a1e26a70SApple OSS Distributions 	 * as it implicitly verifies all of our pointers, but since this is a simple
1395*a1e26a70SApple OSS Distributions 	 * state check against the address space, the real policy around it lies
1396*a1e26a70SApple OSS Distributions 	 * within the kernel still, in which case entering the monitor doesn't
1397*a1e26a70SApple OSS Distributions 	 * really provide much more security.
1398*a1e26a70SApple OSS Distributions 	 */
1399*a1e26a70SApple OSS Distributions 
1400*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_shared_lock(pmap);
1401*a1e26a70SApple OSS Distributions 	debug_regions_allowed = os_atomic_load(&txm_addr_space->allowsInvalidCode, relaxed);
1402*a1e26a70SApple OSS Distributions 	pmap_txm_release_shared_lock(pmap);
1403*a1e26a70SApple OSS Distributions 
1404*a1e26a70SApple OSS Distributions 	if (debug_regions_allowed == true) {
1405*a1e26a70SApple OSS Distributions 		return KERN_SUCCESS;
1406*a1e26a70SApple OSS Distributions 	}
1407*a1e26a70SApple OSS Distributions 	return KERN_DENIED;
1408*a1e26a70SApple OSS Distributions }
1409*a1e26a70SApple OSS Distributions 
1410*a1e26a70SApple OSS Distributions kern_return_t
txm_associate_debug_region(pmap_t pmap,const vm_address_t region_addr,const vm_size_t region_size)1411*a1e26a70SApple OSS Distributions txm_associate_debug_region(
1412*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1413*a1e26a70SApple OSS Distributions 	const vm_address_t region_addr,
1414*a1e26a70SApple OSS Distributions 	const vm_size_t region_size)
1415*a1e26a70SApple OSS Distributions {
1416*a1e26a70SApple OSS Distributions #if kTXMKernelAPIVersion >= 10
1417*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1418*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAssociateDebugRegion,
1419*a1e26a70SApple OSS Distributions 		.num_input_args = 3,
1420*a1e26a70SApple OSS Distributions 	};
1421*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1422*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1423*a1e26a70SApple OSS Distributions 
1424*a1e26a70SApple OSS Distributions 	/*
1425*a1e26a70SApple OSS Distributions 	 * Associating a debug region may require exclusive access to the TXM address
1426*a1e26a70SApple OSS Distributions 	 * space lock within TXM.
1427*a1e26a70SApple OSS Distributions 	 */
1428*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_exclusive_lock(pmap);
1429*a1e26a70SApple OSS Distributions 
1430*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(
1431*a1e26a70SApple OSS Distributions 		&txm_call,
1432*a1e26a70SApple OSS Distributions 		txm_addr_space,
1433*a1e26a70SApple OSS Distributions 		region_addr,
1434*a1e26a70SApple OSS Distributions 		region_size);
1435*a1e26a70SApple OSS Distributions 
1436*a1e26a70SApple OSS Distributions 	/* Unlock the TXM address space lock */
1437*a1e26a70SApple OSS Distributions 	pmap_txm_release_exclusive_lock(pmap);
1438*a1e26a70SApple OSS Distributions 
1439*a1e26a70SApple OSS Distributions 	return ret;
1440*a1e26a70SApple OSS Distributions #else
1441*a1e26a70SApple OSS Distributions 	/*
1442*a1e26a70SApple OSS Distributions 	 * This function is an interesting one. There is no need for us to make
1443*a1e26a70SApple OSS Distributions 	 * a call into TXM for this one and instead, all we need to do here is
1444*a1e26a70SApple OSS Distributions 	 * to verify that the TXM address space actually allows debug regions to
1445*a1e26a70SApple OSS Distributions 	 * be mapped in or not.
1446*a1e26a70SApple OSS Distributions 	 */
1447*a1e26a70SApple OSS Distributions 	(void)region_addr;
1448*a1e26a70SApple OSS Distributions 	(void)region_size;
1449*a1e26a70SApple OSS Distributions 
1450*a1e26a70SApple OSS Distributions 	kern_return_t ret = txm_address_space_debugged(pmap);
1451*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
1452*a1e26a70SApple OSS Distributions 		printf("address space does not allow creating debug regions\n");
1453*a1e26a70SApple OSS Distributions 	}
1454*a1e26a70SApple OSS Distributions 
1455*a1e26a70SApple OSS Distributions 	return ret;
1456*a1e26a70SApple OSS Distributions #endif
1457*a1e26a70SApple OSS Distributions }
1458*a1e26a70SApple OSS Distributions 
1459*a1e26a70SApple OSS Distributions kern_return_t
txm_allow_invalid_code(pmap_t pmap)1460*a1e26a70SApple OSS Distributions txm_allow_invalid_code(
1461*a1e26a70SApple OSS Distributions 	pmap_t pmap)
1462*a1e26a70SApple OSS Distributions {
1463*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1464*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAllowInvalidCode,
1465*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1466*a1e26a70SApple OSS Distributions 	};
1467*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = pmap_txm_addr_space(pmap);
1468*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1469*a1e26a70SApple OSS Distributions 
1470*a1e26a70SApple OSS Distributions 	/*
1471*a1e26a70SApple OSS Distributions 	 * Allowing invalid code may require exclusive access to the TXM address
1472*a1e26a70SApple OSS Distributions 	 * space lock within TXM.
1473*a1e26a70SApple OSS Distributions 	 */
1474*a1e26a70SApple OSS Distributions 
1475*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_exclusive_lock(pmap);
1476*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, txm_addr_space);
1477*a1e26a70SApple OSS Distributions 	pmap_txm_release_exclusive_lock(pmap);
1478*a1e26a70SApple OSS Distributions 
1479*a1e26a70SApple OSS Distributions 	return ret;
1480*a1e26a70SApple OSS Distributions }
1481*a1e26a70SApple OSS Distributions 
1482*a1e26a70SApple OSS Distributions kern_return_t
txm_get_trust_level_kdp(pmap_t pmap,uint32_t * trust_level)1483*a1e26a70SApple OSS Distributions txm_get_trust_level_kdp(
1484*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1485*a1e26a70SApple OSS Distributions 	uint32_t *trust_level)
1486*a1e26a70SApple OSS Distributions {
1487*a1e26a70SApple OSS Distributions 	CSTrust_t txm_trust_level = kCSTrustUntrusted;
1488*a1e26a70SApple OSS Distributions 
1489*a1e26a70SApple OSS Distributions 	kern_return_t ret = pmap_txm_get_trust_level_kdp(pmap, &txm_trust_level);
1490*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
1491*a1e26a70SApple OSS Distributions 		return ret;
1492*a1e26a70SApple OSS Distributions 	}
1493*a1e26a70SApple OSS Distributions 
1494*a1e26a70SApple OSS Distributions 	if (trust_level != NULL) {
1495*a1e26a70SApple OSS Distributions 		*trust_level = txm_trust_level;
1496*a1e26a70SApple OSS Distributions 	}
1497*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1498*a1e26a70SApple OSS Distributions }
1499*a1e26a70SApple OSS Distributions 
1500*a1e26a70SApple OSS Distributions kern_return_t
txm_get_jit_address_range_kdp(pmap_t pmap,uintptr_t * jit_region_start,uintptr_t * jit_region_end)1501*a1e26a70SApple OSS Distributions txm_get_jit_address_range_kdp(
1502*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1503*a1e26a70SApple OSS Distributions 	uintptr_t *jit_region_start,
1504*a1e26a70SApple OSS Distributions 	uintptr_t *jit_region_end)
1505*a1e26a70SApple OSS Distributions {
1506*a1e26a70SApple OSS Distributions 	return pmap_txm_get_jit_address_range_kdp(pmap, jit_region_start, jit_region_end);
1507*a1e26a70SApple OSS Distributions }
1508*a1e26a70SApple OSS Distributions 
1509*a1e26a70SApple OSS Distributions kern_return_t
txm_address_space_exempt(const pmap_t pmap)1510*a1e26a70SApple OSS Distributions txm_address_space_exempt(
1511*a1e26a70SApple OSS Distributions 	const pmap_t pmap)
1512*a1e26a70SApple OSS Distributions {
1513*a1e26a70SApple OSS Distributions 	if (pmap_performs_stage2_translations(pmap) == true) {
1514*a1e26a70SApple OSS Distributions 		return KERN_SUCCESS;
1515*a1e26a70SApple OSS Distributions 	}
1516*a1e26a70SApple OSS Distributions 
1517*a1e26a70SApple OSS Distributions 	return KERN_DENIED;
1518*a1e26a70SApple OSS Distributions }
1519*a1e26a70SApple OSS Distributions 
1520*a1e26a70SApple OSS Distributions kern_return_t
txm_fork_prepare(pmap_t old_pmap,pmap_t new_pmap)1521*a1e26a70SApple OSS Distributions txm_fork_prepare(
1522*a1e26a70SApple OSS Distributions 	pmap_t old_pmap,
1523*a1e26a70SApple OSS Distributions 	pmap_t new_pmap)
1524*a1e26a70SApple OSS Distributions {
1525*a1e26a70SApple OSS Distributions 	/*
1526*a1e26a70SApple OSS Distributions 	 * We'll add support for this as the need for it becomes more important.
1527*a1e26a70SApple OSS Distributions 	 * TXMTODO: Complete this implementation.
1528*a1e26a70SApple OSS Distributions 	 */
1529*a1e26a70SApple OSS Distributions 	(void)old_pmap;
1530*a1e26a70SApple OSS Distributions 	(void)new_pmap;
1531*a1e26a70SApple OSS Distributions 
1532*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1533*a1e26a70SApple OSS Distributions }
1534*a1e26a70SApple OSS Distributions 
1535*a1e26a70SApple OSS Distributions kern_return_t
txm_acquire_signing_identifier(const void * sig_obj,const char ** signing_id)1536*a1e26a70SApple OSS Distributions txm_acquire_signing_identifier(
1537*a1e26a70SApple OSS Distributions 	const void *sig_obj,
1538*a1e26a70SApple OSS Distributions 	const char **signing_id)
1539*a1e26a70SApple OSS Distributions {
1540*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1541*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAcquireSigningIdentifier,
1542*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1543*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1544*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1545*a1e26a70SApple OSS Distributions 	};
1546*a1e26a70SApple OSS Distributions 
1547*a1e26a70SApple OSS Distributions 	/* Get the signing ID -- should not fail */
1548*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, sig_obj);
1549*a1e26a70SApple OSS Distributions 
1550*a1e26a70SApple OSS Distributions 	if (signing_id != NULL) {
1551*a1e26a70SApple OSS Distributions 		*signing_id = (const char*)txm_call.return_words[0];
1552*a1e26a70SApple OSS Distributions 	}
1553*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1554*a1e26a70SApple OSS Distributions }
1555*a1e26a70SApple OSS Distributions 
1556*a1e26a70SApple OSS Distributions #pragma mark Entitlements
1557*a1e26a70SApple OSS Distributions 
1558*a1e26a70SApple OSS Distributions kern_return_t
txm_associate_kernel_entitlements(void * sig_obj,const void * kernel_entitlements)1559*a1e26a70SApple OSS Distributions txm_associate_kernel_entitlements(
1560*a1e26a70SApple OSS Distributions 	void *sig_obj,
1561*a1e26a70SApple OSS Distributions 	const void *kernel_entitlements)
1562*a1e26a70SApple OSS Distributions {
1563*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1564*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAssociateKernelEntitlements,
1565*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
1566*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1567*a1e26a70SApple OSS Distributions 	};
1568*a1e26a70SApple OSS Distributions 
1569*a1e26a70SApple OSS Distributions 	/* Associate the kernel entitlements -- should not fail */
1570*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, sig_obj, kernel_entitlements);
1571*a1e26a70SApple OSS Distributions 
1572*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1573*a1e26a70SApple OSS Distributions }
1574*a1e26a70SApple OSS Distributions 
1575*a1e26a70SApple OSS Distributions kern_return_t
txm_resolve_kernel_entitlements(pmap_t pmap,const void ** kernel_entitlements)1576*a1e26a70SApple OSS Distributions txm_resolve_kernel_entitlements(
1577*a1e26a70SApple OSS Distributions 	pmap_t pmap,
1578*a1e26a70SApple OSS Distributions 	const void **kernel_entitlements)
1579*a1e26a70SApple OSS Distributions {
1580*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1581*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorResolveKernelEntitlementsAddressSpace,
1582*a1e26a70SApple OSS Distributions 		.skip_logs = true,
1583*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1584*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1585*a1e26a70SApple OSS Distributions 		.failure_silent = true,
1586*a1e26a70SApple OSS Distributions 	};
1587*a1e26a70SApple OSS Distributions 	TXMAddressSpace_t *txm_addr_space = NULL;
1588*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1589*a1e26a70SApple OSS Distributions 
1590*a1e26a70SApple OSS Distributions 	if (pmap == pmap_txm_kernel_pmap()) {
1591*a1e26a70SApple OSS Distributions 		return KERN_NOT_FOUND;
1592*a1e26a70SApple OSS Distributions 	}
1593*a1e26a70SApple OSS Distributions 	txm_addr_space = pmap_txm_addr_space(pmap);
1594*a1e26a70SApple OSS Distributions 
1595*a1e26a70SApple OSS Distributions 	pmap_txm_acquire_shared_lock(pmap);
1596*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, txm_addr_space);
1597*a1e26a70SApple OSS Distributions 	pmap_txm_release_shared_lock(pmap);
1598*a1e26a70SApple OSS Distributions 
1599*a1e26a70SApple OSS Distributions 	if ((ret == KERN_SUCCESS) && (kernel_entitlements != NULL)) {
1600*a1e26a70SApple OSS Distributions 		*kernel_entitlements = (const void*)txm_call.return_words[0];
1601*a1e26a70SApple OSS Distributions 	}
1602*a1e26a70SApple OSS Distributions 	return ret;
1603*a1e26a70SApple OSS Distributions }
1604*a1e26a70SApple OSS Distributions 
1605*a1e26a70SApple OSS Distributions kern_return_t
txm_accelerate_entitlements(void * sig_obj,CEQueryContext_t * ce_ctx)1606*a1e26a70SApple OSS Distributions txm_accelerate_entitlements(
1607*a1e26a70SApple OSS Distributions 	void *sig_obj,
1608*a1e26a70SApple OSS Distributions 	CEQueryContext_t *ce_ctx)
1609*a1e26a70SApple OSS Distributions {
1610*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1611*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorAccelerateEntitlements,
1612*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1613*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1614*a1e26a70SApple OSS Distributions 	};
1615*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1616*a1e26a70SApple OSS Distributions 
1617*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, sig_obj);
1618*a1e26a70SApple OSS Distributions 	if ((ret == KERN_SUCCESS) && (ce_ctx != NULL)) {
1619*a1e26a70SApple OSS Distributions 		*ce_ctx = (CEQueryContext_t)txm_call.return_words[0];
1620*a1e26a70SApple OSS Distributions 	}
1621*a1e26a70SApple OSS Distributions 
1622*a1e26a70SApple OSS Distributions 	return ret;
1623*a1e26a70SApple OSS Distributions }
1624*a1e26a70SApple OSS Distributions 
1625*a1e26a70SApple OSS Distributions #pragma mark Image4
1626*a1e26a70SApple OSS Distributions 
1627*a1e26a70SApple OSS Distributions void*
txm_image4_storage_data(__unused size_t * allocated_size)1628*a1e26a70SApple OSS Distributions txm_image4_storage_data(
1629*a1e26a70SApple OSS Distributions 	__unused size_t *allocated_size)
1630*a1e26a70SApple OSS Distributions {
1631*a1e26a70SApple OSS Distributions 	/*
1632*a1e26a70SApple OSS Distributions 	 * AppleImage4 builds a variant of TXM which TXM should link against statically
1633*a1e26a70SApple OSS Distributions 	 * thereby removing the need for the kernel to allocate some data on behalf of
1634*a1e26a70SApple OSS Distributions 	 * the kernel extension.
1635*a1e26a70SApple OSS Distributions 	 */
1636*a1e26a70SApple OSS Distributions 	panic("unsupported AppleImage4 interface");
1637*a1e26a70SApple OSS Distributions }
1638*a1e26a70SApple OSS Distributions 
1639*a1e26a70SApple OSS Distributions void
txm_image4_set_nonce(const img4_nonce_domain_index_t ndi,const img4_nonce_t * nonce)1640*a1e26a70SApple OSS Distributions txm_image4_set_nonce(
1641*a1e26a70SApple OSS Distributions 	const img4_nonce_domain_index_t ndi,
1642*a1e26a70SApple OSS Distributions 	const img4_nonce_t *nonce)
1643*a1e26a70SApple OSS Distributions {
1644*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1645*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4SetNonce,
1646*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1647*a1e26a70SApple OSS Distributions 		.num_input_args = 2,
1648*a1e26a70SApple OSS Distributions 	};
1649*a1e26a70SApple OSS Distributions 
1650*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, ndi, nonce);
1651*a1e26a70SApple OSS Distributions }
1652*a1e26a70SApple OSS Distributions 
1653*a1e26a70SApple OSS Distributions void
txm_image4_roll_nonce(const img4_nonce_domain_index_t ndi)1654*a1e26a70SApple OSS Distributions txm_image4_roll_nonce(
1655*a1e26a70SApple OSS Distributions 	const img4_nonce_domain_index_t ndi)
1656*a1e26a70SApple OSS Distributions {
1657*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1658*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4RollNonce,
1659*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1660*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1661*a1e26a70SApple OSS Distributions 	};
1662*a1e26a70SApple OSS Distributions 
1663*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, ndi);
1664*a1e26a70SApple OSS Distributions }
1665*a1e26a70SApple OSS Distributions 
1666*a1e26a70SApple OSS Distributions errno_t
txm_image4_copy_nonce(const img4_nonce_domain_index_t ndi,img4_nonce_t * nonce_out)1667*a1e26a70SApple OSS Distributions txm_image4_copy_nonce(
1668*a1e26a70SApple OSS Distributions 	const img4_nonce_domain_index_t ndi,
1669*a1e26a70SApple OSS Distributions 	img4_nonce_t *nonce_out)
1670*a1e26a70SApple OSS Distributions {
1671*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1672*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4GetNonce,
1673*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1674*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1675*a1e26a70SApple OSS Distributions 	};
1676*a1e26a70SApple OSS Distributions 	const img4_nonce_t *nonce = NULL;
1677*a1e26a70SApple OSS Distributions 	TXMReturn_t txm_ret = {0};
1678*a1e26a70SApple OSS Distributions 	kern_return_t ret = KERN_DENIED;
1679*a1e26a70SApple OSS Distributions 
1680*a1e26a70SApple OSS Distributions 	ret = txm_kernel_call(&txm_call, ndi);
1681*a1e26a70SApple OSS Distributions 	if (ret != KERN_SUCCESS) {
1682*a1e26a70SApple OSS Distributions 		txm_ret = txm_call.txm_ret;
1683*a1e26a70SApple OSS Distributions 		if (txm_ret.returnCode != kTXMReturnCodeErrno) {
1684*a1e26a70SApple OSS Distributions 			return EPERM;
1685*a1e26a70SApple OSS Distributions 		}
1686*a1e26a70SApple OSS Distributions 		return txm_ret.errnoRet;
1687*a1e26a70SApple OSS Distributions 	}
1688*a1e26a70SApple OSS Distributions 
1689*a1e26a70SApple OSS Distributions 	/* Acquire a pointer to the nonce from TXM */
1690*a1e26a70SApple OSS Distributions 	nonce = (const img4_nonce_t*)txm_call.return_words[0];
1691*a1e26a70SApple OSS Distributions 
1692*a1e26a70SApple OSS Distributions 	if (nonce_out) {
1693*a1e26a70SApple OSS Distributions 		*nonce_out = *nonce;
1694*a1e26a70SApple OSS Distributions 	}
1695*a1e26a70SApple OSS Distributions 	return 0;
1696*a1e26a70SApple OSS Distributions }
1697*a1e26a70SApple OSS Distributions 
1698*a1e26a70SApple OSS Distributions errno_t
txm_image4_execute_object(img4_runtime_object_spec_index_t obj_spec_index,const img4_buff_t * payload,const img4_buff_t * manifest)1699*a1e26a70SApple OSS Distributions txm_image4_execute_object(
1700*a1e26a70SApple OSS Distributions 	img4_runtime_object_spec_index_t obj_spec_index,
1701*a1e26a70SApple OSS Distributions 	const img4_buff_t *payload,
1702*a1e26a70SApple OSS Distributions 	const img4_buff_t *manifest)
1703*a1e26a70SApple OSS Distributions {
1704*a1e26a70SApple OSS Distributions 	/* Not supported within TXM yet */
1705*a1e26a70SApple OSS Distributions 	(void)obj_spec_index;
1706*a1e26a70SApple OSS Distributions 	(void)payload;
1707*a1e26a70SApple OSS Distributions 	(void)manifest;
1708*a1e26a70SApple OSS Distributions 
1709*a1e26a70SApple OSS Distributions 	printf("image4 object execution isn't supported by TXM\n");
1710*a1e26a70SApple OSS Distributions 	return ENOSYS;
1711*a1e26a70SApple OSS Distributions }
1712*a1e26a70SApple OSS Distributions 
1713*a1e26a70SApple OSS Distributions errno_t
txm_image4_copy_object(img4_runtime_object_spec_index_t obj_spec_index,vm_address_t object_out,size_t * object_length)1714*a1e26a70SApple OSS Distributions txm_image4_copy_object(
1715*a1e26a70SApple OSS Distributions 	img4_runtime_object_spec_index_t obj_spec_index,
1716*a1e26a70SApple OSS Distributions 	vm_address_t object_out,
1717*a1e26a70SApple OSS Distributions 	size_t *object_length)
1718*a1e26a70SApple OSS Distributions {
1719*a1e26a70SApple OSS Distributions 	/* Not supported within TXM yet */
1720*a1e26a70SApple OSS Distributions 	(void)obj_spec_index;
1721*a1e26a70SApple OSS Distributions 	(void)object_out;
1722*a1e26a70SApple OSS Distributions 	(void)object_length;
1723*a1e26a70SApple OSS Distributions 
1724*a1e26a70SApple OSS Distributions 	printf("image4 object copying isn't supported by TXM\n");
1725*a1e26a70SApple OSS Distributions 	return ENOSYS;
1726*a1e26a70SApple OSS Distributions }
1727*a1e26a70SApple OSS Distributions 
1728*a1e26a70SApple OSS Distributions const void*
txm_image4_get_monitor_exports(void)1729*a1e26a70SApple OSS Distributions txm_image4_get_monitor_exports(void)
1730*a1e26a70SApple OSS Distributions {
1731*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1732*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4GetExports,
1733*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1734*a1e26a70SApple OSS Distributions 		.num_output_args = 1,
1735*a1e26a70SApple OSS Distributions 	};
1736*a1e26a70SApple OSS Distributions 
1737*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call);
1738*a1e26a70SApple OSS Distributions 	return (const void*)txm_call.return_words[0];
1739*a1e26a70SApple OSS Distributions }
1740*a1e26a70SApple OSS Distributions 
1741*a1e26a70SApple OSS Distributions errno_t
txm_image4_set_release_type(const char * release_type)1742*a1e26a70SApple OSS Distributions txm_image4_set_release_type(
1743*a1e26a70SApple OSS Distributions 	const char *release_type)
1744*a1e26a70SApple OSS Distributions {
1745*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1746*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4SetReleaseType,
1747*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1748*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1749*a1e26a70SApple OSS Distributions 	};
1750*a1e26a70SApple OSS Distributions 
1751*a1e26a70SApple OSS Distributions 	/* Set the release type -- cannot fail */
1752*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, release_type);
1753*a1e26a70SApple OSS Distributions 
1754*a1e26a70SApple OSS Distributions 	return 0;
1755*a1e26a70SApple OSS Distributions }
1756*a1e26a70SApple OSS Distributions 
1757*a1e26a70SApple OSS Distributions errno_t
txm_image4_set_bnch_shadow(const img4_nonce_domain_index_t ndi)1758*a1e26a70SApple OSS Distributions txm_image4_set_bnch_shadow(
1759*a1e26a70SApple OSS Distributions 	const img4_nonce_domain_index_t ndi)
1760*a1e26a70SApple OSS Distributions {
1761*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1762*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4SetBootNonceShadow,
1763*a1e26a70SApple OSS Distributions 		.failure_fatal = true,
1764*a1e26a70SApple OSS Distributions 		.num_input_args = 1,
1765*a1e26a70SApple OSS Distributions 	};
1766*a1e26a70SApple OSS Distributions 
1767*a1e26a70SApple OSS Distributions 	/* Set the release type -- cannot fail */
1768*a1e26a70SApple OSS Distributions 	txm_kernel_call(&txm_call, ndi);
1769*a1e26a70SApple OSS Distributions 
1770*a1e26a70SApple OSS Distributions 	return 0;
1771*a1e26a70SApple OSS Distributions }
1772*a1e26a70SApple OSS Distributions 
1773*a1e26a70SApple OSS Distributions #pragma mark Image4 - New
1774*a1e26a70SApple OSS Distributions 
1775*a1e26a70SApple OSS Distributions static inline bool
_txm_image4_monitor_trap_supported(image4_cs_trap_t selector)1776*a1e26a70SApple OSS Distributions _txm_image4_monitor_trap_supported(
1777*a1e26a70SApple OSS Distributions 	image4_cs_trap_t selector)
1778*a1e26a70SApple OSS Distributions {
1779*a1e26a70SApple OSS Distributions 	switch (selector) {
1780*a1e26a70SApple OSS Distributions #if kTXMImage4APIVersion >= 1
1781*a1e26a70SApple OSS Distributions 	case IMAGE4_CS_TRAP_KMOD_SET_RELEASE_TYPE:
1782*a1e26a70SApple OSS Distributions 	case IMAGE4_CS_TRAP_NONCE_SET:
1783*a1e26a70SApple OSS Distributions 	case IMAGE4_CS_TRAP_NONCE_ROLL:
1784*a1e26a70SApple OSS Distributions 	case IMAGE4_CS_TRAP_IMAGE_ACTIVATE:
1785*a1e26a70SApple OSS Distributions 		return true;
1786*a1e26a70SApple OSS Distributions #endif
1787*a1e26a70SApple OSS Distributions 
1788*a1e26a70SApple OSS Distributions 	default:
1789*a1e26a70SApple OSS Distributions 		return false;
1790*a1e26a70SApple OSS Distributions 	}
1791*a1e26a70SApple OSS Distributions }
1792*a1e26a70SApple OSS Distributions 
1793*a1e26a70SApple OSS Distributions kern_return_t
txm_image4_transfer_region(image4_cs_trap_t selector,vm_address_t region_addr,vm_size_t region_size)1794*a1e26a70SApple OSS Distributions txm_image4_transfer_region(
1795*a1e26a70SApple OSS Distributions 	image4_cs_trap_t selector,
1796*a1e26a70SApple OSS Distributions 	vm_address_t region_addr,
1797*a1e26a70SApple OSS Distributions 	vm_size_t region_size)
1798*a1e26a70SApple OSS Distributions {
1799*a1e26a70SApple OSS Distributions 	if (_txm_image4_monitor_trap_supported(selector) == true) {
1800*a1e26a70SApple OSS Distributions 		txm_transfer_region(region_addr, region_size);
1801*a1e26a70SApple OSS Distributions 	}
1802*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1803*a1e26a70SApple OSS Distributions }
1804*a1e26a70SApple OSS Distributions 
1805*a1e26a70SApple OSS Distributions kern_return_t
txm_image4_reclaim_region(image4_cs_trap_t selector,vm_address_t region_addr,vm_size_t region_size)1806*a1e26a70SApple OSS Distributions txm_image4_reclaim_region(
1807*a1e26a70SApple OSS Distributions 	image4_cs_trap_t selector,
1808*a1e26a70SApple OSS Distributions 	vm_address_t region_addr,
1809*a1e26a70SApple OSS Distributions 	vm_size_t region_size)
1810*a1e26a70SApple OSS Distributions {
1811*a1e26a70SApple OSS Distributions 	if (_txm_image4_monitor_trap_supported(selector) == true) {
1812*a1e26a70SApple OSS Distributions 		txm_reclaim_region(region_addr, region_size);
1813*a1e26a70SApple OSS Distributions 	}
1814*a1e26a70SApple OSS Distributions 	return KERN_SUCCESS;
1815*a1e26a70SApple OSS Distributions }
1816*a1e26a70SApple OSS Distributions 
1817*a1e26a70SApple OSS Distributions errno_t
txm_image4_monitor_trap(image4_cs_trap_t selector,const void * input_data,size_t input_size)1818*a1e26a70SApple OSS Distributions txm_image4_monitor_trap(
1819*a1e26a70SApple OSS Distributions 	image4_cs_trap_t selector,
1820*a1e26a70SApple OSS Distributions 	const void *input_data,
1821*a1e26a70SApple OSS Distributions 	size_t input_size)
1822*a1e26a70SApple OSS Distributions {
1823*a1e26a70SApple OSS Distributions 	txm_call_t txm_call = {
1824*a1e26a70SApple OSS Distributions 		.selector = kTXMKernelSelectorImage4Dispatch,
1825*a1e26a70SApple OSS Distributions 		.num_input_args = 5,
1826*a1e26a70SApple OSS Distributions 	};
1827*a1e26a70SApple OSS Distributions 
1828*a1e26a70SApple OSS Distributions 	kern_return_t ret = txm_kernel_call(
1829*a1e26a70SApple OSS Distributions 		&txm_call, selector,
1830*a1e26a70SApple OSS Distributions 		input_data, input_size,
1831*a1e26a70SApple OSS Distributions 		NULL, NULL);
1832*a1e26a70SApple OSS Distributions 
1833*a1e26a70SApple OSS Distributions 	/* Return 0 for success */
1834*a1e26a70SApple OSS Distributions 	if (ret == KERN_SUCCESS) {
1835*a1e26a70SApple OSS Distributions 		return 0;
1836*a1e26a70SApple OSS Distributions 	}
1837*a1e26a70SApple OSS Distributions 
1838*a1e26a70SApple OSS Distributions 	/* Check for an errno_t return */
1839*a1e26a70SApple OSS Distributions 	if (txm_call.txm_ret.returnCode == kTXMReturnCodeErrno) {
1840*a1e26a70SApple OSS Distributions 		if (txm_call.txm_ret.errnoRet == 0) {
1841*a1e26a70SApple OSS Distributions 			panic("image4 dispatch: unexpected success errno_t: %llu", selector);
1842*a1e26a70SApple OSS Distributions 		}
1843*a1e26a70SApple OSS Distributions 		return txm_call.txm_ret.errnoRet;
1844*a1e26a70SApple OSS Distributions 	}
1845*a1e26a70SApple OSS Distributions 
1846*a1e26a70SApple OSS Distributions 	/* Return a generic error */
1847*a1e26a70SApple OSS Distributions 	return EPERM;
1848*a1e26a70SApple OSS Distributions }
1849*a1e26a70SApple OSS Distributions 
1850*a1e26a70SApple OSS Distributions #pragma mark Metrics
1851*a1e26a70SApple OSS Distributions 
1852*a1e26a70SApple OSS Distributions #if DEVELOPMENT || DEBUG
1853*a1e26a70SApple OSS Distributions 
1854*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm);
1855*a1e26a70SApple OSS Distributions SYSCTL_NODE(, OID_AUTO, txm, CTLFLAG_RD, 0, "TXM");
1856*a1e26a70SApple OSS Distributions 
1857*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics);
1858*a1e26a70SApple OSS Distributions SYSCTL_NODE(_txm, OID_AUTO, metrics, CTLFLAG_RD, 0, "TXM Metrics");
1859*a1e26a70SApple OSS Distributions 
1860*a1e26a70SApple OSS Distributions #define TXM_METRIC(type, name, field)                                               \
1861*a1e26a70SApple OSS Distributions static int __txm_metric_ ## type ## _ ## name SYSCTL_HANDLER_ARGS;                  \
1862*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics_ ## type);                                                 \
1863*a1e26a70SApple OSS Distributions SYSCTL_PROC(                                                                        \
1864*a1e26a70SApple OSS Distributions 	_txm_metrics_ ## type, OID_AUTO,                                                \
1865*a1e26a70SApple OSS Distributions 	name, CTLTYPE_INT | CTLFLAG_RD,                                                 \
1866*a1e26a70SApple OSS Distributions 	NULL, 0, __txm_metric_ ## type ## _ ## name,                                    \
1867*a1e26a70SApple OSS Distributions 	"I", "collected data from \'" #type "\':\'" #field "\'");                       \
1868*a1e26a70SApple OSS Distributions static int __txm_metric_ ## type ## _ ## name SYSCTL_HANDLER_ARGS                   \
1869*a1e26a70SApple OSS Distributions {                                                                                   \
1870*a1e26a70SApple OSS Distributions 	if (req->newptr) {                                                              \
1871*a1e26a70SApple OSS Distributions 	    return EPERM;                                                               \
1872*a1e26a70SApple OSS Distributions 	}                                                                               \
1873*a1e26a70SApple OSS Distributions 	uint32_t value = os_atomic_load(&txm_metrics->field, relaxed);                  \
1874*a1e26a70SApple OSS Distributions 	return SYSCTL_OUT(req, &value, sizeof(value));                                  \
1875*a1e26a70SApple OSS Distributions }
1876*a1e26a70SApple OSS Distributions 
1877*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics_memory);
1878*a1e26a70SApple OSS Distributions SYSCTL_NODE(_txm_metrics, OID_AUTO, memory, CTLFLAG_RD, 0, "TXM Metrics - Memory");
1879*a1e26a70SApple OSS Distributions 
1880*a1e26a70SApple OSS Distributions #define TXM_ALLOCATOR_METRIC(name, field)                                                   \
1881*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics_memory_ ## name);                                                  \
1882*a1e26a70SApple OSS Distributions SYSCTL_NODE(_txm_metrics_memory, OID_AUTO, name, CTLFLAG_RD, 0, "\'" #name "\' allocator"); \
1883*a1e26a70SApple OSS Distributions TXM_METRIC(memory_ ## name, bytes_allocated, field->allocated);                             \
1884*a1e26a70SApple OSS Distributions TXM_METRIC(memory_ ## name, bytes_unused, field->unused);                                   \
1885*a1e26a70SApple OSS Distributions TXM_METRIC(memory_ ## name, bytes_wasted, field->wasted);                                   \
1886*a1e26a70SApple OSS Distributions 
1887*a1e26a70SApple OSS Distributions TXM_METRIC(memory, bootstrap, memory.bootstrap);
1888*a1e26a70SApple OSS Distributions TXM_METRIC(memory, free_list, memory.freeList);
1889*a1e26a70SApple OSS Distributions TXM_METRIC(memory, bulk_data, memory.bulkData);
1890*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(trust_cache, memory.slabs.trustCache);
1891*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(provisioning_profile, memory.slabs.profile);
1892*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(code_signature, memory.slabs.codeSignature);
1893*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(code_region, memory.slabs.codeRegion);
1894*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(address_space, memory.slabs.addressSpace);
1895*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(bucket_1024, memory.buckets.b1024);
1896*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(bucket_2048, memory.buckets.b2048);
1897*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(bucket_4096, memory.buckets.b4096);
1898*a1e26a70SApple OSS Distributions TXM_ALLOCATOR_METRIC(bucket_8192, memory.buckets.b8192);
1899*a1e26a70SApple OSS Distributions 
1900*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics_acceleration);
1901*a1e26a70SApple OSS Distributions SYSCTL_NODE(_txm_metrics, OID_AUTO, acceleration, CTLFLAG_RD, 0, "TXM Metrics - Acceleration");
1902*a1e26a70SApple OSS Distributions TXM_METRIC(acceleration, num_signature, acceleration.signature);
1903*a1e26a70SApple OSS Distributions TXM_METRIC(acceleration, num_bucket, acceleration.bucket);
1904*a1e26a70SApple OSS Distributions TXM_METRIC(acceleration, num_page, acceleration.page);
1905*a1e26a70SApple OSS Distributions TXM_METRIC(acceleration, bucket_256, acceleration.bucket256);
1906*a1e26a70SApple OSS Distributions TXM_METRIC(acceleration, unsupported, acceleration.large);
1907*a1e26a70SApple OSS Distributions 
1908*a1e26a70SApple OSS Distributions SYSCTL_DECL(_txm_metrics_trustcaches);
1909*a1e26a70SApple OSS Distributions SYSCTL_NODE(_txm_metrics, OID_AUTO, trustcaches, CTLFLAG_RD, 0, "TXM Metrics - Trust Caches");
1910*a1e26a70SApple OSS Distributions TXM_METRIC(trustcaches, bytes_needed, trustCaches.bytesNeeded);
1911*a1e26a70SApple OSS Distributions TXM_METRIC(trustcaches, bytes_allocated, trustCaches.bytesAllocated);
1912*a1e26a70SApple OSS Distributions TXM_METRIC(trustcaches, bytes_locked, trustCaches.bytesLocked);
1913*a1e26a70SApple OSS Distributions TXM_METRIC(trustcaches, bytes_tombstoned, trustCaches.bytesTombstoned);
1914*a1e26a70SApple OSS Distributions 
1915*a1e26a70SApple OSS Distributions #endif /* DEVELOPMENT || DEBUG */
1916*a1e26a70SApple OSS Distributions 
1917*a1e26a70SApple OSS Distributions 
1918*a1e26a70SApple OSS Distributions #endif /* CONFIG_SPTM */
1919