xref: /xnu-11215.61.5/osfmk/vm/vm_shared_region.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1 /*
2  * Copyright (c) 2007-2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. Please obtain a copy of the License at
10  * http://www.opensource.apple.com/apsl/ and read it before using this
11  * file.
12  *
13  * The Original Code and all software distributed under the License are
14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18  * Please see the License for the specific language governing rights and
19  * limitations under the License.
20  *
21  * @APPLE_LICENSE_HEADER_END@
22  */
23 
24 /*
25  * Shared region (... and comm page)
26  *
27  * This file handles the VM shared region and comm page.
28  *
29  */
30 /*
31  * SHARED REGIONS
32  * --------------
33  *
34  * A shared region is a submap that contains the most common system shared
35  * libraries for a given environment which is defined by:
36  * - cpu-type
37  * - 64-bitness
38  * - root directory
39  * - Team ID - when we have pointer authentication.
40  *
41  * The point of a shared region is to reduce the setup overhead when exec'ing
42  * a new process. A shared region uses a shared VM submap that gets mapped
43  * automatically at exec() time, see vm_map_exec().  The first process of a given
44  * environment sets up the shared region and all further processes in that
45  * environment can re-use that shared region without having to re-create
46  * the same mappings in their VM map.  All they need is contained in the shared
47  * region.
48  *
49  * The region can also share a pmap (mostly for read-only parts but also for the
50  * initial version of some writable parts), which gets "nested" into the
51  * process's pmap.  This reduces the number of soft faults:  once one process
52  * brings in a page in the shared region, all the other processes can access
53  * it without having to enter it in their own pmap.
54  *
55  * When a process is being exec'ed, vm_map_exec() calls vm_shared_region_enter()
56  * to map the appropriate shared region in the process's address space.
57  * We look up the appropriate shared region for the process's environment.
58  * If we can't find one, we create a new (empty) one and add it to the list.
59  * Otherwise, we just take an extra reference on the shared region we found.
60  *
61  * The "dyld" runtime, mapped into the process's address space at exec() time,
62  * will then use the shared_region_check_np() and shared_region_map_and_slide_2_np()
63  * system calls to validate and/or populate the shared region with the
64  * appropriate dyld_shared_cache file.
65  *
66  * The shared region is inherited on fork() and the child simply takes an
67  * extra reference on its parent's shared region.
68  *
69  * When the task terminates, we release the reference on its shared region.
70  * When the last reference is released, we destroy the shared region.
71  *
72  * After a chroot(), the calling process keeps using its original shared region,
73  * since that's what was mapped when it was started.  But its children
74  * will use a different shared region, because they need to use the shared
75  * cache that's relative to the new root directory.
76  */
77 
78 /*
79  * COMM PAGE
80  *
81  * A "comm page" is an area of memory that is populated by the kernel with
82  * the appropriate platform-specific version of some commonly used code.
83  * There is one "comm page" per platform (cpu-type, 64-bitness) but only
84  * for the native cpu-type.  No need to overly optimize translated code
85  * for hardware that is not really there !
86  *
87  * The comm pages are created and populated at boot time.
88  *
89  * The appropriate comm page is mapped into a process's address space
90  * at exec() time, in vm_map_exec(). It is then inherited on fork().
91  *
92  * The comm page is shared between the kernel and all applications of
93  * a given platform. Only the kernel can modify it.
94  *
95  * Applications just branch to fixed addresses in the comm page and find
96  * the right version of the code for the platform.  There is also some
97  * data provided and updated by the kernel for processes to retrieve easily
98  * without having to do a system call.
99  */
100 
101 #include <debug.h>
102 
103 #include <kern/ipc_tt.h>
104 #include <kern/kalloc.h>
105 #include <kern/thread_call.h>
106 
107 #include <mach/mach_vm.h>
108 #include <mach/machine.h>
109 
110 #include <vm/vm_map_internal.h>
111 #include <vm/vm_memory_entry_xnu.h>
112 #include <vm/vm_shared_region_internal.h>
113 #include <vm/vm_kern_xnu.h>
114 #include <vm/memory_object_internal.h>
115 #include <vm/vm_protos_internal.h>
116 #include <vm/vm_object_internal.h>
117 
118 #include <machine/commpage.h>
119 #include <machine/cpu_capabilities.h>
120 #include <sys/random.h>
121 #include <sys/errno.h>
122 
123 #if defined(__arm64__)
124 #include <arm/cpu_data_internal.h>
125 #include <arm/misc_protos.h>
126 #endif
127 
128 /*
129  * the following codes are used in the  subclass
130  * of the DBG_MACH_SHAREDREGION class
131  */
132 #define PROCESS_SHARED_CACHE_LAYOUT 0x00
133 
134 #if __has_feature(ptrauth_calls)
135 #include <ptrauth.h>
136 #endif /* __has_feature(ptrauth_calls) */
137 
138 /* "dyld" uses this to figure out what the kernel supports */
139 int shared_region_version = 3;
140 
141 /* trace level, output is sent to the system log file */
142 int shared_region_trace_level = SHARED_REGION_TRACE_ERROR_LVL;
143 
144 /* should local (non-chroot) shared regions persist when no task uses them ? */
145 int shared_region_persistence = 0;      /* no by default */
146 
147 
148 /* delay in seconds before reclaiming an unused shared region */
149 TUNABLE_WRITEABLE(int, shared_region_destroy_delay, "vm_shared_region_destroy_delay", 120);
150 
151 /*
152  * Cached pointer to the most recently mapped shared region from PID 1, which should
153  * be the most commonly mapped shared region in the system.  There are many processes
154  * which do not use this, for a variety of reasons.
155  *
156  * The main consumer of this is stackshot.
157  */
158 struct vm_shared_region *primary_system_shared_region = NULL;
159 
160 #if XNU_TARGET_OS_OSX
161 /*
162  * Only one cache gets to slide on Desktop, since we can't
163  * tear down slide info properly today and the desktop actually
164  * produces lots of shared caches.
165  */
166 boolean_t shared_region_completed_slide = FALSE;
167 #endif /* XNU_TARGET_OS_OSX */
168 
169 /* this lock protects all the shared region data structures */
170 static LCK_GRP_DECLARE(vm_shared_region_lck_grp, "vm shared region");
171 static LCK_MTX_DECLARE(vm_shared_region_lock, &vm_shared_region_lck_grp);
172 
173 #define vm_shared_region_lock() lck_mtx_lock(&vm_shared_region_lock)
174 #define vm_shared_region_unlock() lck_mtx_unlock(&vm_shared_region_lock)
175 #define vm_shared_region_sleep(event, interruptible)                    \
176 	lck_mtx_sleep_with_inheritor(&vm_shared_region_lock,            \
177 	              LCK_SLEEP_DEFAULT,                                \
178 	              (event_t) (event),                                \
179 	              *(event),                                         \
180 	              (interruptible) | THREAD_WAIT_NOREPORT,           \
181 	              TIMEOUT_WAIT_FOREVER)
182 #define vm_shared_region_wakeup(event)                                  \
183 	wakeup_all_with_inheritor((event), THREAD_AWAKENED)
184 
185 /* the list of currently available shared regions (one per environment) */
186 queue_head_t    vm_shared_region_queue = QUEUE_HEAD_INITIALIZER(vm_shared_region_queue);
187 int             vm_shared_region_count = 0;
188 int             vm_shared_region_peak = 0;
189 static uint32_t vm_shared_region_lastid = 0; /* for sr_id field */
190 
191 /*
192  * the number of times an event has forced the recalculation of the reslide
193  * shared region slide.
194  */
195 #if __has_feature(ptrauth_calls)
196 int                             vm_shared_region_reslide_count = 0;
197 #endif /* __has_feature(ptrauth_calls) */
198 
199 static void vm_shared_region_reference_locked(vm_shared_region_t shared_region);
200 static vm_shared_region_t vm_shared_region_create(
201 	void          *root_dir,
202 	cpu_type_t    cputype,
203 	cpu_subtype_t cpu_subtype,
204 	boolean_t     is_64bit,
205 	int           target_page_shift,
206 	boolean_t     reslide,
207 	boolean_t     is_driverkit,
208 	uint32_t      rsr_version);
209 static void vm_shared_region_destroy(vm_shared_region_t shared_region);
210 
211 static kern_return_t vm_shared_region_slide_sanity_check(vm_shared_region_slide_info_entry_t entry, mach_vm_size_t size);
212 static void vm_shared_region_timeout(thread_call_param_t param0,
213     thread_call_param_t param1);
214 static kern_return_t vm_shared_region_slide_mapping(
215 	vm_shared_region_t sr,
216 	user_addr_t        slide_info_addr,
217 	mach_vm_size_t     slide_info_size,
218 	mach_vm_offset_t   start,
219 	mach_vm_size_t     size,
220 	mach_vm_offset_t   slid_mapping,
221 	uint32_t           slide,
222 	memory_object_control_t,
223 	vm_prot_t          prot); /* forward */
224 
225 static int __commpage_setup = 0;
226 #if XNU_TARGET_OS_OSX
227 static int __system_power_source = 1;   /* init to extrnal power source */
228 static void post_sys_powersource_internal(int i, int internal);
229 #endif /* XNU_TARGET_OS_OSX */
230 
231 extern u_int32_t random(void);
232 
233 /*
234  * Retrieve a task's shared region and grab an extra reference to
235  * make sure it doesn't disappear while the caller is using it.
236  * The caller is responsible for consuming that extra reference if
237  * necessary.
238  */
239 vm_shared_region_t
vm_shared_region_get(task_t task)240 vm_shared_region_get(
241 	task_t          task)
242 {
243 	vm_shared_region_t      shared_region;
244 
245 	SHARED_REGION_TRACE_DEBUG(
246 		("shared_region: -> get(%p)\n",
247 		(void *)VM_KERNEL_ADDRPERM(task)));
248 
249 	task_lock(task);
250 	vm_shared_region_lock();
251 	shared_region = task->shared_region;
252 	if (shared_region) {
253 		assert(shared_region->sr_ref_count > 0);
254 		vm_shared_region_reference_locked(shared_region);
255 	}
256 	vm_shared_region_unlock();
257 	task_unlock(task);
258 
259 	SHARED_REGION_TRACE_DEBUG(
260 		("shared_region: get(%p) <- %p\n",
261 		(void *)VM_KERNEL_ADDRPERM(task),
262 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
263 
264 	return shared_region;
265 }
266 
267 vm_map_t
vm_shared_region_vm_map(vm_shared_region_t shared_region)268 vm_shared_region_vm_map(
269 	vm_shared_region_t      shared_region)
270 {
271 	ipc_port_t              sr_handle;
272 	vm_named_entry_t        sr_mem_entry;
273 	vm_map_t                sr_map;
274 
275 	SHARED_REGION_TRACE_DEBUG(
276 		("shared_region: -> vm_map(%p)\n",
277 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
278 	assert(shared_region->sr_ref_count > 0);
279 
280 	sr_handle = shared_region->sr_mem_entry;
281 	sr_mem_entry = mach_memory_entry_from_port(sr_handle);
282 	sr_map = sr_mem_entry->backing.map;
283 	assert(sr_mem_entry->is_sub_map);
284 
285 	SHARED_REGION_TRACE_DEBUG(
286 		("shared_region: vm_map(%p) <- %p\n",
287 		(void *)VM_KERNEL_ADDRPERM(shared_region),
288 		(void *)VM_KERNEL_ADDRPERM(sr_map)));
289 	return sr_map;
290 }
291 
292 /*
293  * Set the shared region the process should use.
294  * A NULL new shared region means that we just want to release the old
295  * shared region.
296  * The caller should already have an extra reference on the new shared region
297  * (if any).  We release a reference on the old shared region (if any).
298  */
299 void
vm_shared_region_set(task_t task,vm_shared_region_t new_shared_region)300 vm_shared_region_set(
301 	task_t                  task,
302 	vm_shared_region_t      new_shared_region)
303 {
304 	vm_shared_region_t      old_shared_region;
305 
306 	SHARED_REGION_TRACE_DEBUG(
307 		("shared_region: -> set(%p, %p)\n",
308 		(void *)VM_KERNEL_ADDRPERM(task),
309 		(void *)VM_KERNEL_ADDRPERM(new_shared_region)));
310 
311 	task_lock(task);
312 	vm_shared_region_lock();
313 
314 	old_shared_region = task->shared_region;
315 	if (new_shared_region) {
316 		assert(new_shared_region->sr_ref_count > 0);
317 	}
318 
319 	task->shared_region = new_shared_region;
320 
321 	vm_shared_region_unlock();
322 	task_unlock(task);
323 
324 	if (old_shared_region) {
325 		assert(old_shared_region->sr_ref_count > 0);
326 		vm_shared_region_deallocate(old_shared_region);
327 	}
328 
329 	SHARED_REGION_TRACE_DEBUG(
330 		("shared_region: set(%p) <- old=%p new=%p\n",
331 		(void *)VM_KERNEL_ADDRPERM(task),
332 		(void *)VM_KERNEL_ADDRPERM(old_shared_region),
333 		(void *)VM_KERNEL_ADDRPERM(new_shared_region)));
334 }
335 
336 /*
337  * New arm64 shared regions match with an existing arm64e region.
338  * They just get a private non-authenticating pager.
339  */
340 static inline bool
match_subtype(cpu_type_t cputype,cpu_subtype_t exist,cpu_subtype_t new)341 match_subtype(cpu_type_t cputype, cpu_subtype_t exist, cpu_subtype_t new)
342 {
343 	if (exist == new) {
344 		return true;
345 	}
346 	if (cputype == CPU_TYPE_ARM64 &&
347 	    exist == CPU_SUBTYPE_ARM64E &&
348 	    new == CPU_SUBTYPE_ARM64_ALL) {
349 		return true;
350 	}
351 	return false;
352 }
353 
354 
355 /*
356  * Lookup up the shared region for the desired environment.
357  * If none is found, create a new (empty) one.
358  * Grab an extra reference on the returned shared region, to make sure
359  * it doesn't get destroyed before the caller is done with it.  The caller
360  * is responsible for consuming that extra reference if necessary.
361  */
362 vm_shared_region_t
vm_shared_region_lookup(void * root_dir,cpu_type_t cputype,cpu_subtype_t cpu_subtype,boolean_t is_64bit,int target_page_shift,boolean_t reslide,boolean_t is_driverkit,uint32_t rsr_version)363 vm_shared_region_lookup(
364 	void            *root_dir,
365 	cpu_type_t      cputype,
366 	cpu_subtype_t   cpu_subtype,
367 	boolean_t       is_64bit,
368 	int             target_page_shift,
369 	boolean_t       reslide,
370 	boolean_t       is_driverkit,
371 	uint32_t        rsr_version)
372 {
373 	vm_shared_region_t      shared_region;
374 	vm_shared_region_t      new_shared_region;
375 
376 	SHARED_REGION_TRACE_DEBUG(
377 		("shared_region: -> lookup(root=%p,cpu=<%d,%d>,64bit=%d,pgshift=%d,reslide=%d,driverkit=%d)\n",
378 		(void *)VM_KERNEL_ADDRPERM(root_dir),
379 		cputype, cpu_subtype, is_64bit, target_page_shift,
380 		reslide, is_driverkit));
381 
382 	shared_region = NULL;
383 	new_shared_region = NULL;
384 
385 	vm_shared_region_lock();
386 	for (;;) {
387 		queue_iterate(&vm_shared_region_queue,
388 		    shared_region,
389 		    vm_shared_region_t,
390 		    sr_q) {
391 			assert(shared_region->sr_ref_count > 0);
392 			if (shared_region->sr_cpu_type == cputype &&
393 			    match_subtype(cputype, shared_region->sr_cpu_subtype, cpu_subtype) &&
394 			    shared_region->sr_root_dir == root_dir &&
395 			    shared_region->sr_64bit == is_64bit &&
396 #if __ARM_MIXED_PAGE_SIZE__
397 			    shared_region->sr_page_shift == target_page_shift &&
398 #endif /* __ARM_MIXED_PAGE_SIZE__ */
399 #if __has_feature(ptrauth_calls)
400 			    shared_region->sr_reslide == reslide &&
401 #endif /* __has_feature(ptrauth_calls) */
402 			    shared_region->sr_driverkit == is_driverkit &&
403 			    shared_region->sr_rsr_version == rsr_version &&
404 			    !shared_region->sr_stale) {
405 				/* found a match ! */
406 				vm_shared_region_reference_locked(shared_region);
407 				goto done;
408 			}
409 		}
410 		if (new_shared_region == NULL) {
411 			/* no match: create a new one */
412 			vm_shared_region_unlock();
413 			new_shared_region = vm_shared_region_create(root_dir,
414 			    cputype,
415 			    cpu_subtype,
416 			    is_64bit,
417 			    target_page_shift,
418 			    reslide,
419 			    is_driverkit,
420 			    rsr_version);
421 			/* do the lookup again, in case we lost a race */
422 			vm_shared_region_lock();
423 			continue;
424 		}
425 		/* still no match: use our new one */
426 		shared_region = new_shared_region;
427 		new_shared_region = NULL;
428 		uint32_t newid = ++vm_shared_region_lastid;
429 		if (newid == 0) {
430 			panic("shared_region: vm_shared_region_lastid wrapped");
431 		}
432 		shared_region->sr_id = newid;
433 		shared_region->sr_install_time = mach_absolute_time();
434 		queue_enter(&vm_shared_region_queue,
435 		    shared_region,
436 		    vm_shared_region_t,
437 		    sr_q);
438 		vm_shared_region_count++;
439 		if (vm_shared_region_count > vm_shared_region_peak) {
440 			vm_shared_region_peak = vm_shared_region_count;
441 		}
442 		break;
443 	}
444 
445 done:
446 	vm_shared_region_unlock();
447 
448 	if (new_shared_region) {
449 		/*
450 		 * We lost a race with someone else to create a new shared
451 		 * region for that environment. Get rid of our unused one.
452 		 */
453 		assert(new_shared_region->sr_ref_count == 1);
454 		new_shared_region->sr_ref_count--;
455 		vm_shared_region_destroy(new_shared_region);
456 		new_shared_region = NULL;
457 	}
458 
459 	SHARED_REGION_TRACE_DEBUG(
460 		("shared_region: lookup(root=%p,cpu=<%d,%d>,64bit=%d,pgshift=%d,reslide=%d,driverkit=%d) <- %p\n",
461 		(void *)VM_KERNEL_ADDRPERM(root_dir),
462 		cputype, cpu_subtype, is_64bit, target_page_shift,
463 		reslide, is_driverkit,
464 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
465 
466 	assert(shared_region->sr_ref_count > 0);
467 	return shared_region;
468 }
469 
470 /*
471  * Take an extra reference on a shared region.
472  * The vm_shared_region_lock should already be held by the caller.
473  */
474 static void
vm_shared_region_reference_locked(vm_shared_region_t shared_region)475 vm_shared_region_reference_locked(
476 	vm_shared_region_t      shared_region)
477 {
478 	LCK_MTX_ASSERT(&vm_shared_region_lock, LCK_MTX_ASSERT_OWNED);
479 
480 	SHARED_REGION_TRACE_DEBUG(
481 		("shared_region: -> reference_locked(%p)\n",
482 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
483 	assert(shared_region->sr_ref_count > 0);
484 	shared_region->sr_ref_count++;
485 	assert(shared_region->sr_ref_count != 0);
486 
487 	if (shared_region->sr_timer_call != NULL) {
488 		boolean_t cancelled;
489 
490 		/* cancel and free any pending timeout */
491 		cancelled = thread_call_cancel(shared_region->sr_timer_call);
492 		if (cancelled) {
493 			thread_call_free(shared_region->sr_timer_call);
494 			shared_region->sr_timer_call = NULL;
495 			/* release the reference held by the cancelled timer */
496 			shared_region->sr_ref_count--;
497 		} else {
498 			/* the timer will drop the reference and free itself */
499 		}
500 	}
501 
502 	SHARED_REGION_TRACE_DEBUG(
503 		("shared_region: reference_locked(%p) <- %d\n",
504 		(void *)VM_KERNEL_ADDRPERM(shared_region),
505 		shared_region->sr_ref_count));
506 }
507 
508 /*
509  * Take a reference on a shared region.
510  */
511 void
vm_shared_region_reference(vm_shared_region_t shared_region)512 vm_shared_region_reference(vm_shared_region_t shared_region)
513 {
514 	SHARED_REGION_TRACE_DEBUG(
515 		("shared_region: -> reference(%p)\n",
516 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
517 
518 	vm_shared_region_lock();
519 	vm_shared_region_reference_locked(shared_region);
520 	vm_shared_region_unlock();
521 
522 	SHARED_REGION_TRACE_DEBUG(
523 		("shared_region: reference(%p) <- %d\n",
524 		(void *)VM_KERNEL_ADDRPERM(shared_region),
525 		shared_region->sr_ref_count));
526 }
527 
528 /*
529  * Release a reference on the shared region.
530  * Destroy it if there are no references left.
531  */
532 void
vm_shared_region_deallocate(vm_shared_region_t shared_region)533 vm_shared_region_deallocate(
534 	vm_shared_region_t      shared_region)
535 {
536 	SHARED_REGION_TRACE_DEBUG(
537 		("shared_region: -> deallocate(%p)\n",
538 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
539 
540 	vm_shared_region_lock();
541 
542 	assert(shared_region->sr_ref_count > 0);
543 
544 	if (shared_region->sr_root_dir == NULL) {
545 		/*
546 		 * Local (i.e. based on the boot volume) shared regions
547 		 * can persist or not based on the "shared_region_persistence"
548 		 * sysctl.
549 		 * Make sure that this one complies.
550 		 *
551 		 * See comments in vm_shared_region_slide() for notes about
552 		 * shared regions we have slid (which are not torn down currently).
553 		 */
554 		if (shared_region_persistence &&
555 		    !shared_region->sr_persists) {
556 			/* make this one persistent */
557 			shared_region->sr_ref_count++;
558 			shared_region->sr_persists = TRUE;
559 		} else if (!shared_region_persistence &&
560 		    shared_region->sr_persists) {
561 			/* make this one no longer persistent */
562 			assert(shared_region->sr_ref_count > 1);
563 			shared_region->sr_ref_count--;
564 			shared_region->sr_persists = FALSE;
565 		}
566 	}
567 
568 	assert(shared_region->sr_ref_count > 0);
569 	shared_region->sr_ref_count--;
570 	SHARED_REGION_TRACE_DEBUG(
571 		("shared_region: deallocate(%p): ref now %d\n",
572 		(void *)VM_KERNEL_ADDRPERM(shared_region),
573 		shared_region->sr_ref_count));
574 
575 	if (shared_region->sr_ref_count == 0) {
576 		uint64_t deadline;
577 
578 		/*
579 		 * Even though a shared region is unused, delay a while before
580 		 * tearing it down, in case a new app launch can use it.
581 		 * We don't keep around stale shared regions, nor older RSR ones.
582 		 */
583 		if (shared_region->sr_timer_call == NULL &&
584 		    shared_region_destroy_delay != 0 &&
585 		    !shared_region->sr_stale &&
586 		    !(shared_region->sr_rsr_version != 0 &&
587 		    shared_region->sr_rsr_version != rsr_get_version())) {
588 			/* hold one reference for the timer */
589 			assert(!shared_region->sr_mapping_in_progress);
590 			shared_region->sr_ref_count++;
591 
592 			/* set up the timer */
593 			shared_region->sr_timer_call = thread_call_allocate(
594 				(thread_call_func_t) vm_shared_region_timeout,
595 				(thread_call_param_t) shared_region);
596 
597 			/* schedule the timer */
598 			clock_interval_to_deadline(shared_region_destroy_delay,
599 			    NSEC_PER_SEC,
600 			    &deadline);
601 			thread_call_enter_delayed(shared_region->sr_timer_call,
602 			    deadline);
603 
604 			SHARED_REGION_TRACE_DEBUG(
605 				("shared_region: deallocate(%p): armed timer\n",
606 				(void *)VM_KERNEL_ADDRPERM(shared_region)));
607 
608 			vm_shared_region_unlock();
609 		} else {
610 			/* timer expired: let go of this shared region */
611 
612 			/* Make sure there's no cached pointer to the region. */
613 			if (primary_system_shared_region == shared_region) {
614 				primary_system_shared_region = NULL;
615 			}
616 
617 			/*
618 			 * Remove it from the queue first, so no one can find
619 			 * it...
620 			 */
621 			queue_remove(&vm_shared_region_queue,
622 			    shared_region,
623 			    vm_shared_region_t,
624 			    sr_q);
625 			vm_shared_region_count--;
626 			vm_shared_region_unlock();
627 
628 			/* ... and destroy it */
629 			vm_shared_region_destroy(shared_region);
630 			shared_region = NULL;
631 		}
632 	} else {
633 		vm_shared_region_unlock();
634 	}
635 
636 	SHARED_REGION_TRACE_DEBUG(
637 		("shared_region: deallocate(%p) <-\n",
638 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
639 }
640 
641 void
vm_shared_region_timeout(thread_call_param_t param0,__unused thread_call_param_t param1)642 vm_shared_region_timeout(
643 	thread_call_param_t     param0,
644 	__unused thread_call_param_t    param1)
645 {
646 	vm_shared_region_t      shared_region;
647 
648 	shared_region = (vm_shared_region_t) param0;
649 
650 	vm_shared_region_deallocate(shared_region);
651 }
652 
653 
654 /*
655  * Create a new (empty) shared region for a new environment.
656  */
657 static vm_shared_region_t
vm_shared_region_create(void * root_dir,cpu_type_t cputype,cpu_subtype_t cpu_subtype,boolean_t is_64bit,int target_page_shift,__unused boolean_t reslide,boolean_t is_driverkit,uint32_t rsr_version)658 vm_shared_region_create(
659 	void                    *root_dir,
660 	cpu_type_t              cputype,
661 	cpu_subtype_t           cpu_subtype,
662 	boolean_t               is_64bit,
663 	int                     target_page_shift,
664 #if !__has_feature(ptrauth_calls)
665 	__unused
666 #endif /* __has_feature(ptrauth_calls) */
667 	boolean_t               reslide,
668 	boolean_t               is_driverkit,
669 	uint32_t                rsr_version)
670 {
671 	vm_named_entry_t        mem_entry;
672 	ipc_port_t              mem_entry_port;
673 	vm_shared_region_t      shared_region;
674 	vm_map_t                sub_map;
675 	mach_vm_offset_t        base_address, pmap_nesting_start;
676 	mach_vm_size_t          size, pmap_nesting_size;
677 
678 	SHARED_REGION_TRACE_INFO(
679 		("shared_region: -> create(root=%p,cpu=<%d,%d>,64bit=%d,pgshift=%d,reslide=%d,driverkit=%d)\n",
680 		(void *)VM_KERNEL_ADDRPERM(root_dir),
681 		cputype, cpu_subtype, is_64bit, target_page_shift,
682 		reslide, is_driverkit));
683 
684 	base_address = 0;
685 	size = 0;
686 	mem_entry = NULL;
687 	mem_entry_port = IPC_PORT_NULL;
688 	sub_map = VM_MAP_NULL;
689 
690 	/* create a new shared region structure... */
691 	shared_region = kalloc_type(struct vm_shared_region,
692 	    Z_WAITOK | Z_NOFAIL);
693 
694 	/* figure out the correct settings for the desired environment */
695 	if (is_64bit) {
696 		switch (cputype) {
697 #if defined(__arm64__)
698 		case CPU_TYPE_ARM64:
699 			base_address = SHARED_REGION_BASE_ARM64;
700 			size = SHARED_REGION_SIZE_ARM64;
701 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_ARM64;
702 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_ARM64;
703 			break;
704 #else
705 		case CPU_TYPE_I386:
706 			base_address = SHARED_REGION_BASE_X86_64;
707 			size = SHARED_REGION_SIZE_X86_64;
708 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_X86_64;
709 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_X86_64;
710 			break;
711 		case CPU_TYPE_POWERPC:
712 			base_address = SHARED_REGION_BASE_PPC64;
713 			size = SHARED_REGION_SIZE_PPC64;
714 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_PPC64;
715 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_PPC64;
716 			break;
717 #endif
718 		default:
719 			SHARED_REGION_TRACE_ERROR(
720 				("shared_region: create: unknown cpu type %d\n",
721 				cputype));
722 			kfree_type(struct vm_shared_region, shared_region);
723 			shared_region = NULL;
724 			goto done;
725 		}
726 	} else {
727 		switch (cputype) {
728 #if defined(__arm64__)
729 		case CPU_TYPE_ARM:
730 			base_address = SHARED_REGION_BASE_ARM;
731 			size = SHARED_REGION_SIZE_ARM;
732 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_ARM;
733 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_ARM;
734 			break;
735 #else
736 		case CPU_TYPE_I386:
737 			base_address = SHARED_REGION_BASE_I386;
738 			size = SHARED_REGION_SIZE_I386;
739 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_I386;
740 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_I386;
741 			break;
742 		case CPU_TYPE_POWERPC:
743 			base_address = SHARED_REGION_BASE_PPC;
744 			size = SHARED_REGION_SIZE_PPC;
745 			pmap_nesting_start = SHARED_REGION_NESTING_BASE_PPC;
746 			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_PPC;
747 			break;
748 #endif
749 		default:
750 			SHARED_REGION_TRACE_ERROR(
751 				("shared_region: create: unknown cpu type %d\n",
752 				cputype));
753 			kfree_type(struct vm_shared_region, shared_region);
754 			shared_region = NULL;
755 			goto done;
756 		}
757 	}
758 
759 	/* create a memory entry structure and a Mach port handle */
760 	mem_entry = mach_memory_entry_allocate(&mem_entry_port);
761 
762 #if defined(__arm64__)
763 	{
764 		struct pmap *pmap_nested;
765 		int pmap_flags = 0;
766 		pmap_flags |= is_64bit ? PMAP_CREATE_64BIT : 0;
767 
768 
769 #if __ARM_MIXED_PAGE_SIZE__
770 		if (cputype == CPU_TYPE_ARM64 &&
771 		    target_page_shift == FOURK_PAGE_SHIFT) {
772 			/* arm64/4k address space */
773 			pmap_flags |= PMAP_CREATE_FORCE_4K_PAGES;
774 		}
775 #endif /* __ARM_MIXED_PAGE_SIZE__ */
776 
777 		pmap_nested = pmap_create_options(NULL, 0, pmap_flags);
778 		if (pmap_nested != PMAP_NULL) {
779 			pmap_set_nested(pmap_nested);
780 			sub_map = vm_map_create_options(pmap_nested, 0,
781 			    (vm_map_offset_t)size, VM_MAP_CREATE_PAGEABLE);
782 
783 			if (is_64bit ||
784 			    page_shift_user32 == SIXTEENK_PAGE_SHIFT) {
785 				/* enforce 16KB alignment of VM map entries */
786 				vm_map_set_page_shift(sub_map, SIXTEENK_PAGE_SHIFT);
787 			}
788 #if __ARM_MIXED_PAGE_SIZE__
789 			if (cputype == CPU_TYPE_ARM64 &&
790 			    target_page_shift == FOURK_PAGE_SHIFT) {
791 				/* arm64/4k address space */
792 				vm_map_set_page_shift(sub_map, FOURK_PAGE_SHIFT);
793 			}
794 #endif /* __ARM_MIXED_PAGE_SIZE__ */
795 		} else {
796 			sub_map = VM_MAP_NULL;
797 		}
798 	}
799 #else /* defined(__arm64__) */
800 	{
801 		/* create a VM sub map and its pmap */
802 		pmap_t pmap = pmap_create_options(NULL, 0, is_64bit);
803 		if (pmap != NULL) {
804 			sub_map = vm_map_create_options(pmap, 0,
805 			    (vm_map_offset_t)size, VM_MAP_CREATE_PAGEABLE);
806 		} else {
807 			sub_map = VM_MAP_NULL;
808 		}
809 	}
810 #endif /* defined(__arm64__) */
811 	if (sub_map == VM_MAP_NULL) {
812 		ipc_port_release_send(mem_entry_port);
813 		kfree_type(struct vm_shared_region, shared_region);
814 		shared_region = NULL;
815 		SHARED_REGION_TRACE_ERROR(("shared_region: create: couldn't allocate map\n"));
816 		goto done;
817 	}
818 
819 	/* shared regions should always enforce code-signing */
820 	vm_map_cs_enforcement_set(sub_map, true);
821 	assert(vm_map_cs_enforcement(sub_map));
822 	assert(pmap_get_vm_map_cs_enforced(vm_map_pmap(sub_map)));
823 
824 	assert(!sub_map->disable_vmentry_reuse);
825 	sub_map->is_nested_map = TRUE;
826 
827 	/* make the memory entry point to the VM sub map */
828 	mem_entry->is_sub_map = TRUE;
829 	mem_entry->backing.map = sub_map;
830 	mem_entry->size = size;
831 	mem_entry->protection = VM_PROT_ALL;
832 
833 	/* make the shared region point at the memory entry */
834 	shared_region->sr_mem_entry = mem_entry_port;
835 
836 	/* fill in the shared region's environment and settings */
837 	shared_region->sr_base_address = base_address;
838 	shared_region->sr_size = size;
839 	shared_region->sr_pmap_nesting_start = pmap_nesting_start;
840 	shared_region->sr_pmap_nesting_size = pmap_nesting_size;
841 	shared_region->sr_cpu_type = cputype;
842 	shared_region->sr_cpu_subtype = cpu_subtype;
843 	shared_region->sr_64bit = (uint8_t)is_64bit;
844 #if __ARM_MIXED_PAGE_SIZE__
845 	shared_region->sr_page_shift = (uint8_t)target_page_shift;
846 #endif /* __ARM_MIXED_PAGE_SIZE__ */
847 	shared_region->sr_driverkit = (uint8_t)is_driverkit;
848 	shared_region->sr_rsr_version = rsr_version;
849 	shared_region->sr_root_dir = root_dir;
850 
851 	queue_init(&shared_region->sr_q);
852 	shared_region->sr_mapping_in_progress = THREAD_NULL;
853 	shared_region->sr_slide_in_progress = THREAD_NULL;
854 	shared_region->sr_persists = FALSE;
855 	shared_region->sr_stale = FALSE;
856 	shared_region->sr_timer_call = NULL;
857 	shared_region->sr_first_mapping = (mach_vm_offset_t) -1;
858 
859 	/* grab a reference for the caller */
860 	shared_region->sr_ref_count = 1;
861 
862 	shared_region->sr_slide = 0; /* not slid yet */
863 
864 	/* Initialize UUID and other metadata */
865 	memset(&shared_region->sr_uuid, '\0', sizeof(shared_region->sr_uuid));
866 	shared_region->sr_uuid_copied = FALSE;
867 	shared_region->sr_images_count = 0;
868 	shared_region->sr_images = NULL;
869 #if __has_feature(ptrauth_calls)
870 	shared_region->sr_reslide = reslide;
871 	shared_region->sr_num_auth_section = 0;
872 	shared_region->sr_next_auth_section = 0;
873 	shared_region->sr_auth_section = NULL;
874 #endif /* __has_feature(ptrauth_calls) */
875 
876 done:
877 	if (shared_region) {
878 		SHARED_REGION_TRACE_INFO(
879 			("shared_region: create(root=%p,cpu=<%d,%d>,64bit=%d,reslide=%d,driverkit=%d,"
880 			"base=0x%llx,size=0x%llx) <- "
881 			"%p mem=(%p,%p) map=%p pmap=%p\n",
882 			(void *)VM_KERNEL_ADDRPERM(root_dir),
883 			cputype, cpu_subtype, is_64bit, reslide, is_driverkit,
884 			(long long)base_address,
885 			(long long)size,
886 			(void *)VM_KERNEL_ADDRPERM(shared_region),
887 			(void *)VM_KERNEL_ADDRPERM(mem_entry_port),
888 			(void *)VM_KERNEL_ADDRPERM(mem_entry),
889 			(void *)VM_KERNEL_ADDRPERM(sub_map),
890 			(void *)VM_KERNEL_ADDRPERM(sub_map->pmap)));
891 	} else {
892 		SHARED_REGION_TRACE_INFO(
893 			("shared_region: create(root=%p,cpu=<%d,%d>,64bit=%d,driverkit=%d,"
894 			"base=0x%llx,size=0x%llx) <- NULL",
895 			(void *)VM_KERNEL_ADDRPERM(root_dir),
896 			cputype, cpu_subtype, is_64bit, is_driverkit,
897 			(long long)base_address,
898 			(long long)size));
899 	}
900 	return shared_region;
901 }
902 
903 /*
904  * Destroy a now-unused shared region.
905  * The shared region is no longer in the queue and can not be looked up.
906  */
907 static void
vm_shared_region_destroy(vm_shared_region_t shared_region)908 vm_shared_region_destroy(
909 	vm_shared_region_t      shared_region)
910 {
911 	vm_named_entry_t        mem_entry;
912 	vm_map_t                map;
913 
914 	SHARED_REGION_TRACE_INFO(
915 		("shared_region: -> destroy(%p) (root=%p,cpu=<%d,%d>,64bit=%d,driverkit=%d)\n",
916 		(void *)VM_KERNEL_ADDRPERM(shared_region),
917 		(void *)VM_KERNEL_ADDRPERM(shared_region->sr_root_dir),
918 		shared_region->sr_cpu_type,
919 		shared_region->sr_cpu_subtype,
920 		shared_region->sr_64bit,
921 		shared_region->sr_driverkit));
922 
923 	assert(shared_region->sr_ref_count == 0);
924 	assert(!shared_region->sr_persists);
925 
926 	mem_entry = mach_memory_entry_from_port(shared_region->sr_mem_entry);
927 	assert(mem_entry->is_sub_map);
928 	assert(!mem_entry->internal);
929 	assert(!mem_entry->is_copy);
930 	map = mem_entry->backing.map;
931 
932 	/*
933 	 * Clean up the pmap first.  The virtual addresses that were
934 	 * entered in this possibly "nested" pmap may have different values
935 	 * than the VM map's min and max offsets, if the VM sub map was
936 	 * mapped at a non-zero offset in the processes' main VM maps, which
937 	 * is usually the case, so the clean-up we do in vm_map_destroy() would
938 	 * not be enough.
939 	 */
940 	if (map->pmap) {
941 		pmap_remove(map->pmap,
942 		    (vm_map_offset_t)shared_region->sr_base_address,
943 		    (vm_map_offset_t)(shared_region->sr_base_address + shared_region->sr_size));
944 	}
945 
946 	/*
947 	 * Release our (one and only) handle on the memory entry.
948 	 * This will generate a no-senders notification, which will be processed
949 	 * by ipc_kobject_notify_no_senders(), which will release the one and only
950 	 * reference on the memory entry and cause it to be destroyed, along
951 	 * with the VM sub map and its pmap.
952 	 */
953 	mach_memory_entry_port_release(shared_region->sr_mem_entry);
954 	mem_entry = NULL;
955 	shared_region->sr_mem_entry = IPC_PORT_NULL;
956 
957 	if (shared_region->sr_timer_call) {
958 		thread_call_free(shared_region->sr_timer_call);
959 	}
960 
961 #if __has_feature(ptrauth_calls)
962 	/*
963 	 * Free the cached copies of slide_info for the AUTH regions.
964 	 */
965 	for (uint_t i = 0; i < shared_region->sr_num_auth_section; ++i) {
966 		vm_shared_region_slide_info_t si = shared_region->sr_auth_section[i];
967 		if (si != NULL) {
968 			vm_object_deallocate(si->si_slide_object);
969 			kfree_data(si->si_slide_info_entry,
970 			    si->si_slide_info_size);
971 			kfree_type(struct vm_shared_region_slide_info, si);
972 			shared_region->sr_auth_section[i] = NULL;
973 		}
974 	}
975 	if (shared_region->sr_auth_section != NULL) {
976 		assert(shared_region->sr_num_auth_section > 0);
977 		kfree_type(vm_shared_region_slide_info_t, shared_region->sr_num_auth_section, shared_region->sr_auth_section);
978 		shared_region->sr_auth_section = NULL;
979 		shared_region->sr_num_auth_section = 0;
980 	}
981 #endif /* __has_feature(ptrauth_calls) */
982 
983 	/* release the shared region structure... */
984 	kfree_type(struct vm_shared_region, shared_region);
985 
986 	SHARED_REGION_TRACE_DEBUG(
987 		("shared_region: destroy(%p) <-\n",
988 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
989 	shared_region = NULL;
990 }
991 
992 /*
993  * Gets the address of the first (in time) mapping in the shared region.
994  * If used during initial task setup by dyld, task should non-NULL.
995  */
996 kern_return_t
vm_shared_region_start_address(vm_shared_region_t shared_region,mach_vm_offset_t * start_address,task_t task)997 vm_shared_region_start_address(
998 	vm_shared_region_t      shared_region,
999 	mach_vm_offset_t        *start_address,
1000 	task_t                  task)
1001 {
1002 	kern_return_t           kr;
1003 	mach_vm_offset_t        sr_base_address;
1004 	mach_vm_offset_t        sr_first_mapping;
1005 
1006 	SHARED_REGION_TRACE_DEBUG(
1007 		("shared_region: -> start_address(%p)\n",
1008 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
1009 
1010 	vm_shared_region_lock();
1011 
1012 	/*
1013 	 * Wait if there's another thread establishing a mapping
1014 	 * in this shared region right when we're looking at it.
1015 	 * We want a consistent view of the map...
1016 	 */
1017 	while (shared_region->sr_mapping_in_progress) {
1018 		/* wait for our turn... */
1019 		vm_shared_region_sleep(&shared_region->sr_mapping_in_progress,
1020 		    THREAD_UNINT);
1021 	}
1022 	assert(!shared_region->sr_mapping_in_progress);
1023 	assert(shared_region->sr_ref_count > 0);
1024 
1025 	sr_base_address = shared_region->sr_base_address;
1026 	sr_first_mapping = shared_region->sr_first_mapping;
1027 
1028 	if (sr_first_mapping == (mach_vm_offset_t) -1) {
1029 		/* shared region is empty */
1030 		kr = KERN_INVALID_ADDRESS;
1031 	} else {
1032 		kr = KERN_SUCCESS;
1033 		*start_address = sr_base_address + sr_first_mapping;
1034 	}
1035 
1036 
1037 	uint32_t slide = shared_region->sr_slide;
1038 
1039 	vm_shared_region_unlock();
1040 
1041 	/*
1042 	 * Cache shared region info in the task for telemetry gathering, if we're
1043 	 * passed in the task. No task lock here as we're still in intial task set up.
1044 	 */
1045 	if (kr == KERN_SUCCESS && task != NULL && task->task_shared_region_slide == -1) {
1046 		uint_t sc_header_uuid_offset = offsetof(struct _dyld_cache_header, uuid);
1047 		if (copyin((user_addr_t)(*start_address + sc_header_uuid_offset),
1048 		    (char *)&task->task_shared_region_uuid,
1049 		    sizeof(task->task_shared_region_uuid)) == 0) {
1050 			task->task_shared_region_slide = slide;
1051 		}
1052 	}
1053 
1054 	SHARED_REGION_TRACE_DEBUG(
1055 		("shared_region: start_address(%p) <- 0x%llx\n",
1056 		(void *)VM_KERNEL_ADDRPERM(shared_region),
1057 		(long long)shared_region->sr_base_address));
1058 
1059 	return kr;
1060 }
1061 
1062 /*
1063  * Look up a pre-existing mapping in shared region, for replacement.
1064  * Takes an extra object reference if found.
1065  */
1066 static kern_return_t
find_mapping_to_slide(vm_map_t map,vm_map_address_t addr,vm_map_entry_t entry)1067 find_mapping_to_slide(vm_map_t map, vm_map_address_t addr, vm_map_entry_t entry)
1068 {
1069 	vm_map_entry_t found;
1070 
1071 	/* find the shared region's map entry to slide */
1072 	vm_map_lock_read(map);
1073 	if (!vm_map_lookup_entry_allow_pgz(map, addr, &found)) {
1074 		/* no mapping there */
1075 		vm_map_unlock(map);
1076 		return KERN_INVALID_ARGUMENT;
1077 	}
1078 
1079 	*entry = *found;
1080 	/* extra ref to keep object alive while map is unlocked */
1081 	vm_object_reference(VME_OBJECT(found));
1082 	vm_map_unlock_read(map);
1083 	return KERN_SUCCESS;
1084 }
1085 
1086 static bool
shared_region_make_permanent(vm_shared_region_t sr,vm_prot_t max_prot)1087 shared_region_make_permanent(
1088 	vm_shared_region_t sr,
1089 	vm_prot_t max_prot)
1090 {
1091 	if (sr->sr_cpu_type == CPU_TYPE_X86_64) {
1092 		return false;
1093 	}
1094 	if (max_prot & VM_PROT_WRITE) {
1095 		/*
1096 		 * Potentially writable mapping: no major issue with allowing
1097 		 * it to be replaced since its contents could be modified
1098 		 * anyway.
1099 		 */
1100 		return false;
1101 	}
1102 	if (max_prot & VM_PROT_EXECUTE) {
1103 		/*
1104 		 * Potentially executable mapping: some software might want
1105 		 * to try and replace it to interpose their own code when a
1106 		 * given routine is called or returns, for example.
1107 		 * So let's not make it "permanent".
1108 		 */
1109 		return false;
1110 	}
1111 	/*
1112 	 * Make this mapping "permanent" to prevent it from being deleted
1113 	 * and/or replaced with another mapping.
1114 	 */
1115 	return true;
1116 }
1117 
1118 static bool
shared_region_tpro_protect(vm_shared_region_t sr,vm_prot_t max_prot __unused)1119 shared_region_tpro_protect(
1120 	vm_shared_region_t sr,
1121 	vm_prot_t max_prot __unused)
1122 {
1123 	if (sr->sr_cpu_type != CPU_TYPE_ARM64 ||
1124 	    (sr->sr_cpu_subtype & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_ARM64E) {
1125 		return false;
1126 	}
1127 
1128 
1129 	/*
1130 	 * Unless otherwise explicitly requested all other mappings do not get
1131 	 * TPRO protection.
1132 	 */
1133 	return false;
1134 }
1135 
1136 #if __has_feature(ptrauth_calls)
1137 
1138 /*
1139  * Determine if this task is actually using pointer signing.
1140  */
1141 static boolean_t
task_sign_pointers(task_t task)1142 task_sign_pointers(task_t task)
1143 {
1144 	if (task->map &&
1145 	    task->map->pmap &&
1146 	    !task->map->pmap->disable_jop) {
1147 		return TRUE;
1148 	}
1149 	return FALSE;
1150 }
1151 
1152 /*
1153  * If the shared region contains mappings that are authenticated, then
1154  * remap them into the task private map.
1155  *
1156  * Failures are possible in this routine when jetsam kills a process
1157  * just as dyld is trying to set it up. The vm_map and task shared region
1158  * info get torn down w/o waiting for this thread to finish up.
1159  */
1160 __attribute__((noinline))
1161 kern_return_t
vm_shared_region_auth_remap(vm_shared_region_t sr)1162 vm_shared_region_auth_remap(vm_shared_region_t sr)
1163 {
1164 	memory_object_t               sr_pager = MEMORY_OBJECT_NULL;
1165 	task_t                        task = current_task();
1166 	vm_shared_region_slide_info_t si;
1167 	uint_t                        i;
1168 	vm_object_t                   object;
1169 	vm_map_t                      sr_map;
1170 	struct vm_map_entry           tmp_entry_store = {0};
1171 	vm_map_entry_t                tmp_entry = NULL;
1172 	vm_map_kernel_flags_t         vmk_flags;
1173 	vm_map_offset_t               map_addr;
1174 	kern_return_t                 kr = KERN_SUCCESS;
1175 	boolean_t                     use_ptr_auth = task_sign_pointers(task);
1176 
1177 	/*
1178 	 * Don't do this more than once and avoid any race conditions in finishing it.
1179 	 */
1180 	vm_shared_region_lock();
1181 	while (sr->sr_mapping_in_progress) {
1182 		/* wait for our turn... */
1183 		vm_shared_region_sleep(&sr->sr_mapping_in_progress, THREAD_UNINT);
1184 	}
1185 	assert(!sr->sr_mapping_in_progress);
1186 	assert(sr->sr_ref_count > 0);
1187 
1188 	/* Just return if already done. */
1189 	if (task->shared_region_auth_remapped) {
1190 		vm_shared_region_unlock();
1191 		return KERN_SUCCESS;
1192 	}
1193 
1194 	/* let others know to wait while we're working in this shared region */
1195 	sr->sr_mapping_in_progress = current_thread();
1196 	vm_shared_region_unlock();
1197 
1198 	/*
1199 	 * Remap any sections with pointer authentications into the private map.
1200 	 */
1201 	for (i = 0; i < sr->sr_num_auth_section; ++i) {
1202 		si = sr->sr_auth_section[i];
1203 		assert(si != NULL);
1204 		assert(si->si_ptrauth);
1205 
1206 		/*
1207 		 * We have mapping that needs to be private.
1208 		 * Look for an existing slid mapping's pager with matching
1209 		 * object, offset, slide info and shared_region_id to reuse.
1210 		 */
1211 		object = si->si_slide_object;
1212 		sr_pager = shared_region_pager_match(object, si->si_start, si,
1213 		    use_ptr_auth ? task->jop_pid : 0);
1214 		if (sr_pager == MEMORY_OBJECT_NULL) {
1215 			printf("%s(): shared_region_pager_match() failed\n", __func__);
1216 			kr = KERN_FAILURE;
1217 			goto done;
1218 		}
1219 
1220 		/*
1221 		 * verify matching jop_pid for this task and this pager
1222 		 */
1223 		if (use_ptr_auth) {
1224 			shared_region_pager_match_task_key(sr_pager, task);
1225 		}
1226 
1227 		sr_map = vm_shared_region_vm_map(sr);
1228 		tmp_entry = NULL;
1229 
1230 		kr = find_mapping_to_slide(sr_map, si->si_slid_address - sr->sr_base_address, &tmp_entry_store);
1231 		if (kr != KERN_SUCCESS) {
1232 			printf("%s(): find_mapping_to_slide() failed\n", __func__);
1233 			goto done;
1234 		}
1235 		tmp_entry = &tmp_entry_store;
1236 
1237 		/*
1238 		 * Check that the object exactly covers the region to slide.
1239 		 */
1240 		if (tmp_entry->vme_end - tmp_entry->vme_start != si->si_end - si->si_start) {
1241 			printf("%s(): doesn't fully cover\n", __func__);
1242 			kr = KERN_FAILURE;
1243 			goto done;
1244 		}
1245 
1246 		/*
1247 		 * map the pager over the portion of the mapping that needs sliding
1248 		 */
1249 		vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true);
1250 		vmk_flags.vmkf_overwrite_immutable = true;
1251 		vmk_flags.vmf_permanent = shared_region_make_permanent(sr,
1252 		    tmp_entry->max_protection);
1253 
1254 		/* Preserve the TPRO flag if task has TPRO enabled */
1255 		vmk_flags.vmf_tpro = (vm_map_tpro(task->map) &&
1256 		    tmp_entry->used_for_tpro &&
1257 		    task_is_hardened_binary(task));
1258 
1259 		map_addr = si->si_slid_address;
1260 		kr = mach_vm_map_kernel(task->map,
1261 		    vm_sanitize_wrap_addr_ref(&map_addr),
1262 		    si->si_end - si->si_start,
1263 		    0,
1264 		    vmk_flags,
1265 		    (ipc_port_t)(uintptr_t) sr_pager,
1266 		    0,
1267 		    TRUE,
1268 		    tmp_entry->protection,
1269 		    tmp_entry->max_protection,
1270 		    tmp_entry->inheritance);
1271 		memory_object_deallocate(sr_pager);
1272 		sr_pager = MEMORY_OBJECT_NULL;
1273 		if (kr != KERN_SUCCESS) {
1274 			printf("%s(): mach_vm_map_kernel() failed\n", __func__);
1275 			goto done;
1276 		}
1277 		assertf(map_addr == si->si_slid_address,
1278 		    "map_addr=0x%llx si_slid_address=0x%llx tmp_entry=%p\n",
1279 		    (uint64_t)map_addr,
1280 		    (uint64_t)si->si_slid_address,
1281 		    tmp_entry);
1282 
1283 		/* Drop the ref count grabbed by find_mapping_to_slide */
1284 		vm_object_deallocate(VME_OBJECT(tmp_entry));
1285 		tmp_entry = NULL;
1286 	}
1287 
1288 done:
1289 	if (tmp_entry) {
1290 		/* Drop the ref count grabbed by find_mapping_to_slide */
1291 		vm_object_deallocate(VME_OBJECT(tmp_entry));
1292 		tmp_entry = NULL;
1293 	}
1294 
1295 	/*
1296 	 * Drop any extra reference to the pager in case we're quitting due to an error above.
1297 	 */
1298 	if (sr_pager != MEMORY_OBJECT_NULL) {
1299 		memory_object_deallocate(sr_pager);
1300 	}
1301 
1302 	/*
1303 	 * Mark the region as having it's auth sections remapped.
1304 	 */
1305 	vm_shared_region_lock();
1306 	task->shared_region_auth_remapped = TRUE;
1307 	assert(sr->sr_mapping_in_progress == current_thread());
1308 	sr->sr_mapping_in_progress = THREAD_NULL;
1309 	vm_shared_region_wakeup((event_t)&sr->sr_mapping_in_progress);
1310 	vm_shared_region_unlock();
1311 	return kr;
1312 }
1313 #endif /* __has_feature(ptrauth_calls) */
1314 
1315 void
vm_shared_region_undo_mappings(vm_map_t sr_map,mach_vm_offset_t sr_base_address,struct _sr_file_mappings * srf_mappings,struct _sr_file_mappings * srf_mappings_current,unsigned int srf_current_mappings_count)1316 vm_shared_region_undo_mappings(
1317 	vm_map_t                 sr_map,
1318 	mach_vm_offset_t         sr_base_address,
1319 	struct _sr_file_mappings *srf_mappings,
1320 	struct _sr_file_mappings *srf_mappings_current,
1321 	unsigned int             srf_current_mappings_count)
1322 {
1323 	unsigned int             j = 0;
1324 	vm_shared_region_t       shared_region = NULL;
1325 	boolean_t                reset_shared_region_state = FALSE;
1326 	struct _sr_file_mappings *srfmp;
1327 	unsigned int             mappings_count;
1328 	struct shared_file_mapping_slide_np *mappings;
1329 
1330 	shared_region = vm_shared_region_get(current_task());
1331 	if (shared_region == NULL) {
1332 		printf("Failed to undo mappings because of NULL shared region.\n");
1333 		return;
1334 	}
1335 
1336 	shared_region->sr_first_mapping = (mach_vm_offset_t) -1;
1337 
1338 	if (sr_map == NULL) {
1339 		ipc_port_t              sr_handle;
1340 		vm_named_entry_t        sr_mem_entry;
1341 
1342 		vm_shared_region_lock();
1343 		assert(shared_region->sr_ref_count > 0);
1344 
1345 		while (shared_region->sr_mapping_in_progress) {
1346 			/* wait for our turn... */
1347 			vm_shared_region_sleep(&shared_region->sr_mapping_in_progress,
1348 			    THREAD_UNINT);
1349 		}
1350 		assert(!shared_region->sr_mapping_in_progress);
1351 		assert(shared_region->sr_ref_count > 0);
1352 		/* let others know we're working in this shared region */
1353 		shared_region->sr_mapping_in_progress = current_thread();
1354 
1355 		vm_shared_region_unlock();
1356 
1357 		reset_shared_region_state = TRUE;
1358 
1359 		/* no need to lock because this data is never modified... */
1360 		sr_handle = shared_region->sr_mem_entry;
1361 		sr_mem_entry = mach_memory_entry_from_port(sr_handle);
1362 		sr_map = sr_mem_entry->backing.map;
1363 		sr_base_address = shared_region->sr_base_address;
1364 	}
1365 	/*
1366 	 * Undo the mappings we've established so far.
1367 	 */
1368 	for (srfmp = &srf_mappings[0];
1369 	    srfmp <= srf_mappings_current;
1370 	    srfmp++) {
1371 		mappings = srfmp->mappings;
1372 		mappings_count = srfmp->mappings_count;
1373 		if (srfmp == srf_mappings_current) {
1374 			mappings_count = srf_current_mappings_count;
1375 		}
1376 
1377 		for (j = 0; j < mappings_count; j++) {
1378 			kern_return_t kr2;
1379 			mach_vm_offset_t start, end;
1380 
1381 			if (mappings[j].sms_size == 0) {
1382 				/*
1383 				 * We didn't establish this
1384 				 * mapping, so nothing to undo.
1385 				 */
1386 				continue;
1387 			}
1388 			SHARED_REGION_TRACE_INFO(
1389 				("shared_region: mapping[%d]: "
1390 				"address:0x%016llx "
1391 				"size:0x%016llx "
1392 				"offset:0x%016llx "
1393 				"maxprot:0x%x prot:0x%x: "
1394 				"undoing...\n",
1395 				j,
1396 				(long long)mappings[j].sms_address,
1397 				(long long)mappings[j].sms_size,
1398 				(long long)mappings[j].sms_file_offset,
1399 				mappings[j].sms_max_prot,
1400 				mappings[j].sms_init_prot));
1401 			start = (mappings[j].sms_address - sr_base_address);
1402 			end = start + mappings[j].sms_size;
1403 			start = vm_map_trunc_page(start, VM_MAP_PAGE_MASK(sr_map));
1404 			end = vm_map_round_page(end, VM_MAP_PAGE_MASK(sr_map));
1405 			kr2 = vm_map_remove_guard(sr_map,
1406 			    start,
1407 			    end,
1408 			    VM_MAP_REMOVE_IMMUTABLE,
1409 			    KMEM_GUARD_NONE).kmr_return;
1410 			assert(kr2 == KERN_SUCCESS);
1411 		}
1412 	}
1413 
1414 	if (reset_shared_region_state) {
1415 		vm_shared_region_lock();
1416 		assert(shared_region->sr_ref_count > 0);
1417 		assert(shared_region->sr_mapping_in_progress == current_thread());
1418 		/* we're done working on that shared region */
1419 		shared_region->sr_mapping_in_progress = THREAD_NULL;
1420 		vm_shared_region_wakeup((event_t) &shared_region->sr_mapping_in_progress);
1421 		vm_shared_region_unlock();
1422 		reset_shared_region_state = FALSE;
1423 	}
1424 
1425 	vm_shared_region_deallocate(shared_region);
1426 }
1427 
1428 /*
1429  * First part of vm_shared_region_map_file(). Split out to
1430  * avoid kernel stack overflow.
1431  */
1432 __attribute__((noinline))
1433 static kern_return_t
vm_shared_region_map_file_setup(vm_shared_region_t shared_region,int sr_file_mappings_count,struct _sr_file_mappings * sr_file_mappings,unsigned int * mappings_to_slide_cnt,struct shared_file_mapping_slide_np ** mappings_to_slide,mach_vm_offset_t * slid_mappings,memory_object_control_t * slid_file_controls,mach_vm_offset_t * sfm_min_address,mach_vm_offset_t * sfm_max_address,vm_map_t * sr_map_ptr,vm_map_offset_t * lowest_unnestable_addr_ptr,unsigned int vmsr_num_slides)1434 vm_shared_region_map_file_setup(
1435 	vm_shared_region_t              shared_region,
1436 	int                             sr_file_mappings_count,
1437 	struct _sr_file_mappings        *sr_file_mappings,
1438 	unsigned int                    *mappings_to_slide_cnt,
1439 	struct shared_file_mapping_slide_np **mappings_to_slide,
1440 	mach_vm_offset_t                *slid_mappings,
1441 	memory_object_control_t         *slid_file_controls,
1442 	mach_vm_offset_t                *sfm_min_address,
1443 	mach_vm_offset_t                *sfm_max_address,
1444 	vm_map_t                        *sr_map_ptr,
1445 	vm_map_offset_t                 *lowest_unnestable_addr_ptr,
1446 	unsigned int                    vmsr_num_slides)
1447 {
1448 	kern_return_t           kr = KERN_SUCCESS;
1449 	memory_object_control_t file_control;
1450 	vm_object_t             file_object;
1451 	ipc_port_t              sr_handle;
1452 	vm_named_entry_t        sr_mem_entry;
1453 	vm_map_t                sr_map;
1454 	mach_vm_offset_t        sr_base_address;
1455 	unsigned int            i = 0;
1456 	mach_port_t             map_port;
1457 	vm_map_offset_t         target_address;
1458 	vm_object_t             object;
1459 	vm_object_size_t        obj_size;
1460 	vm_map_offset_t         lowest_unnestable_addr = 0;
1461 	vm_map_kernel_flags_t   vmk_flags;
1462 	mach_vm_offset_t        sfm_end;
1463 	uint32_t                mappings_count;
1464 	struct shared_file_mapping_slide_np *mappings;
1465 	struct _sr_file_mappings *srfmp;
1466 
1467 	vm_shared_region_lock();
1468 	assert(shared_region->sr_ref_count > 0);
1469 
1470 	/*
1471 	 * Make sure we handle only one mapping at a time in a given
1472 	 * shared region, to avoid race conditions.  This should not
1473 	 * happen frequently...
1474 	 */
1475 	while (shared_region->sr_mapping_in_progress) {
1476 		/* wait for our turn... */
1477 		vm_shared_region_sleep(&shared_region->sr_mapping_in_progress,
1478 		    THREAD_UNINT);
1479 	}
1480 	assert(!shared_region->sr_mapping_in_progress);
1481 	assert(shared_region->sr_ref_count > 0);
1482 
1483 
1484 	/* let others know we're working in this shared region */
1485 	shared_region->sr_mapping_in_progress = current_thread();
1486 
1487 	/*
1488 	 * Did someone race in and map this shared region already?
1489 	 */
1490 	if (shared_region->sr_first_mapping != -1) {
1491 		vm_shared_region_unlock();
1492 #if DEVELOPMENT || DEBUG
1493 		printf("shared_region: caught race in map and slide\n");
1494 #endif /* DEVELOPMENT || DEBUG */
1495 		return KERN_FAILURE;
1496 	}
1497 
1498 	vm_shared_region_unlock();
1499 
1500 	/* no need to lock because this data is never modified... */
1501 	sr_handle = shared_region->sr_mem_entry;
1502 	sr_mem_entry = mach_memory_entry_from_port(sr_handle);
1503 	sr_map = sr_mem_entry->backing.map;
1504 	sr_base_address = shared_region->sr_base_address;
1505 
1506 	SHARED_REGION_TRACE_DEBUG(
1507 		("shared_region: -> map(%p)\n",
1508 		(void *)VM_KERNEL_ADDRPERM(shared_region)));
1509 
1510 	mappings_count = 0;
1511 	mappings = NULL;
1512 	srfmp = NULL;
1513 
1514 	/* process all the files to be mapped */
1515 	for (srfmp = &sr_file_mappings[0];
1516 	    srfmp < &sr_file_mappings[sr_file_mappings_count];
1517 	    srfmp++) {
1518 		mappings_count = srfmp->mappings_count;
1519 		mappings = srfmp->mappings;
1520 		file_control = srfmp->file_control;
1521 
1522 		if (mappings_count == 0) {
1523 			/* no mappings here... */
1524 			continue;
1525 		}
1526 
1527 		/*
1528 		 * The code below can only correctly "slide" (perform relocations) for one
1529 		 * value of the slide amount. So if a file has a non-zero slide, it has to
1530 		 * match any previous value. A zero slide value is ok for things that are
1531 		 * just directly mapped.
1532 		 */
1533 		if (shared_region->sr_slide == 0 && srfmp->slide != 0) {
1534 			shared_region->sr_slide = srfmp->slide;
1535 		} else if (shared_region->sr_slide != 0 &&
1536 		    srfmp->slide != 0 &&
1537 		    shared_region->sr_slide != srfmp->slide) {
1538 			SHARED_REGION_TRACE_ERROR(
1539 				("shared_region: more than 1 non-zero slide value amount "
1540 				"slide 1:0x%x slide 2:0x%x\n ",
1541 				shared_region->sr_slide, srfmp->slide));
1542 			kr = KERN_INVALID_ARGUMENT;
1543 			break;
1544 		}
1545 
1546 		/*
1547 		 * An FD of -1 means we need to copyin the data to an anonymous object.
1548 		 */
1549 		if (srfmp->fd == -1) {
1550 			assert(mappings_count == 1);
1551 			SHARED_REGION_TRACE_INFO(
1552 				("shared_region: mapping[0]: "
1553 				"address:0x%016llx size:0x%016llx offset/addr:0x%016llx "
1554 				"maxprot:0x%x prot:0x%x fd==-1\n",
1555 				(long long)mappings[0].sms_address,
1556 				(long long)mappings[0].sms_size,
1557 				(long long)mappings[0].sms_file_offset,
1558 				mappings[0].sms_max_prot,
1559 				mappings[0].sms_init_prot));
1560 
1561 			/*
1562 			 * We need an anon object to hold the data in the shared region.
1563 			 * The size needs to be suitable to map into kernel.
1564 			 */
1565 			obj_size = vm_object_round_page(mappings->sms_size);
1566 			object = vm_object_allocate(obj_size);
1567 			if (object == VM_OBJECT_NULL) {
1568 				printf("%s(): for fd==-1 vm_object_allocate() failed\n", __func__);
1569 				kr = KERN_RESOURCE_SHORTAGE;
1570 				break;
1571 			}
1572 
1573 			/*
1574 			 * map the object into the kernel
1575 			 */
1576 			vm_map_offset_t kaddr = 0;
1577 			vmk_flags = VM_MAP_KERNEL_FLAGS_ANYWHERE();
1578 			vmk_flags.vmkf_no_copy_on_read = 1;
1579 			vmk_flags.vmkf_range_id = KMEM_RANGE_ID_DATA;
1580 
1581 			kr = vm_map_enter(kernel_map,
1582 			    &kaddr,
1583 			    obj_size,
1584 			    0,
1585 			    vmk_flags,
1586 			    object,
1587 			    0,
1588 			    FALSE,
1589 			    (VM_PROT_READ | VM_PROT_WRITE),
1590 			    (VM_PROT_READ | VM_PROT_WRITE),
1591 			    VM_INHERIT_NONE);
1592 			if (kr != KERN_SUCCESS) {
1593 				printf("%s(): for fd==-1 vm_map_enter() in kernel failed\n", __func__);
1594 				vm_object_deallocate(object);
1595 				object = VM_OBJECT_NULL;
1596 				break;
1597 			}
1598 
1599 			/*
1600 			 * We'll need another reference to keep the object alive after
1601 			 * we vm_map_remove() it from the kernel.
1602 			 */
1603 			vm_object_reference(object);
1604 
1605 			/*
1606 			 * Zero out the object's pages, so we can't leak data.
1607 			 */
1608 			bzero((void *)kaddr, obj_size);
1609 
1610 			/*
1611 			 * Copyin the data from dyld to the new object.
1612 			 * Then remove the kernel mapping.
1613 			 */
1614 			int copyin_err =
1615 			    copyin((user_addr_t)mappings->sms_file_offset, (void *)kaddr, mappings->sms_size);
1616 			vm_map_remove(kernel_map, kaddr, kaddr + obj_size);
1617 			if (copyin_err) {
1618 				printf("%s(): for fd==-1 copyin() failed, errno=%d\n", __func__, copyin_err);
1619 				switch (copyin_err) {
1620 				case EPERM:
1621 				case EACCES:
1622 					kr = KERN_PROTECTION_FAILURE;
1623 					break;
1624 				case EFAULT:
1625 					kr = KERN_INVALID_ADDRESS;
1626 					break;
1627 				default:
1628 					kr = KERN_FAILURE;
1629 					break;
1630 				}
1631 				vm_object_deallocate(object);
1632 				object = VM_OBJECT_NULL;
1633 				break;
1634 			}
1635 
1636 			/*
1637 			 * Finally map the object into the shared region.
1638 			 */
1639 			target_address = (vm_map_offset_t)(mappings[0].sms_address - sr_base_address);
1640 			vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED();
1641 			vmk_flags.vmkf_already = TRUE;
1642 			vmk_flags.vmkf_no_copy_on_read = 1;
1643 			vmk_flags.vmf_permanent = shared_region_make_permanent(shared_region,
1644 			    mappings[0].sms_max_prot);
1645 
1646 			kr = vm_map_enter(
1647 				sr_map,
1648 				&target_address,
1649 				vm_map_round_page(mappings[0].sms_size, VM_MAP_PAGE_MASK(sr_map)),
1650 				0,
1651 				vmk_flags,
1652 				object,
1653 				0,
1654 				TRUE,
1655 				mappings[0].sms_init_prot & VM_PROT_ALL,
1656 				mappings[0].sms_max_prot & VM_PROT_ALL,
1657 				VM_INHERIT_DEFAULT);
1658 			if (kr != KERN_SUCCESS) {
1659 				printf("%s(): for fd==-1 vm_map_enter() in SR failed\n", __func__);
1660 				vm_object_deallocate(object);
1661 				break;
1662 			}
1663 
1664 			if (mappings[0].sms_address < *sfm_min_address) {
1665 				*sfm_min_address = mappings[0].sms_address;
1666 			}
1667 
1668 			if (os_add_overflow(mappings[0].sms_address,
1669 			    mappings[0].sms_size,
1670 			    &sfm_end) ||
1671 			    (vm_map_round_page(sfm_end, VM_MAP_PAGE_MASK(sr_map)) <
1672 			    mappings[0].sms_address)) {
1673 				/* overflow */
1674 				kr = KERN_INVALID_ARGUMENT;
1675 				break;
1676 			}
1677 
1678 			if (sfm_end > *sfm_max_address) {
1679 				*sfm_max_address = sfm_end;
1680 			}
1681 
1682 			continue;
1683 		}
1684 
1685 		/* get the VM object associated with the file to be mapped */
1686 		file_object = memory_object_control_to_vm_object(file_control);
1687 		assert(file_object);
1688 
1689 		if (!file_object->object_is_shared_cache) {
1690 			vm_object_lock(file_object);
1691 			file_object->object_is_shared_cache = true;
1692 			vm_object_unlock(file_object);
1693 		}
1694 
1695 #if CONFIG_SECLUDED_MEMORY
1696 		/*
1697 		 * Camera will need the shared cache, so don't put the pages
1698 		 * on the secluded queue, assume that's the primary region.
1699 		 * Also keep DEXT shared cache pages off secluded.
1700 		 */
1701 		if (primary_system_shared_region == NULL ||
1702 		    primary_system_shared_region == shared_region ||
1703 		    shared_region->sr_driverkit) {
1704 			memory_object_mark_eligible_for_secluded(file_control, FALSE);
1705 		}
1706 #endif /* CONFIG_SECLUDED_MEMORY */
1707 
1708 		/* establish the mappings for that file */
1709 		for (i = 0; i < mappings_count; i++) {
1710 			SHARED_REGION_TRACE_INFO(
1711 				("shared_region: mapping[%d]: "
1712 				"address:0x%016llx size:0x%016llx offset:0x%016llx "
1713 				"maxprot:0x%x prot:0x%x\n",
1714 				i,
1715 				(long long)mappings[i].sms_address,
1716 				(long long)mappings[i].sms_size,
1717 				(long long)mappings[i].sms_file_offset,
1718 				mappings[i].sms_max_prot,
1719 				mappings[i].sms_init_prot));
1720 
1721 			if (mappings[i].sms_address < *sfm_min_address) {
1722 				*sfm_min_address = mappings[i].sms_address;
1723 			}
1724 
1725 			if (os_add_overflow(mappings[i].sms_address,
1726 			    mappings[i].sms_size,
1727 			    &sfm_end) ||
1728 			    (vm_map_round_page(sfm_end, VM_MAP_PAGE_MASK(sr_map)) <
1729 			    mappings[i].sms_address)) {
1730 				/* overflow */
1731 				kr = KERN_INVALID_ARGUMENT;
1732 				break;
1733 			}
1734 
1735 			if (sfm_end > *sfm_max_address) {
1736 				*sfm_max_address = sfm_end;
1737 			}
1738 
1739 			if (mappings[i].sms_init_prot & VM_PROT_ZF) {
1740 				/* zero-filled memory */
1741 				map_port = MACH_PORT_NULL;
1742 			} else {
1743 				/* file-backed memory */
1744 				__IGNORE_WCASTALIGN(map_port = (ipc_port_t) file_object->pager);
1745 			}
1746 
1747 			/*
1748 			 * Remember which mappings need sliding.
1749 			 */
1750 			if (mappings[i].sms_max_prot & VM_PROT_SLIDE) {
1751 				if (*mappings_to_slide_cnt == vmsr_num_slides) {
1752 					SHARED_REGION_TRACE_INFO(
1753 						("shared_region: mapping[%d]: "
1754 						"address:0x%016llx size:0x%016llx "
1755 						"offset:0x%016llx "
1756 						"maxprot:0x%x prot:0x%x "
1757 						"too many mappings to slide...\n",
1758 						i,
1759 						(long long)mappings[i].sms_address,
1760 						(long long)mappings[i].sms_size,
1761 						(long long)mappings[i].sms_file_offset,
1762 						mappings[i].sms_max_prot,
1763 						mappings[i].sms_init_prot));
1764 				} else {
1765 					mappings_to_slide[*mappings_to_slide_cnt] = &mappings[i];
1766 					*mappings_to_slide_cnt += 1;
1767 				}
1768 			}
1769 
1770 			/* mapping's address is relative to the shared region base */
1771 			if (__improbable(
1772 				    os_sub_overflow(
1773 					    mappings[i].sms_address,
1774 					    sr_base_address,
1775 					    &target_address))) {
1776 				kr = KERN_INVALID_ARGUMENT;
1777 				break;
1778 			}
1779 
1780 			vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED();
1781 			vmk_flags.vmkf_already = TRUE;
1782 			/* no copy-on-read for mapped binaries */
1783 			vmk_flags.vmkf_no_copy_on_read = 1;
1784 			vmk_flags.vmf_permanent = shared_region_make_permanent(
1785 				shared_region,
1786 				mappings[i].sms_max_prot);
1787 			vmk_flags.vmf_tpro = shared_region_tpro_protect(
1788 				shared_region,
1789 				mappings[i].sms_max_prot);
1790 
1791 			/* establish that mapping, OK if it's "already" there */
1792 			if (map_port == MACH_PORT_NULL) {
1793 				/*
1794 				 * We want to map some anonymous memory in a shared region.
1795 				 * We have to create the VM object now, so that it can be mapped "copy-on-write".
1796 				 */
1797 				obj_size = vm_map_round_page(mappings[i].sms_size, VM_MAP_PAGE_MASK(sr_map));
1798 				object = vm_object_allocate(obj_size);
1799 				if (object == VM_OBJECT_NULL) {
1800 					kr = KERN_RESOURCE_SHORTAGE;
1801 				} else {
1802 					kr = vm_map_enter(
1803 						sr_map,
1804 						&target_address,
1805 						vm_map_round_page(mappings[i].sms_size, VM_MAP_PAGE_MASK(sr_map)),
1806 						0,
1807 						vmk_flags,
1808 						object,
1809 						0,
1810 						TRUE,
1811 						mappings[i].sms_init_prot & VM_PROT_ALL,
1812 						mappings[i].sms_max_prot & VM_PROT_ALL,
1813 						VM_INHERIT_DEFAULT);
1814 				}
1815 			} else {
1816 				object = VM_OBJECT_NULL; /* no anonymous memory here */
1817 				kr = mach_vm_map_kernel(
1818 					sr_map,
1819 					vm_sanitize_wrap_addr_ref(&target_address),
1820 					vm_map_round_page(
1821 						mappings[i].sms_size, VM_MAP_PAGE_MASK(sr_map)),
1822 					0,
1823 					vmk_flags,
1824 					map_port,
1825 					mappings[i].sms_file_offset,
1826 					TRUE,
1827 					mappings[i].sms_init_prot & VM_PROT_ALL,
1828 					mappings[i].sms_max_prot & VM_PROT_ALL,
1829 					VM_INHERIT_DEFAULT);
1830 			}
1831 
1832 			if (kr == KERN_SUCCESS) {
1833 				/*
1834 				 * Record the first successful mapping(s) in the shared
1835 				 * region by file. We're protected by "sr_mapping_in_progress"
1836 				 * here, so no need to lock "shared_region".
1837 				 *
1838 				 * Note that if we have an AOT shared cache (ARM) for a
1839 				 * translated task, then it's always the first file.
1840 				 * The original "native" (i.e. x86) shared cache is the
1841 				 * second file.
1842 				 */
1843 
1844 				if (shared_region->sr_first_mapping == (mach_vm_offset_t)-1) {
1845 					shared_region->sr_first_mapping = target_address;
1846 				}
1847 
1848 				if (*mappings_to_slide_cnt > 0 &&
1849 				    mappings_to_slide[*mappings_to_slide_cnt - 1] == &mappings[i]) {
1850 					slid_mappings[*mappings_to_slide_cnt - 1] = target_address;
1851 					slid_file_controls[*mappings_to_slide_cnt - 1] = file_control;
1852 				}
1853 
1854 				/*
1855 				 * Record the lowest writable address in this
1856 				 * sub map, to log any unexpected unnesting below
1857 				 * that address (see log_unnest_badness()).
1858 				 */
1859 				if ((mappings[i].sms_init_prot & VM_PROT_WRITE) &&
1860 				    sr_map->is_nested_map &&
1861 				    (lowest_unnestable_addr == 0 ||
1862 				    (target_address < lowest_unnestable_addr))) {
1863 					lowest_unnestable_addr = target_address;
1864 				}
1865 			} else {
1866 				if (map_port == MACH_PORT_NULL) {
1867 					/*
1868 					 * Get rid of the VM object we just created
1869 					 * but failed to map.
1870 					 */
1871 					vm_object_deallocate(object);
1872 					object = VM_OBJECT_NULL;
1873 				}
1874 				if (kr == KERN_MEMORY_PRESENT) {
1875 					/*
1876 					 * This exact mapping was already there:
1877 					 * that's fine.
1878 					 */
1879 					SHARED_REGION_TRACE_INFO(
1880 						("shared_region: mapping[%d]: "
1881 						"address:0x%016llx size:0x%016llx "
1882 						"offset:0x%016llx "
1883 						"maxprot:0x%x prot:0x%x "
1884 						"already mapped...\n",
1885 						i,
1886 						(long long)mappings[i].sms_address,
1887 						(long long)mappings[i].sms_size,
1888 						(long long)mappings[i].sms_file_offset,
1889 						mappings[i].sms_max_prot,
1890 						mappings[i].sms_init_prot));
1891 					/*
1892 					 * We didn't establish this mapping ourselves;
1893 					 * let's reset its size, so that we do not
1894 					 * attempt to undo it if an error occurs later.
1895 					 */
1896 					mappings[i].sms_size = 0;
1897 					kr = KERN_SUCCESS;
1898 				} else {
1899 					break;
1900 				}
1901 			}
1902 		}
1903 
1904 		if (kr != KERN_SUCCESS) {
1905 			break;
1906 		}
1907 	}
1908 
1909 	if (kr != KERN_SUCCESS) {
1910 		/* the last mapping we tried (mappings[i]) failed ! */
1911 		assert(i < mappings_count);
1912 		SHARED_REGION_TRACE_ERROR(
1913 			("shared_region: mapping[%d]: "
1914 			"address:0x%016llx size:0x%016llx "
1915 			"offset:0x%016llx "
1916 			"maxprot:0x%x prot:0x%x failed 0x%x\n",
1917 			i,
1918 			(long long)mappings[i].sms_address,
1919 			(long long)mappings[i].sms_size,
1920 			(long long)mappings[i].sms_file_offset,
1921 			mappings[i].sms_max_prot,
1922 			mappings[i].sms_init_prot,
1923 			kr));
1924 
1925 		/*
1926 		 * Respect the design of vm_shared_region_undo_mappings
1927 		 * as we are holding the sr_mapping_in_progress here.
1928 		 * So don't allow sr_map == NULL otherwise vm_shared_region_undo_mappings
1929 		 * will be blocked at waiting sr_mapping_in_progress to be NULL.
1930 		 */
1931 		assert(sr_map != NULL);
1932 		/* undo all the previous mappings */
1933 		vm_shared_region_undo_mappings(sr_map, sr_base_address, sr_file_mappings, srfmp, i);
1934 		return kr;
1935 	}
1936 
1937 	*lowest_unnestable_addr_ptr = lowest_unnestable_addr;
1938 	*sr_map_ptr = sr_map;
1939 	return KERN_SUCCESS;
1940 }
1941 
1942 /* forwared declaration */
1943 __attribute__((noinline))
1944 static void
1945 vm_shared_region_map_file_final(
1946 	vm_shared_region_t shared_region,
1947 	vm_map_t           sr_map,
1948 	mach_vm_offset_t   sfm_min_address,
1949 	mach_vm_offset_t   sfm_max_address);
1950 
1951 /*
1952  * Establish some mappings of a file in the shared region.
1953  * This is used by "dyld" via the shared_region_map_np() system call
1954  * to populate the shared region with the appropriate shared cache.
1955  *
1956  * One could also call it several times to incrementally load several
1957  * libraries, as long as they do not overlap.
1958  * It will return KERN_SUCCESS if the mappings were successfully established
1959  * or if they were already established identically by another process.
1960  */
1961 __attribute__((noinline))
1962 kern_return_t
vm_shared_region_map_file(vm_shared_region_t shared_region,int sr_file_mappings_count,struct _sr_file_mappings * sr_file_mappings)1963 vm_shared_region_map_file(
1964 	vm_shared_region_t       shared_region,
1965 	int                      sr_file_mappings_count,
1966 	struct _sr_file_mappings *sr_file_mappings)
1967 {
1968 	kern_return_t           kr = KERN_SUCCESS;
1969 	unsigned int            i;
1970 	unsigned int            mappings_to_slide_cnt = 0;
1971 	mach_vm_offset_t        sfm_min_address = (mach_vm_offset_t)-1;
1972 	mach_vm_offset_t        sfm_max_address = 0;
1973 	vm_map_t                sr_map = NULL;
1974 	vm_map_offset_t         lowest_unnestable_addr = 0;
1975 	unsigned int            vmsr_num_slides = 0;
1976 	typedef mach_vm_offset_t slid_mappings_t __kernel_data_semantics;
1977 	slid_mappings_t         *slid_mappings = NULL;                  /* [0..vmsr_num_slides] */
1978 	memory_object_control_t *slid_file_controls = NULL;             /* [0..vmsr_num_slides] */
1979 	struct shared_file_mapping_slide_np **mappings_to_slide = NULL; /* [0..vmsr_num_slides] */
1980 	struct _sr_file_mappings *srfmp;
1981 
1982 	/*
1983 	 * Figure out how many of the mappings have slides.
1984 	 */
1985 	for (srfmp = &sr_file_mappings[0];
1986 	    srfmp < &sr_file_mappings[sr_file_mappings_count];
1987 	    srfmp++) {
1988 		for (i = 0; i < srfmp->mappings_count; ++i) {
1989 			if (srfmp->mappings[i].sms_max_prot & VM_PROT_SLIDE) {
1990 				++vmsr_num_slides;
1991 			}
1992 		}
1993 	}
1994 
1995 	/* Allocate per slide data structures */
1996 	if (vmsr_num_slides > 0) {
1997 		slid_mappings =
1998 		    kalloc_data(vmsr_num_slides * sizeof(*slid_mappings), Z_WAITOK);
1999 		slid_file_controls =
2000 		    kalloc_type(memory_object_control_t, vmsr_num_slides, Z_WAITOK);
2001 		mappings_to_slide =
2002 		    kalloc_type(struct shared_file_mapping_slide_np *, vmsr_num_slides, Z_WAITOK | Z_ZERO);
2003 	}
2004 
2005 	kr = vm_shared_region_map_file_setup(shared_region, sr_file_mappings_count, sr_file_mappings,
2006 	    &mappings_to_slide_cnt, mappings_to_slide, slid_mappings, slid_file_controls,
2007 	    &sfm_min_address, &sfm_max_address, &sr_map, &lowest_unnestable_addr, vmsr_num_slides);
2008 	if (kr != KERN_SUCCESS) {
2009 		vm_shared_region_lock();
2010 		goto done;
2011 	}
2012 	assert(vmsr_num_slides == mappings_to_slide_cnt);
2013 
2014 	/*
2015 	 * The call above installed direct mappings to the shared cache file.
2016 	 * Now we go back and overwrite the mappings that need relocation
2017 	 * with a special shared region pager.
2018 	 *
2019 	 * Note that this does copyin() of data, needed by the pager, which
2020 	 * the previous code just established mappings for. This is why we
2021 	 * do it in a separate pass.
2022 	 */
2023 #if __has_feature(ptrauth_calls)
2024 	/*
2025 	 * need to allocate storage needed for any sr_auth_sections
2026 	 */
2027 	for (i = 0; i < mappings_to_slide_cnt; ++i) {
2028 		if (shared_region->sr_cpu_type == CPU_TYPE_ARM64 &&
2029 		    shared_region->sr_cpu_subtype == CPU_SUBTYPE_ARM64E &&
2030 		    !(mappings_to_slide[i]->sms_max_prot & VM_PROT_NOAUTH)) {
2031 			++shared_region->sr_num_auth_section;
2032 		}
2033 	}
2034 	if (shared_region->sr_num_auth_section > 0) {
2035 		shared_region->sr_auth_section =
2036 		    kalloc_type(vm_shared_region_slide_info_t, shared_region->sr_num_auth_section,
2037 		    Z_WAITOK | Z_ZERO);
2038 	}
2039 #endif /* __has_feature(ptrauth_calls) */
2040 	for (i = 0; i < mappings_to_slide_cnt; ++i) {
2041 		kr = vm_shared_region_slide(shared_region->sr_slide,
2042 		    mappings_to_slide[i]->sms_file_offset,
2043 		    mappings_to_slide[i]->sms_size,
2044 		    mappings_to_slide[i]->sms_slide_start,
2045 		    mappings_to_slide[i]->sms_slide_size,
2046 		    slid_mappings[i],
2047 		    slid_file_controls[i],
2048 		    mappings_to_slide[i]->sms_max_prot);
2049 		if (kr != KERN_SUCCESS) {
2050 			SHARED_REGION_TRACE_ERROR(
2051 				("shared_region: region_slide("
2052 				"slide:0x%x start:0x%016llx "
2053 				"size:0x%016llx) failed 0x%x\n",
2054 				shared_region->sr_slide,
2055 				(long long)mappings_to_slide[i]->sms_slide_start,
2056 				(long long)mappings_to_slide[i]->sms_slide_size,
2057 				kr));
2058 			vm_shared_region_undo_mappings(sr_map, shared_region->sr_base_address,
2059 			    &sr_file_mappings[0],
2060 			    &sr_file_mappings[sr_file_mappings_count - 1],
2061 			    sr_file_mappings_count);
2062 			vm_shared_region_lock();
2063 			goto done;
2064 		}
2065 	}
2066 
2067 	assert(kr == KERN_SUCCESS);
2068 
2069 	/* adjust the map's "lowest_unnestable_start" */
2070 	lowest_unnestable_addr &= ~(pmap_shared_region_size_min(sr_map->pmap) - 1);
2071 	if (lowest_unnestable_addr != sr_map->lowest_unnestable_start) {
2072 		vm_map_lock(sr_map);
2073 		sr_map->lowest_unnestable_start = lowest_unnestable_addr;
2074 		vm_map_unlock(sr_map);
2075 	}
2076 
2077 	vm_shared_region_lock();
2078 	assert(shared_region->sr_ref_count > 0);
2079 	assert(shared_region->sr_mapping_in_progress == current_thread());
2080 
2081 	vm_shared_region_map_file_final(shared_region, sr_map, sfm_min_address, sfm_max_address);
2082 
2083 done:
2084 	/*
2085 	 * We're done working on that shared region.
2086 	 * Wake up any waiting threads.
2087 	 */
2088 	assert(shared_region->sr_mapping_in_progress == current_thread());
2089 	shared_region->sr_mapping_in_progress = THREAD_NULL;
2090 	vm_shared_region_wakeup((event_t) &shared_region->sr_mapping_in_progress);
2091 	vm_shared_region_unlock();
2092 
2093 #if __has_feature(ptrauth_calls)
2094 	if (kr == KERN_SUCCESS) {
2095 		/*
2096 		 * Since authenticated mappings were just added to the shared region,
2097 		 * go back and remap them into private mappings for this task.
2098 		 */
2099 		kr = vm_shared_region_auth_remap(shared_region);
2100 	}
2101 #endif /* __has_feature(ptrauth_calls) */
2102 
2103 	/* Cache shared region info needed for telemetry in the task */
2104 	task_t task;
2105 	if (kr == KERN_SUCCESS && (task = current_task())->task_shared_region_slide == -1) {
2106 		mach_vm_offset_t start_address;
2107 		(void)vm_shared_region_start_address(shared_region, &start_address, task);
2108 	}
2109 
2110 	SHARED_REGION_TRACE_DEBUG(
2111 		("shared_region: map(%p) <- 0x%x \n",
2112 		(void *)VM_KERNEL_ADDRPERM(shared_region), kr));
2113 	if (vmsr_num_slides > 0) {
2114 		kfree_data(slid_mappings, vmsr_num_slides * sizeof(*slid_mappings));
2115 		kfree_type(memory_object_control_t, vmsr_num_slides, slid_file_controls);
2116 		kfree_type(struct shared_file_mapping_slide_np *, vmsr_num_slides,
2117 		    mappings_to_slide);
2118 	}
2119 	return kr;
2120 }
2121 
2122 /*
2123  * Final part of vm_shared_region_map_file().
2124  * Kept in separate function to avoid blowing out the stack.
2125  */
2126 __attribute__((noinline))
2127 static void
vm_shared_region_map_file_final(vm_shared_region_t shared_region,vm_map_t sr_map __unused,mach_vm_offset_t sfm_min_address __unused,mach_vm_offset_t sfm_max_address __unused)2128 vm_shared_region_map_file_final(
2129 	vm_shared_region_t        shared_region,
2130 	vm_map_t                  sr_map __unused,
2131 	mach_vm_offset_t          sfm_min_address __unused,
2132 	mach_vm_offset_t          sfm_max_address __unused)
2133 {
2134 	struct _dyld_cache_header sr_cache_header;
2135 	int                       error;
2136 	size_t                    image_array_length;
2137 	struct _dyld_cache_image_text_info *sr_image_layout;
2138 	boolean_t                 locally_built = FALSE;
2139 
2140 
2141 	/*
2142 	 * copy in the shared region UUID to the shared region structure.
2143 	 * we do this indirectly by first copying in the shared cache header
2144 	 * and then copying the UUID from there because we'll need to look
2145 	 * at other content from the shared cache header.
2146 	 */
2147 	if (!shared_region->sr_uuid_copied) {
2148 		error = copyin((user_addr_t)(shared_region->sr_base_address + shared_region->sr_first_mapping),
2149 		    (char *)&sr_cache_header,
2150 		    sizeof(sr_cache_header));
2151 		if (error == 0) {
2152 			memcpy(&shared_region->sr_uuid, &sr_cache_header.uuid, sizeof(shared_region->sr_uuid));
2153 			shared_region->sr_uuid_copied = TRUE;
2154 			locally_built = sr_cache_header.locallyBuiltCache;
2155 		} else {
2156 #if DEVELOPMENT || DEBUG
2157 			panic("shared_region: copyin shared_cache_header(sr_base_addr:0x%016llx sr_first_mapping:0x%016llx "
2158 			    "offset:0 size:0x%016llx) failed with %d\n",
2159 			    (long long)shared_region->sr_base_address,
2160 			    (long long)shared_region->sr_first_mapping,
2161 			    (long long)sizeof(sr_cache_header),
2162 			    error);
2163 #endif /* DEVELOPMENT || DEBUG */
2164 			shared_region->sr_uuid_copied = FALSE;
2165 		}
2166 	}
2167 
2168 	/*
2169 	 * We save a pointer to the shared cache mapped by the "init task", i.e. launchd.  This is used by
2170 	 * the stackshot code to reduce output size in the common case that everything maps the same shared cache.
2171 	 * One gotcha is that "userspace reboots" can occur which can cause a new shared region to be the primary
2172 	 * region.  In that case, launchd re-exec's itself, so we may go through this path multiple times.  We
2173 	 * let the most recent one win.
2174 	 *
2175 	 * Check whether the shared cache is a custom built one and copy in the shared cache layout accordingly.
2176 	 */
2177 	bool is_init_task = (task_pid(current_task()) == 1);
2178 	if (shared_region->sr_uuid_copied && is_init_task) {
2179 		/* Copy in the shared cache layout if we're running with a locally built shared cache */
2180 		if (locally_built) {
2181 			KDBG((MACHDBG_CODE(DBG_MACH_SHAREDREGION, PROCESS_SHARED_CACHE_LAYOUT)) | DBG_FUNC_START);
2182 			image_array_length = (size_t)(sr_cache_header.imagesTextCount * sizeof(struct _dyld_cache_image_text_info));
2183 			sr_image_layout = kalloc_data(image_array_length, Z_WAITOK);
2184 			error = copyin((user_addr_t)(shared_region->sr_base_address + shared_region->sr_first_mapping +
2185 			    sr_cache_header.imagesTextOffset), (char *)sr_image_layout, image_array_length);
2186 			if (error == 0) {
2187 				if (sr_cache_header.imagesTextCount >= UINT32_MAX) {
2188 					panic("shared_region: sr_cache_header.imagesTextCount >= UINT32_MAX");
2189 				}
2190 				shared_region->sr_images = kalloc_data((vm_size_t)(sr_cache_header.imagesTextCount * sizeof(struct dyld_uuid_info_64)), Z_WAITOK);
2191 				for (size_t index = 0; index < sr_cache_header.imagesTextCount; index++) {
2192 					memcpy((char *)&shared_region->sr_images[index].imageUUID, (char *)&sr_image_layout[index].uuid,
2193 					    sizeof(shared_region->sr_images[index].imageUUID));
2194 					shared_region->sr_images[index].imageLoadAddress = sr_image_layout[index].loadAddress;
2195 				}
2196 
2197 				shared_region->sr_images_count = (uint32_t) sr_cache_header.imagesTextCount;
2198 			} else {
2199 #if DEVELOPMENT || DEBUG
2200 				panic("shared_region: copyin shared_cache_layout(sr_base_addr:0x%016llx sr_first_mapping:0x%016llx "
2201 				    "offset:0x%016llx size:0x%016llx) failed with %d\n",
2202 				    (long long)shared_region->sr_base_address,
2203 				    (long long)shared_region->sr_first_mapping,
2204 				    (long long)sr_cache_header.imagesTextOffset,
2205 				    (long long)image_array_length,
2206 				    error);
2207 #endif /* DEVELOPMENT || DEBUG */
2208 			}
2209 			KDBG((MACHDBG_CODE(DBG_MACH_SHAREDREGION, PROCESS_SHARED_CACHE_LAYOUT)) | DBG_FUNC_END, shared_region->sr_images_count);
2210 			kfree_data(sr_image_layout, image_array_length);
2211 			sr_image_layout = NULL;
2212 		}
2213 		primary_system_shared_region = shared_region;
2214 	}
2215 
2216 #ifndef NO_NESTED_PMAP
2217 	/*
2218 	 * If we succeeded, we know the bounds of the shared region.
2219 	 * Trim our pmaps to only cover this range (if applicable to
2220 	 * this platform).
2221 	 */
2222 	if (VM_MAP_PAGE_SHIFT(current_map()) == VM_MAP_PAGE_SHIFT(sr_map)) {
2223 		pmap_trim(current_map()->pmap, sr_map->pmap, sfm_min_address, sfm_max_address - sfm_min_address);
2224 	}
2225 #endif
2226 }
2227 
2228 /*
2229  * Retrieve a task's shared region and grab an extra reference to
2230  * make sure it doesn't disappear while the caller is using it.
2231  * The caller is responsible for consuming that extra reference if
2232  * necessary.
2233  *
2234  * This also tries to trim the pmap for the shared region.
2235  */
2236 vm_shared_region_t
vm_shared_region_trim_and_get(task_t task)2237 vm_shared_region_trim_and_get(task_t task)
2238 {
2239 	vm_shared_region_t shared_region;
2240 	ipc_port_t sr_handle;
2241 	vm_named_entry_t sr_mem_entry;
2242 	vm_map_t sr_map;
2243 
2244 	/* Get the shared region and the map. */
2245 	shared_region = vm_shared_region_get(task);
2246 	if (shared_region == NULL) {
2247 		return NULL;
2248 	}
2249 
2250 	sr_handle = shared_region->sr_mem_entry;
2251 	sr_mem_entry = mach_memory_entry_from_port(sr_handle);
2252 	sr_map = sr_mem_entry->backing.map;
2253 
2254 #ifndef NO_NESTED_PMAP
2255 	/* Trim the pmap if possible. */
2256 	if (VM_MAP_PAGE_SHIFT(task->map) == VM_MAP_PAGE_SHIFT(sr_map)) {
2257 		pmap_trim(task->map->pmap, sr_map->pmap, 0, 0);
2258 	}
2259 #endif
2260 
2261 	return shared_region;
2262 }
2263 
2264 /*
2265  * Enter the appropriate shared region into "map" for "task".
2266  * This involves looking up the shared region (and possibly creating a new
2267  * one) for the desired environment, then mapping the VM sub map into the
2268  * task's VM "map", with the appropriate level of pmap-nesting.
2269  */
2270 kern_return_t
vm_shared_region_enter(struct _vm_map * map,struct task * task,boolean_t is_64bit,void * fsroot,cpu_type_t cpu,cpu_subtype_t cpu_subtype,boolean_t reslide,boolean_t is_driverkit,uint32_t rsr_version)2271 vm_shared_region_enter(
2272 	struct _vm_map          *map,
2273 	struct task             *task,
2274 	boolean_t               is_64bit,
2275 	void                    *fsroot,
2276 	cpu_type_t              cpu,
2277 	cpu_subtype_t           cpu_subtype,
2278 	boolean_t               reslide,
2279 	boolean_t               is_driverkit,
2280 	uint32_t                rsr_version)
2281 {
2282 	kern_return_t           kr;
2283 	vm_shared_region_t      shared_region;
2284 	vm_map_offset_t         sr_address, sr_offset, target_address;
2285 	vm_map_size_t           sr_size, mapping_size;
2286 	vm_map_offset_t         sr_pmap_nesting_start;
2287 	vm_map_size_t           sr_pmap_nesting_size;
2288 	ipc_port_t              sr_handle;
2289 	vm_prot_t               cur_prot, max_prot;
2290 	vm_map_kernel_flags_t   vmk_flags;
2291 
2292 	SHARED_REGION_TRACE_DEBUG(
2293 		("shared_region: -> "
2294 		"enter(map=%p,task=%p,root=%p,cpu=<%d,%d>,64bit=%d,driverkit=%d)\n",
2295 		(void *)VM_KERNEL_ADDRPERM(map),
2296 		(void *)VM_KERNEL_ADDRPERM(task),
2297 		(void *)VM_KERNEL_ADDRPERM(fsroot),
2298 		cpu, cpu_subtype, is_64bit, is_driverkit));
2299 
2300 	/* lookup (create if needed) the shared region for this environment */
2301 	shared_region = vm_shared_region_lookup(fsroot, cpu, cpu_subtype, is_64bit, VM_MAP_PAGE_SHIFT(map), reslide, is_driverkit, rsr_version);
2302 	if (shared_region == NULL) {
2303 		/* this should not happen ! */
2304 		SHARED_REGION_TRACE_ERROR(
2305 			("shared_region: -> "
2306 			"enter(map=%p,task=%p,root=%p,cpu=<%d,%d>,64bit=%d,reslide=%d,driverkit=%d): "
2307 			"lookup failed !\n",
2308 			(void *)VM_KERNEL_ADDRPERM(map),
2309 			(void *)VM_KERNEL_ADDRPERM(task),
2310 			(void *)VM_KERNEL_ADDRPERM(fsroot),
2311 			cpu, cpu_subtype, is_64bit, reslide, is_driverkit));
2312 		//panic("shared_region_enter: lookup failed");
2313 		return KERN_FAILURE;
2314 	}
2315 
2316 	kr = KERN_SUCCESS;
2317 	/* no need to lock since this data is never modified */
2318 	sr_address = (vm_map_offset_t)shared_region->sr_base_address;
2319 	sr_size = (vm_map_size_t)shared_region->sr_size;
2320 	sr_handle = shared_region->sr_mem_entry;
2321 	sr_pmap_nesting_start = (vm_map_offset_t)shared_region->sr_pmap_nesting_start;
2322 	sr_pmap_nesting_size = (vm_map_size_t)shared_region->sr_pmap_nesting_size;
2323 	vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED();
2324 
2325 	cur_prot = VM_PROT_READ;
2326 	if (VM_MAP_POLICY_WRITABLE_SHARED_REGION(map)) {
2327 		/*
2328 		 * XXX BINARY COMPATIBILITY
2329 		 * java6 apparently needs to modify some code in the
2330 		 * dyld shared cache and needs to be allowed to add
2331 		 * write access...
2332 		 */
2333 		max_prot = VM_PROT_ALL;
2334 	} else {
2335 		max_prot = VM_PROT_READ;
2336 		/* make it "permanent" to protect against re-mappings */
2337 		vmk_flags.vmf_permanent = true;
2338 	}
2339 
2340 	/*
2341 	 * Start mapping the shared region's VM sub map into the task's VM map.
2342 	 */
2343 	sr_offset = 0;
2344 
2345 	if (sr_pmap_nesting_start > sr_address) {
2346 		/* we need to map a range without pmap-nesting first */
2347 		target_address = sr_address;
2348 		mapping_size = sr_pmap_nesting_start - sr_address;
2349 		kr = mach_vm_map_kernel(
2350 			map,
2351 			vm_sanitize_wrap_addr_ref(&target_address),
2352 			mapping_size,
2353 			0,
2354 			vmk_flags,
2355 			sr_handle,
2356 			sr_offset,
2357 			TRUE,
2358 			cur_prot,
2359 			max_prot,
2360 			VM_INHERIT_SHARE);
2361 		if (kr != KERN_SUCCESS) {
2362 			SHARED_REGION_TRACE_ERROR(
2363 				("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2364 				"vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2365 				(void *)VM_KERNEL_ADDRPERM(map),
2366 				(void *)VM_KERNEL_ADDRPERM(task),
2367 				(void *)VM_KERNEL_ADDRPERM(fsroot),
2368 				cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2369 				(long long)target_address,
2370 				(long long)mapping_size,
2371 				(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2372 			goto done;
2373 		}
2374 		SHARED_REGION_TRACE_DEBUG(
2375 			("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2376 			"vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2377 			(void *)VM_KERNEL_ADDRPERM(map),
2378 			(void *)VM_KERNEL_ADDRPERM(task),
2379 			(void *)VM_KERNEL_ADDRPERM(fsroot),
2380 			cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2381 			(long long)target_address, (long long)mapping_size,
2382 			(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2383 		sr_offset += mapping_size;
2384 		sr_size -= mapping_size;
2385 	}
2386 
2387 	/* The pmap-nesting is triggered by the "vmkf_nested_pmap" flag. */
2388 	vmk_flags.vmkf_nested_pmap = true;
2389 	vmk_flags.vm_tag = VM_MEMORY_SHARED_PMAP;
2390 
2391 	/*
2392 	 * Use pmap-nesting to map the majority of the shared region into the task's
2393 	 * VM space. Very rarely will architectures have a shared region that isn't
2394 	 * the same size as the pmap-nesting region, or start at a different address
2395 	 * than the pmap-nesting region, so this code will map the entirety of the
2396 	 * shared region for most architectures.
2397 	 */
2398 	assert((sr_address + sr_offset) == sr_pmap_nesting_start);
2399 	target_address = sr_pmap_nesting_start;
2400 	kr = mach_vm_map_kernel(
2401 		map,
2402 		vm_sanitize_wrap_addr_ref(&target_address),
2403 		sr_pmap_nesting_size,
2404 		0,
2405 		vmk_flags,
2406 		sr_handle,
2407 		sr_offset,
2408 		TRUE,
2409 		cur_prot,
2410 		max_prot,
2411 		VM_INHERIT_SHARE);
2412 	if (kr != KERN_SUCCESS) {
2413 		SHARED_REGION_TRACE_ERROR(
2414 			("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2415 			"vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2416 			(void *)VM_KERNEL_ADDRPERM(map),
2417 			(void *)VM_KERNEL_ADDRPERM(task),
2418 			(void *)VM_KERNEL_ADDRPERM(fsroot),
2419 			cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2420 			(long long)target_address,
2421 			(long long)sr_pmap_nesting_size,
2422 			(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2423 		goto done;
2424 	}
2425 	SHARED_REGION_TRACE_DEBUG(
2426 		("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2427 		"nested vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2428 		(void *)VM_KERNEL_ADDRPERM(map),
2429 		(void *)VM_KERNEL_ADDRPERM(task),
2430 		(void *)VM_KERNEL_ADDRPERM(fsroot),
2431 		cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2432 		(long long)target_address, (long long)sr_pmap_nesting_size,
2433 		(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2434 
2435 	sr_offset += sr_pmap_nesting_size;
2436 	sr_size -= sr_pmap_nesting_size;
2437 
2438 	if (sr_size > 0) {
2439 		/* and there's some left to be mapped without pmap-nesting */
2440 		vmk_flags.vmkf_nested_pmap = false; /* no pmap nesting */
2441 		target_address = sr_address + sr_offset;
2442 		mapping_size = sr_size;
2443 		kr = mach_vm_map_kernel(
2444 			map,
2445 			vm_sanitize_wrap_addr_ref(&target_address),
2446 			mapping_size,
2447 			0,
2448 			VM_MAP_KERNEL_FLAGS_FIXED(),
2449 			sr_handle,
2450 			sr_offset,
2451 			TRUE,
2452 			cur_prot,
2453 			max_prot,
2454 			VM_INHERIT_SHARE);
2455 		if (kr != KERN_SUCCESS) {
2456 			SHARED_REGION_TRACE_ERROR(
2457 				("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2458 				"vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2459 				(void *)VM_KERNEL_ADDRPERM(map),
2460 				(void *)VM_KERNEL_ADDRPERM(task),
2461 				(void *)VM_KERNEL_ADDRPERM(fsroot),
2462 				cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2463 				(long long)target_address,
2464 				(long long)mapping_size,
2465 				(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2466 			goto done;
2467 		}
2468 		SHARED_REGION_TRACE_DEBUG(
2469 			("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d): "
2470 			"vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
2471 			(void *)VM_KERNEL_ADDRPERM(map),
2472 			(void *)VM_KERNEL_ADDRPERM(task),
2473 			(void *)VM_KERNEL_ADDRPERM(fsroot),
2474 			cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2475 			(long long)target_address, (long long)mapping_size,
2476 			(void *)VM_KERNEL_ADDRPERM(sr_handle), kr));
2477 		sr_offset += mapping_size;
2478 		sr_size -= mapping_size;
2479 	}
2480 	assert(sr_size == 0);
2481 
2482 done:
2483 	if (kr == KERN_SUCCESS) {
2484 		/* let the task use that shared region */
2485 		vm_shared_region_set(task, shared_region);
2486 	} else {
2487 		/* drop our reference since we're not using it */
2488 		vm_shared_region_deallocate(shared_region);
2489 		vm_shared_region_set(task, NULL);
2490 	}
2491 
2492 	SHARED_REGION_TRACE_DEBUG(
2493 		("shared_region: enter(%p,%p,%p,%d,%d,%d,%d,%d) <- 0x%x\n",
2494 		(void *)VM_KERNEL_ADDRPERM(map),
2495 		(void *)VM_KERNEL_ADDRPERM(task),
2496 		(void *)VM_KERNEL_ADDRPERM(fsroot),
2497 		cpu, cpu_subtype, is_64bit, reslide, is_driverkit,
2498 		kr));
2499 	return kr;
2500 }
2501 
2502 void
vm_shared_region_remove(task_t task,vm_shared_region_t sr)2503 vm_shared_region_remove(
2504 	task_t task,
2505 	vm_shared_region_t sr)
2506 {
2507 	vm_map_t map;
2508 	mach_vm_offset_t start;
2509 	mach_vm_size_t size;
2510 	vm_map_kernel_flags_t vmk_flags;
2511 	kern_return_t kr;
2512 
2513 	if (sr == NULL) {
2514 		return;
2515 	}
2516 	map = get_task_map(task);
2517 	start = sr->sr_base_address;
2518 	size = sr->sr_size;
2519 
2520 	vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true);
2521 	vmk_flags.vmkf_overwrite_immutable = true;
2522 	vmk_flags.vm_tag = VM_MEMORY_DYLD;
2523 
2524 	/* range_id is set by mach_vm_map_kernel */
2525 	kr = mach_vm_map_kernel(map,
2526 	    vm_sanitize_wrap_addr_ref(&start),
2527 	    size,
2528 	    0,                     /* mask */
2529 	    vmk_flags,
2530 	    MACH_PORT_NULL,
2531 	    0,
2532 	    FALSE,                     /* copy */
2533 	    VM_PROT_NONE,
2534 	    VM_PROT_NONE,
2535 	    VM_INHERIT_DEFAULT);
2536 	if (kr != KERN_SUCCESS) {
2537 		printf("%s:%d vm_map(0x%llx, 0x%llx) error %d\n", __FUNCTION__, __LINE__, (uint64_t)sr->sr_base_address, (uint64_t)size, kr);
2538 	}
2539 }
2540 
2541 #define SANE_SLIDE_INFO_SIZE            (2560*1024) /*Can be changed if needed*/
2542 
2543 kern_return_t
vm_shared_region_sliding_valid(uint32_t slide)2544 vm_shared_region_sliding_valid(uint32_t slide)
2545 {
2546 	kern_return_t kr = KERN_SUCCESS;
2547 	vm_shared_region_t sr = vm_shared_region_get(current_task());
2548 
2549 	/* No region yet? we're fine. */
2550 	if (sr == NULL) {
2551 		return kr;
2552 	}
2553 
2554 	if (sr->sr_slide != 0 && slide != 0) {
2555 		if (slide == sr->sr_slide) {
2556 			/*
2557 			 * Request for sliding when we've
2558 			 * already done it with exactly the
2559 			 * same slide value before.
2560 			 * This isn't wrong technically but
2561 			 * we don't want to slide again and
2562 			 * so we return this value.
2563 			 */
2564 			kr = KERN_INVALID_ARGUMENT;
2565 		} else {
2566 			printf("Mismatched shared region slide\n");
2567 			kr = KERN_FAILURE;
2568 		}
2569 	}
2570 	vm_shared_region_deallocate(sr);
2571 	return kr;
2572 }
2573 
2574 /*
2575  * Actually create (really overwrite) the mapping to part of the shared cache which
2576  * undergoes relocation.  This routine reads in the relocation info from dyld and
2577  * verifies it. It then creates a (or finds a matching) shared region pager which
2578  * handles the actual modification of the page contents and installs the mapping
2579  * using that pager.
2580  */
2581 kern_return_t
vm_shared_region_slide_mapping(vm_shared_region_t sr,user_addr_t slide_info_addr,mach_vm_size_t slide_info_size,mach_vm_offset_t start,mach_vm_size_t size,mach_vm_offset_t slid_mapping,uint32_t slide,memory_object_control_t sr_file_control,vm_prot_t prot)2582 vm_shared_region_slide_mapping(
2583 	vm_shared_region_t      sr,
2584 	user_addr_t             slide_info_addr,
2585 	mach_vm_size_t          slide_info_size,
2586 	mach_vm_offset_t        start,
2587 	mach_vm_size_t          size,
2588 	mach_vm_offset_t        slid_mapping,
2589 	uint32_t                slide,
2590 	memory_object_control_t sr_file_control,
2591 	vm_prot_t               prot)
2592 {
2593 	kern_return_t           kr;
2594 	vm_object_t             object = VM_OBJECT_NULL;
2595 	vm_shared_region_slide_info_t si = NULL;
2596 	vm_map_entry_t          tmp_entry = VM_MAP_ENTRY_NULL;
2597 	struct vm_map_entry     tmp_entry_store;
2598 	memory_object_t         sr_pager = MEMORY_OBJECT_NULL;
2599 	vm_map_t                sr_map;
2600 	vm_map_kernel_flags_t   vmk_flags;
2601 	vm_map_offset_t         map_addr;
2602 	void                    *slide_info_entry = NULL;
2603 	int                     error;
2604 
2605 	assert(sr->sr_slide_in_progress);
2606 
2607 	if (sr_file_control == MEMORY_OBJECT_CONTROL_NULL) {
2608 		return KERN_INVALID_ARGUMENT;
2609 	}
2610 
2611 	/*
2612 	 * Copy in and verify the relocation information.
2613 	 */
2614 	if (slide_info_size < MIN_SLIDE_INFO_SIZE) {
2615 		printf("Slide_info_size too small: %lx\n", (uintptr_t)slide_info_size);
2616 		return KERN_FAILURE;
2617 	}
2618 	if (slide_info_size > SANE_SLIDE_INFO_SIZE) {
2619 		printf("Slide_info_size too large: %lx\n", (uintptr_t)slide_info_size);
2620 		return KERN_FAILURE;
2621 	}
2622 
2623 	slide_info_entry = kalloc_data((vm_size_t)slide_info_size, Z_WAITOK);
2624 	if (slide_info_entry == NULL) {
2625 		return KERN_RESOURCE_SHORTAGE;
2626 	}
2627 	error = copyin(slide_info_addr, slide_info_entry, (size_t)slide_info_size);
2628 	if (error) {
2629 		printf("copyin of slide_info failed\n");
2630 		kr = KERN_INVALID_ADDRESS;
2631 		goto done;
2632 	}
2633 
2634 	if ((kr = vm_shared_region_slide_sanity_check(slide_info_entry, slide_info_size)) != KERN_SUCCESS) {
2635 		printf("Sanity Check failed for slide_info\n");
2636 		goto done;
2637 	}
2638 
2639 	/*
2640 	 * Allocate and fill in a vm_shared_region_slide_info.
2641 	 * This will either be used by a new pager, or used to find
2642 	 * a pre-existing matching pager.
2643 	 */
2644 	object = memory_object_control_to_vm_object(sr_file_control);
2645 	if (object == VM_OBJECT_NULL || object->internal) {
2646 		object = VM_OBJECT_NULL;
2647 		kr = KERN_INVALID_ADDRESS;
2648 		goto done;
2649 	}
2650 
2651 	si = kalloc_type(struct vm_shared_region_slide_info,
2652 	    Z_WAITOK | Z_NOFAIL);
2653 	vm_object_lock(object);
2654 
2655 	vm_object_reference_locked(object);     /* for si->slide_object */
2656 	object->object_is_shared_cache = TRUE;
2657 	vm_object_unlock(object);
2658 
2659 	si->si_slide_info_entry = slide_info_entry;
2660 	si->si_slide_info_size = slide_info_size;
2661 
2662 	assert(slid_mapping != (mach_vm_offset_t) -1);
2663 	si->si_slid_address = slid_mapping + sr->sr_base_address;
2664 	si->si_slide_object = object;
2665 	si->si_start = start;
2666 	si->si_end = si->si_start + size;
2667 	si->si_slide = slide;
2668 #if __has_feature(ptrauth_calls)
2669 	/*
2670 	 * If there is authenticated pointer data in this slid mapping,
2671 	 * then just add the information needed to create new pagers for
2672 	 * different shared_region_id's later.
2673 	 */
2674 	if (sr->sr_cpu_type == CPU_TYPE_ARM64 &&
2675 	    sr->sr_cpu_subtype == CPU_SUBTYPE_ARM64E &&
2676 	    !(prot & VM_PROT_NOAUTH)) {
2677 		if (sr->sr_next_auth_section == sr->sr_num_auth_section) {
2678 			printf("Too many auth/private sections for shared region!!\n");
2679 			kr = KERN_INVALID_ARGUMENT;
2680 			goto done;
2681 		}
2682 		si->si_ptrauth = TRUE;
2683 		sr->sr_auth_section[sr->sr_next_auth_section++] = si;
2684 		/*
2685 		 * Remember the shared region, since that's where we'll
2686 		 * stash this info for all auth pagers to share. Each pager
2687 		 * will need to take a reference to it.
2688 		 */
2689 		si->si_shared_region = sr;
2690 		kr = KERN_SUCCESS;
2691 		goto done;
2692 	}
2693 	si->si_shared_region = NULL;
2694 	si->si_ptrauth = FALSE;
2695 #endif /* __has_feature(ptrauth_calls) */
2696 
2697 	/*
2698 	 * find the pre-existing shared region's map entry to slide
2699 	 */
2700 	sr_map = vm_shared_region_vm_map(sr);
2701 	kr = find_mapping_to_slide(sr_map, (vm_map_address_t)slid_mapping, &tmp_entry_store);
2702 	if (kr != KERN_SUCCESS) {
2703 		goto done;
2704 	}
2705 	tmp_entry = &tmp_entry_store;
2706 
2707 	/*
2708 	 * The object must exactly cover the region to slide.
2709 	 */
2710 	assert(VME_OFFSET(tmp_entry) == start);
2711 	assert(tmp_entry->vme_end - tmp_entry->vme_start == size);
2712 
2713 	/* create a "shared_region" sliding pager */
2714 	sr_pager = shared_region_pager_setup(VME_OBJECT(tmp_entry), VME_OFFSET(tmp_entry), si, 0);
2715 	if (sr_pager == MEMORY_OBJECT_NULL) {
2716 		kr = KERN_RESOURCE_SHORTAGE;
2717 		goto done;
2718 	}
2719 
2720 #if CONFIG_SECLUDED_MEMORY
2721 	/*
2722 	 * The shared region pagers used by camera or DEXT should have
2723 	 * pagers that won't go on the secluded queue.
2724 	 */
2725 	if (primary_system_shared_region == NULL ||
2726 	    primary_system_shared_region == sr ||
2727 	    sr->sr_driverkit) {
2728 		memory_object_mark_eligible_for_secluded(sr_pager->mo_control, FALSE);
2729 	}
2730 #endif /* CONFIG_SECLUDED_MEMORY */
2731 
2732 	/* map that pager over the portion of the mapping that needs sliding */
2733 	map_addr = tmp_entry->vme_start;
2734 	vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true);
2735 	vmk_flags.vmkf_overwrite_immutable = true;
2736 	vmk_flags.vmf_permanent = shared_region_make_permanent(sr,
2737 	    tmp_entry->max_protection);
2738 	vmk_flags.vmf_tpro = shared_region_tpro_protect(sr,
2739 	    prot);
2740 	kr = mach_vm_map_kernel(sr_map,
2741 	    vm_sanitize_wrap_addr_ref(&map_addr),
2742 	    tmp_entry->vme_end - tmp_entry->vme_start,
2743 	    0,
2744 	    vmk_flags,
2745 	    (ipc_port_t)(uintptr_t) sr_pager,
2746 	    0,
2747 	    TRUE,
2748 	    tmp_entry->protection,
2749 	    tmp_entry->max_protection,
2750 	    tmp_entry->inheritance);
2751 	assertf(kr == KERN_SUCCESS, "kr = 0x%x\n", kr);
2752 	assertf(map_addr == tmp_entry->vme_start,
2753 	    "map_addr=0x%llx vme_start=0x%llx tmp_entry=%p\n",
2754 	    (uint64_t)map_addr,
2755 	    (uint64_t) tmp_entry->vme_start,
2756 	    tmp_entry);
2757 
2758 	/* success! */
2759 	kr = KERN_SUCCESS;
2760 
2761 done:
2762 	if (sr_pager != NULL) {
2763 		/*
2764 		 * Release the sr_pager reference obtained by shared_region_pager_setup().
2765 		 * The mapping, if it succeeded, is now holding a reference on the memory object.
2766 		 */
2767 		memory_object_deallocate(sr_pager);
2768 		sr_pager = MEMORY_OBJECT_NULL;
2769 	}
2770 	if (tmp_entry != NULL) {
2771 		/* release extra ref on tmp_entry's VM object */
2772 		vm_object_deallocate(VME_OBJECT(tmp_entry));
2773 		tmp_entry = VM_MAP_ENTRY_NULL;
2774 	}
2775 
2776 	if (kr != KERN_SUCCESS) {
2777 		/* cleanup */
2778 		if (si != NULL) {
2779 			if (si->si_slide_object) {
2780 				vm_object_deallocate(si->si_slide_object);
2781 				si->si_slide_object = VM_OBJECT_NULL;
2782 			}
2783 			kfree_type(struct vm_shared_region_slide_info, si);
2784 			si = NULL;
2785 		}
2786 		if (slide_info_entry != NULL) {
2787 			kfree_data(slide_info_entry, (vm_size_t)slide_info_size);
2788 			slide_info_entry = NULL;
2789 		}
2790 	}
2791 	return kr;
2792 }
2793 
2794 static kern_return_t
vm_shared_region_slide_sanity_check_v1(vm_shared_region_slide_info_entry_v1_t s_info)2795 vm_shared_region_slide_sanity_check_v1(
2796 	vm_shared_region_slide_info_entry_v1_t s_info)
2797 {
2798 	uint32_t pageIndex = 0;
2799 	uint16_t entryIndex = 0;
2800 	uint16_t *toc = NULL;
2801 
2802 	toc = (uint16_t*)((uintptr_t)s_info + s_info->toc_offset);
2803 	for (; pageIndex < s_info->toc_count; pageIndex++) {
2804 		entryIndex =  (uint16_t)(toc[pageIndex]);
2805 
2806 		if (entryIndex >= s_info->entry_count) {
2807 			printf("No sliding bitmap entry for pageIndex: %d at entryIndex: %d amongst %d entries\n", pageIndex, entryIndex, s_info->entry_count);
2808 			return KERN_FAILURE;
2809 		}
2810 	}
2811 	return KERN_SUCCESS;
2812 }
2813 
2814 static kern_return_t
vm_shared_region_slide_sanity_check_v2(vm_shared_region_slide_info_entry_v2_t s_info,mach_vm_size_t slide_info_size)2815 vm_shared_region_slide_sanity_check_v2(
2816 	vm_shared_region_slide_info_entry_v2_t s_info,
2817 	mach_vm_size_t slide_info_size)
2818 {
2819 	if (slide_info_size < sizeof(struct vm_shared_region_slide_info_entry_v2)) {
2820 		printf("%s bad slide_info_size: %lx\n", __func__, (uintptr_t)slide_info_size);
2821 		return KERN_FAILURE;
2822 	}
2823 	if (s_info->page_size != PAGE_SIZE_FOR_SR_SLIDE) {
2824 		return KERN_FAILURE;
2825 	}
2826 
2827 	/* Ensure that the slide info doesn't reference any data outside of its bounds. */
2828 
2829 	uint32_t page_starts_count = s_info->page_starts_count;
2830 	uint32_t page_extras_count = s_info->page_extras_count;
2831 	mach_vm_size_t num_trailing_entries = page_starts_count + page_extras_count;
2832 	if (num_trailing_entries < page_starts_count) {
2833 		return KERN_FAILURE;
2834 	}
2835 
2836 	/* Scale by sizeof(uint16_t). Hard-coding the size simplifies the overflow check. */
2837 	mach_vm_size_t trailing_size = num_trailing_entries << 1;
2838 	if (trailing_size >> 1 != num_trailing_entries) {
2839 		return KERN_FAILURE;
2840 	}
2841 
2842 	mach_vm_size_t required_size = sizeof(*s_info) + trailing_size;
2843 	if (required_size < sizeof(*s_info)) {
2844 		return KERN_FAILURE;
2845 	}
2846 
2847 	if (required_size > slide_info_size) {
2848 		return KERN_FAILURE;
2849 	}
2850 
2851 	return KERN_SUCCESS;
2852 }
2853 
2854 static kern_return_t
vm_shared_region_slide_sanity_check_v3(vm_shared_region_slide_info_entry_v3_t s_info,mach_vm_size_t slide_info_size)2855 vm_shared_region_slide_sanity_check_v3(
2856 	vm_shared_region_slide_info_entry_v3_t s_info,
2857 	mach_vm_size_t slide_info_size)
2858 {
2859 	if (slide_info_size < sizeof(struct vm_shared_region_slide_info_entry_v3)) {
2860 		printf("%s bad slide_info_size: %lx\n", __func__, (uintptr_t)slide_info_size);
2861 		return KERN_FAILURE;
2862 	}
2863 	if (s_info->page_size != PAGE_SIZE_FOR_SR_SLIDE) {
2864 		printf("vm_shared_region_slide_sanity_check_v3: s_info->page_size != PAGE_SIZE_FOR_SR_SL 0x%llx != 0x%llx\n", (uint64_t)s_info->page_size, (uint64_t)PAGE_SIZE_FOR_SR_SLIDE);
2865 		return KERN_FAILURE;
2866 	}
2867 
2868 	uint32_t page_starts_count = s_info->page_starts_count;
2869 	mach_vm_size_t num_trailing_entries = page_starts_count;
2870 	mach_vm_size_t trailing_size = num_trailing_entries << 1;
2871 	mach_vm_size_t required_size = sizeof(*s_info) + trailing_size;
2872 	if (required_size < sizeof(*s_info)) {
2873 		printf("vm_shared_region_slide_sanity_check_v3: required_size != sizeof(*s_info) 0x%llx != 0x%llx\n", (uint64_t)required_size, (uint64_t)sizeof(*s_info));
2874 		return KERN_FAILURE;
2875 	}
2876 
2877 	if (required_size > slide_info_size) {
2878 		printf("vm_shared_region_slide_sanity_check_v3: required_size != slide_info_size 0x%llx != 0x%llx\n", (uint64_t)required_size, (uint64_t)slide_info_size);
2879 		return KERN_FAILURE;
2880 	}
2881 
2882 	return KERN_SUCCESS;
2883 }
2884 
2885 static kern_return_t
vm_shared_region_slide_sanity_check_v4(vm_shared_region_slide_info_entry_v4_t s_info,mach_vm_size_t slide_info_size)2886 vm_shared_region_slide_sanity_check_v4(
2887 	vm_shared_region_slide_info_entry_v4_t s_info,
2888 	mach_vm_size_t slide_info_size)
2889 {
2890 	if (slide_info_size < sizeof(struct vm_shared_region_slide_info_entry_v4)) {
2891 		printf("%s bad slide_info_size: %lx\n", __func__, (uintptr_t)slide_info_size);
2892 		return KERN_FAILURE;
2893 	}
2894 	if (s_info->page_size != PAGE_SIZE_FOR_SR_SLIDE) {
2895 		return KERN_FAILURE;
2896 	}
2897 
2898 	/* Ensure that the slide info doesn't reference any data outside of its bounds. */
2899 
2900 	uint32_t page_starts_count = s_info->page_starts_count;
2901 	uint32_t page_extras_count = s_info->page_extras_count;
2902 	mach_vm_size_t num_trailing_entries = page_starts_count + page_extras_count;
2903 	if (num_trailing_entries < page_starts_count) {
2904 		return KERN_FAILURE;
2905 	}
2906 
2907 	/* Scale by sizeof(uint16_t). Hard-coding the size simplifies the overflow check. */
2908 	mach_vm_size_t trailing_size = num_trailing_entries << 1;
2909 	if (trailing_size >> 1 != num_trailing_entries) {
2910 		return KERN_FAILURE;
2911 	}
2912 
2913 	mach_vm_size_t required_size = sizeof(*s_info) + trailing_size;
2914 	if (required_size < sizeof(*s_info)) {
2915 		return KERN_FAILURE;
2916 	}
2917 
2918 	if (required_size > slide_info_size) {
2919 		return KERN_FAILURE;
2920 	}
2921 
2922 	return KERN_SUCCESS;
2923 }
2924 
2925 static kern_return_t
vm_shared_region_slide_sanity_check_v5(vm_shared_region_slide_info_entry_v5_t s_info,mach_vm_size_t slide_info_size)2926 vm_shared_region_slide_sanity_check_v5(
2927 	vm_shared_region_slide_info_entry_v5_t s_info,
2928 	mach_vm_size_t slide_info_size)
2929 {
2930 	if (slide_info_size < sizeof(struct vm_shared_region_slide_info_entry_v5)) {
2931 		printf("%s bad slide_info_size: %lx\n", __func__, (uintptr_t)slide_info_size);
2932 		return KERN_FAILURE;
2933 	}
2934 	if (s_info->page_size != PAGE_SIZE_FOR_SR_SLIDE_16KB) {
2935 		printf("vm_shared_region_slide_sanity_check_v5: s_info->page_size != PAGE_SIZE_FOR_SR_SL 0x%llx != 0x%llx\n", (uint64_t)s_info->page_size, (uint64_t)PAGE_SIZE_FOR_SR_SLIDE_16KB);
2936 		return KERN_FAILURE;
2937 	}
2938 
2939 	uint32_t page_starts_count = s_info->page_starts_count;
2940 	mach_vm_size_t num_trailing_entries = page_starts_count;
2941 	mach_vm_size_t trailing_size = num_trailing_entries << 1;
2942 	mach_vm_size_t required_size = sizeof(*s_info) + trailing_size;
2943 	if (required_size < sizeof(*s_info)) {
2944 		printf("vm_shared_region_slide_sanity_check_v5: required_size != sizeof(*s_info) 0x%llx != 0x%llx\n", (uint64_t)required_size, (uint64_t)sizeof(*s_info));
2945 		return KERN_FAILURE;
2946 	}
2947 
2948 	if (required_size > slide_info_size) {
2949 		printf("vm_shared_region_slide_sanity_check_v5: required_size != slide_info_size 0x%llx != 0x%llx\n", (uint64_t)required_size, (uint64_t)slide_info_size);
2950 		return KERN_FAILURE;
2951 	}
2952 
2953 	return KERN_SUCCESS;
2954 }
2955 
2956 
2957 static kern_return_t
vm_shared_region_slide_sanity_check(vm_shared_region_slide_info_entry_t s_info,mach_vm_size_t s_info_size)2958 vm_shared_region_slide_sanity_check(
2959 	vm_shared_region_slide_info_entry_t s_info,
2960 	mach_vm_size_t s_info_size)
2961 {
2962 	kern_return_t kr;
2963 
2964 	switch (s_info->version) {
2965 	case 1:
2966 		kr = vm_shared_region_slide_sanity_check_v1(&s_info->v1);
2967 		break;
2968 	case 2:
2969 		kr = vm_shared_region_slide_sanity_check_v2(&s_info->v2, s_info_size);
2970 		break;
2971 	case 3:
2972 		kr = vm_shared_region_slide_sanity_check_v3(&s_info->v3, s_info_size);
2973 		break;
2974 	case 4:
2975 		kr = vm_shared_region_slide_sanity_check_v4(&s_info->v4, s_info_size);
2976 		break;
2977 	case 5:
2978 		kr = vm_shared_region_slide_sanity_check_v5(&s_info->v5, s_info_size);
2979 		break;
2980 	default:
2981 		kr = KERN_FAILURE;
2982 	}
2983 	return kr;
2984 }
2985 
2986 static kern_return_t
vm_shared_region_slide_page_v1(vm_shared_region_slide_info_t si,vm_offset_t vaddr,uint32_t pageIndex)2987 vm_shared_region_slide_page_v1(vm_shared_region_slide_info_t si, vm_offset_t vaddr, uint32_t pageIndex)
2988 {
2989 	uint16_t *toc = NULL;
2990 	slide_info_entry_toc_t bitmap = NULL;
2991 	uint32_t i = 0, j = 0;
2992 	uint8_t b = 0;
2993 	uint32_t slide = si->si_slide;
2994 	int is_64 = task_has_64Bit_addr(current_task());
2995 
2996 	vm_shared_region_slide_info_entry_v1_t s_info = &si->si_slide_info_entry->v1;
2997 	toc = (uint16_t*)((uintptr_t)s_info + s_info->toc_offset);
2998 
2999 	if (pageIndex >= s_info->toc_count) {
3000 		printf("No slide entry for this page in toc. PageIndex: %d Toc Count: %d\n", pageIndex, s_info->toc_count);
3001 	} else {
3002 		uint16_t entryIndex =  (uint16_t)(toc[pageIndex]);
3003 		slide_info_entry_toc_t slide_info_entries = (slide_info_entry_toc_t)((uintptr_t)s_info + s_info->entry_offset);
3004 
3005 		if (entryIndex >= s_info->entry_count) {
3006 			printf("No sliding bitmap entry for entryIndex: %d amongst %d entries\n", entryIndex, s_info->entry_count);
3007 		} else {
3008 			bitmap = &slide_info_entries[entryIndex];
3009 
3010 			for (i = 0; i < NUM_SLIDING_BITMAPS_PER_PAGE; ++i) {
3011 				b = bitmap->entry[i];
3012 				if (b != 0) {
3013 					for (j = 0; j < 8; ++j) {
3014 						if (b & (1 << j)) {
3015 							uint32_t *ptr_to_slide;
3016 							uint32_t old_value;
3017 
3018 							ptr_to_slide = (uint32_t*)((uintptr_t)(vaddr) + (sizeof(uint32_t) * (i * 8 + j)));
3019 							old_value = *ptr_to_slide;
3020 							*ptr_to_slide += slide;
3021 							if (is_64 && *ptr_to_slide < old_value) {
3022 								/*
3023 								 * We just slid the low 32 bits of a 64-bit pointer
3024 								 * and it looks like there should have been a carry-over
3025 								 * to the upper 32 bits.
3026 								 * The sliding failed...
3027 								 */
3028 								printf("vm_shared_region_slide() carry over: i=%d j=%d b=0x%x slide=0x%x old=0x%x new=0x%x\n",
3029 								    i, j, b, slide, old_value, *ptr_to_slide);
3030 								return KERN_FAILURE;
3031 							}
3032 						}
3033 					}
3034 				}
3035 			}
3036 		}
3037 	}
3038 
3039 	return KERN_SUCCESS;
3040 }
3041 
3042 static kern_return_t
rebase_chain_32(uint8_t * page_content,uint16_t start_offset,uint32_t slide_amount,vm_shared_region_slide_info_entry_v2_t s_info)3043 rebase_chain_32(
3044 	uint8_t *page_content,
3045 	uint16_t start_offset,
3046 	uint32_t slide_amount,
3047 	vm_shared_region_slide_info_entry_v2_t s_info)
3048 {
3049 	const uint32_t last_page_offset = PAGE_SIZE_FOR_SR_SLIDE - sizeof(uint32_t);
3050 
3051 	const uint32_t delta_mask = (uint32_t)(s_info->delta_mask);
3052 	const uint32_t value_mask = ~delta_mask;
3053 	const uint32_t value_add = (uint32_t)(s_info->value_add);
3054 	const uint32_t delta_shift = __builtin_ctzll(delta_mask) - 2;
3055 
3056 	uint32_t page_offset = start_offset;
3057 	uint32_t delta = 1;
3058 
3059 	while (delta != 0 && page_offset <= last_page_offset) {
3060 		uint8_t *loc;
3061 		uint32_t value;
3062 
3063 		loc = page_content + page_offset;
3064 		memcpy(&value, loc, sizeof(value));
3065 		delta = (value & delta_mask) >> delta_shift;
3066 		value &= value_mask;
3067 
3068 		if (value != 0) {
3069 			value += value_add;
3070 			value += slide_amount;
3071 		}
3072 		memcpy(loc, &value, sizeof(value));
3073 		page_offset += delta;
3074 	}
3075 
3076 	/* If the offset went past the end of the page, then the slide data is invalid. */
3077 	if (page_offset > last_page_offset) {
3078 		return KERN_FAILURE;
3079 	}
3080 	return KERN_SUCCESS;
3081 }
3082 
3083 static kern_return_t
rebase_chain_64(uint8_t * page_content,uint16_t start_offset,uint32_t slide_amount,vm_shared_region_slide_info_entry_v2_t s_info)3084 rebase_chain_64(
3085 	uint8_t *page_content,
3086 	uint16_t start_offset,
3087 	uint32_t slide_amount,
3088 	vm_shared_region_slide_info_entry_v2_t s_info)
3089 {
3090 	const uint32_t last_page_offset = PAGE_SIZE_FOR_SR_SLIDE - sizeof(uint64_t);
3091 
3092 	const uint64_t delta_mask = s_info->delta_mask;
3093 	const uint64_t value_mask = ~delta_mask;
3094 	const uint64_t value_add = s_info->value_add;
3095 	const uint64_t delta_shift = __builtin_ctzll(delta_mask) - 2;
3096 
3097 	uint32_t page_offset = start_offset;
3098 	uint32_t delta = 1;
3099 
3100 	while (delta != 0 && page_offset <= last_page_offset) {
3101 		uint8_t *loc;
3102 		uint64_t value;
3103 
3104 		loc = page_content + page_offset;
3105 		memcpy(&value, loc, sizeof(value));
3106 		delta = (uint32_t)((value & delta_mask) >> delta_shift);
3107 		value &= value_mask;
3108 
3109 		if (value != 0) {
3110 			value += value_add;
3111 			value += slide_amount;
3112 		}
3113 		memcpy(loc, &value, sizeof(value));
3114 		page_offset += delta;
3115 	}
3116 
3117 	if (page_offset + sizeof(uint32_t) == PAGE_SIZE_FOR_SR_SLIDE) {
3118 		/* If a pointer straddling the page boundary needs to be adjusted, then
3119 		 * add the slide to the lower half. The encoding guarantees that the upper
3120 		 * half on the next page will need no masking.
3121 		 *
3122 		 * This assumes a little-endian machine and that the region being slid
3123 		 * never crosses a 4 GB boundary. */
3124 
3125 		uint8_t *loc = page_content + page_offset;
3126 		uint32_t value;
3127 
3128 		memcpy(&value, loc, sizeof(value));
3129 		value += slide_amount;
3130 		memcpy(loc, &value, sizeof(value));
3131 	} else if (page_offset > last_page_offset) {
3132 		return KERN_FAILURE;
3133 	}
3134 
3135 	return KERN_SUCCESS;
3136 }
3137 
3138 static kern_return_t
rebase_chain(boolean_t is_64,uint32_t pageIndex,uint8_t * page_content,uint16_t start_offset,uint32_t slide_amount,vm_shared_region_slide_info_entry_v2_t s_info)3139 rebase_chain(
3140 	boolean_t is_64,
3141 	uint32_t pageIndex,
3142 	uint8_t *page_content,
3143 	uint16_t start_offset,
3144 	uint32_t slide_amount,
3145 	vm_shared_region_slide_info_entry_v2_t s_info)
3146 {
3147 	kern_return_t kr;
3148 	if (is_64) {
3149 		kr = rebase_chain_64(page_content, start_offset, slide_amount, s_info);
3150 	} else {
3151 		kr = rebase_chain_32(page_content, start_offset, slide_amount, s_info);
3152 	}
3153 
3154 	if (kr != KERN_SUCCESS) {
3155 		printf("vm_shared_region_slide_page() offset overflow: pageIndex=%u, start_offset=%u, slide_amount=%u\n",
3156 		    pageIndex, start_offset, slide_amount);
3157 	}
3158 	return kr;
3159 }
3160 
3161 static kern_return_t
vm_shared_region_slide_page_v2(vm_shared_region_slide_info_t si,vm_offset_t vaddr,uint32_t pageIndex)3162 vm_shared_region_slide_page_v2(vm_shared_region_slide_info_t si, vm_offset_t vaddr, uint32_t pageIndex)
3163 {
3164 	vm_shared_region_slide_info_entry_v2_t s_info = &si->si_slide_info_entry->v2;
3165 	const uint32_t slide_amount = si->si_slide;
3166 
3167 	/* The high bits of the delta_mask field are nonzero precisely when the shared
3168 	 * cache is 64-bit. */
3169 	const boolean_t is_64 = (s_info->delta_mask >> 32) != 0;
3170 
3171 	const uint16_t *page_starts = (uint16_t *)((uintptr_t)s_info + s_info->page_starts_offset);
3172 	const uint16_t *page_extras = (uint16_t *)((uintptr_t)s_info + s_info->page_extras_offset);
3173 
3174 	uint8_t *page_content = (uint8_t *)vaddr;
3175 	uint16_t page_entry;
3176 
3177 	if (pageIndex >= s_info->page_starts_count) {
3178 		printf("vm_shared_region_slide_page() did not find page start in slide info: pageIndex=%u, count=%u\n",
3179 		    pageIndex, s_info->page_starts_count);
3180 		return KERN_FAILURE;
3181 	}
3182 	page_entry = page_starts[pageIndex];
3183 
3184 	if (page_entry == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE) {
3185 		return KERN_SUCCESS;
3186 	}
3187 
3188 	if (page_entry & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA) {
3189 		uint16_t chain_index = page_entry & DYLD_CACHE_SLIDE_PAGE_VALUE;
3190 		uint16_t info;
3191 
3192 		do {
3193 			uint16_t page_start_offset;
3194 			kern_return_t kr;
3195 
3196 			if (chain_index >= s_info->page_extras_count) {
3197 				printf("vm_shared_region_slide_page() out-of-bounds extras index: index=%u, count=%u\n",
3198 				    chain_index, s_info->page_extras_count);
3199 				return KERN_FAILURE;
3200 			}
3201 			info = page_extras[chain_index];
3202 			page_start_offset = (uint16_t)((info & DYLD_CACHE_SLIDE_PAGE_VALUE) << DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT);
3203 
3204 			kr = rebase_chain(is_64, pageIndex, page_content, page_start_offset, slide_amount, s_info);
3205 			if (kr != KERN_SUCCESS) {
3206 				return KERN_FAILURE;
3207 			}
3208 
3209 			chain_index++;
3210 		} while (!(info & DYLD_CACHE_SLIDE_PAGE_ATTR_END));
3211 	} else {
3212 		const uint16_t page_start_offset = (uint16_t)(page_entry << DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT);
3213 		kern_return_t kr;
3214 
3215 		kr = rebase_chain(is_64, pageIndex, page_content, page_start_offset, slide_amount, s_info);
3216 		if (kr != KERN_SUCCESS) {
3217 			return KERN_FAILURE;
3218 		}
3219 	}
3220 
3221 	return KERN_SUCCESS;
3222 }
3223 
3224 
3225 static kern_return_t
vm_shared_region_slide_page_v3(vm_shared_region_slide_info_t si,vm_offset_t vaddr,__unused mach_vm_offset_t uservaddr,uint32_t pageIndex,__unused uint64_t jop_key)3226 vm_shared_region_slide_page_v3(
3227 	vm_shared_region_slide_info_t si,
3228 	vm_offset_t vaddr,
3229 	__unused mach_vm_offset_t uservaddr,
3230 	uint32_t pageIndex,
3231 #if !__has_feature(ptrauth_calls)
3232 	__unused
3233 #endif /* !__has_feature(ptrauth_calls) */
3234 	uint64_t jop_key)
3235 {
3236 	vm_shared_region_slide_info_entry_v3_t s_info = &si->si_slide_info_entry->v3;
3237 	const uint32_t slide_amount = si->si_slide;
3238 
3239 	uint8_t *page_content = (uint8_t *)vaddr;
3240 	uint16_t page_entry;
3241 
3242 	if (pageIndex >= s_info->page_starts_count) {
3243 		printf("vm_shared_region_slide_page() did not find page start in slide info: pageIndex=%u, count=%u\n",
3244 		    pageIndex, s_info->page_starts_count);
3245 		return KERN_FAILURE;
3246 	}
3247 	page_entry = s_info->page_starts[pageIndex];
3248 
3249 	if (page_entry == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE) {
3250 		return KERN_SUCCESS;
3251 	}
3252 
3253 	uint8_t* rebaseLocation = page_content;
3254 	uint64_t delta = page_entry;
3255 	do {
3256 		rebaseLocation += delta;
3257 		uint64_t value;
3258 		memcpy(&value, rebaseLocation, sizeof(value));
3259 		delta = ((value & 0x3FF8000000000000) >> 51) * sizeof(uint64_t);
3260 
3261 		// A pointer is one of :
3262 		// {
3263 		//	 uint64_t pointerValue : 51;
3264 		//	 uint64_t offsetToNextPointer : 11;
3265 		//	 uint64_t isBind : 1 = 0;
3266 		//	 uint64_t authenticated : 1 = 0;
3267 		// }
3268 		// {
3269 		//	 uint32_t offsetFromSharedCacheBase;
3270 		//	 uint16_t diversityData;
3271 		//	 uint16_t hasAddressDiversity : 1;
3272 		//	 uint16_t hasDKey : 1;
3273 		//	 uint16_t hasBKey : 1;
3274 		//	 uint16_t offsetToNextPointer : 11;
3275 		//	 uint16_t isBind : 1;
3276 		//	 uint16_t authenticated : 1 = 1;
3277 		// }
3278 
3279 		bool isBind = (value & (1ULL << 62)) != 0;
3280 		if (isBind) {
3281 			return KERN_FAILURE;
3282 		}
3283 
3284 #if __has_feature(ptrauth_calls)
3285 		uint16_t diversity_data = (uint16_t)(value >> 32);
3286 		bool hasAddressDiversity = (value & (1ULL << 48)) != 0;
3287 		ptrauth_key key = (ptrauth_key)((value >> 49) & 0x3);
3288 #endif /* __has_feature(ptrauth_calls) */
3289 		bool isAuthenticated = (value & (1ULL << 63)) != 0;
3290 
3291 		if (isAuthenticated) {
3292 			// The new value for a rebase is the low 32-bits of the threaded value plus the slide.
3293 			value = (value & 0xFFFFFFFF) + slide_amount;
3294 			// Add in the offset from the mach_header
3295 			const uint64_t value_add = s_info->value_add;
3296 			value += value_add;
3297 
3298 #if __has_feature(ptrauth_calls)
3299 			uint64_t discriminator = diversity_data;
3300 			if (hasAddressDiversity) {
3301 				// First calculate a new discriminator using the address of where we are trying to store the value
3302 				uintptr_t pageOffset = rebaseLocation - page_content;
3303 				discriminator = __builtin_ptrauth_blend_discriminator((void*)(((uintptr_t)uservaddr) + pageOffset), discriminator);
3304 			}
3305 
3306 			if (jop_key != 0 && si->si_ptrauth && !arm_user_jop_disabled()) {
3307 				/*
3308 				 * these pointers are used in user mode. disable the kernel key diversification
3309 				 * so we can sign them for use in user mode.
3310 				 */
3311 				value = (uintptr_t)pmap_sign_user_ptr((void *)value, key, discriminator, jop_key);
3312 			}
3313 #endif /* __has_feature(ptrauth_calls) */
3314 		} else {
3315 			// The new value for a rebase is the low 51-bits of the threaded value plus the slide.
3316 			// Regular pointer which needs to fit in 51-bits of value.
3317 			// C++ RTTI uses the top bit, so we'll allow the whole top-byte
3318 			// and the bottom 43-bits to be fit in to 51-bits.
3319 			uint64_t top8Bits = value & 0x0007F80000000000ULL;
3320 			uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL;
3321 			uint64_t targetValue = (top8Bits << 13) | bottom43Bits;
3322 			value = targetValue + slide_amount;
3323 		}
3324 
3325 		memcpy(rebaseLocation, &value, sizeof(value));
3326 	} while (delta != 0);
3327 
3328 	return KERN_SUCCESS;
3329 }
3330 
3331 static kern_return_t
rebase_chainv4(uint8_t * page_content,uint16_t start_offset,uint32_t slide_amount,vm_shared_region_slide_info_entry_v4_t s_info)3332 rebase_chainv4(
3333 	uint8_t *page_content,
3334 	uint16_t start_offset,
3335 	uint32_t slide_amount,
3336 	vm_shared_region_slide_info_entry_v4_t s_info)
3337 {
3338 	const uint32_t last_page_offset = PAGE_SIZE_FOR_SR_SLIDE - sizeof(uint32_t);
3339 
3340 	const uint32_t delta_mask = (uint32_t)(s_info->delta_mask);
3341 	const uint32_t value_mask = ~delta_mask;
3342 	const uint32_t value_add = (uint32_t)(s_info->value_add);
3343 	const uint32_t delta_shift = __builtin_ctzll(delta_mask) - 2;
3344 
3345 	uint32_t page_offset = start_offset;
3346 	uint32_t delta = 1;
3347 
3348 	while (delta != 0 && page_offset <= last_page_offset) {
3349 		uint8_t *loc;
3350 		uint32_t value;
3351 
3352 		loc = page_content + page_offset;
3353 		memcpy(&value, loc, sizeof(value));
3354 		delta = (value & delta_mask) >> delta_shift;
3355 		value &= value_mask;
3356 
3357 		if ((value & 0xFFFF8000) == 0) {
3358 			// small positive non-pointer, use as-is
3359 		} else if ((value & 0x3FFF8000) == 0x3FFF8000) {
3360 			// small negative non-pointer
3361 			value |= 0xC0000000;
3362 		} else {
3363 			// pointer that needs rebasing
3364 			value += value_add;
3365 			value += slide_amount;
3366 		}
3367 		memcpy(loc, &value, sizeof(value));
3368 		page_offset += delta;
3369 	}
3370 
3371 	/* If the offset went past the end of the page, then the slide data is invalid. */
3372 	if (page_offset > last_page_offset) {
3373 		return KERN_FAILURE;
3374 	}
3375 	return KERN_SUCCESS;
3376 }
3377 
3378 static kern_return_t
vm_shared_region_slide_page_v4(vm_shared_region_slide_info_t si,vm_offset_t vaddr,uint32_t pageIndex)3379 vm_shared_region_slide_page_v4(vm_shared_region_slide_info_t si, vm_offset_t vaddr, uint32_t pageIndex)
3380 {
3381 	vm_shared_region_slide_info_entry_v4_t s_info = &si->si_slide_info_entry->v4;
3382 	const uint32_t slide_amount = si->si_slide;
3383 
3384 	const uint16_t *page_starts = (uint16_t *)((uintptr_t)s_info + s_info->page_starts_offset);
3385 	const uint16_t *page_extras = (uint16_t *)((uintptr_t)s_info + s_info->page_extras_offset);
3386 
3387 	uint8_t *page_content = (uint8_t *)vaddr;
3388 	uint16_t page_entry;
3389 
3390 	if (pageIndex >= s_info->page_starts_count) {
3391 		printf("vm_shared_region_slide_page() did not find page start in slide info: pageIndex=%u, count=%u\n",
3392 		    pageIndex, s_info->page_starts_count);
3393 		return KERN_FAILURE;
3394 	}
3395 	page_entry = page_starts[pageIndex];
3396 
3397 	if (page_entry == DYLD_CACHE_SLIDE4_PAGE_NO_REBASE) {
3398 		return KERN_SUCCESS;
3399 	}
3400 
3401 	if (page_entry & DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA) {
3402 		uint16_t chain_index = page_entry & DYLD_CACHE_SLIDE4_PAGE_INDEX;
3403 		uint16_t info;
3404 
3405 		do {
3406 			uint16_t page_start_offset;
3407 			kern_return_t kr;
3408 
3409 			if (chain_index >= s_info->page_extras_count) {
3410 				printf("vm_shared_region_slide_page() out-of-bounds extras index: index=%u, count=%u\n",
3411 				    chain_index, s_info->page_extras_count);
3412 				return KERN_FAILURE;
3413 			}
3414 			info = page_extras[chain_index];
3415 			page_start_offset = (uint16_t)((info & DYLD_CACHE_SLIDE4_PAGE_INDEX) << DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT);
3416 
3417 			kr = rebase_chainv4(page_content, page_start_offset, slide_amount, s_info);
3418 			if (kr != KERN_SUCCESS) {
3419 				return KERN_FAILURE;
3420 			}
3421 
3422 			chain_index++;
3423 		} while (!(info & DYLD_CACHE_SLIDE4_PAGE_EXTRA_END));
3424 	} else {
3425 		const uint16_t page_start_offset = (uint16_t)(page_entry << DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT);
3426 		kern_return_t kr;
3427 
3428 		kr = rebase_chainv4(page_content, page_start_offset, slide_amount, s_info);
3429 		if (kr != KERN_SUCCESS) {
3430 			return KERN_FAILURE;
3431 		}
3432 	}
3433 
3434 	return KERN_SUCCESS;
3435 }
3436 
3437 
3438 static kern_return_t
vm_shared_region_slide_page_v5(vm_shared_region_slide_info_t si,vm_offset_t vaddr,__unused mach_vm_offset_t uservaddr,uint32_t pageIndex,__unused uint64_t jop_key)3439 vm_shared_region_slide_page_v5(
3440 	vm_shared_region_slide_info_t si,
3441 	vm_offset_t vaddr,
3442 	__unused mach_vm_offset_t uservaddr,
3443 	uint32_t pageIndex,
3444 #if !__has_feature(ptrauth_calls)
3445 	__unused
3446 #endif /* !__has_feature(ptrauth_calls) */
3447 	uint64_t jop_key)
3448 {
3449 	vm_shared_region_slide_info_entry_v5_t s_info = &si->si_slide_info_entry->v5;
3450 	const uint32_t slide_amount = si->si_slide;
3451 	const uint64_t value_add = s_info->value_add;
3452 
3453 	uint8_t *page_content = (uint8_t *)vaddr;
3454 	uint16_t page_entry;
3455 
3456 	if (pageIndex >= s_info->page_starts_count) {
3457 		printf("vm_shared_region_slide_page() did not find page start in slide info: pageIndex=%u, count=%u\n",
3458 		    pageIndex, s_info->page_starts_count);
3459 		return KERN_FAILURE;
3460 	}
3461 	page_entry = s_info->page_starts[pageIndex];
3462 
3463 	if (page_entry == DYLD_CACHE_SLIDE_V5_PAGE_ATTR_NO_REBASE) {
3464 		return KERN_SUCCESS;
3465 	}
3466 
3467 	uint8_t* rebaseLocation = page_content;
3468 	uint64_t delta = page_entry;
3469 	do {
3470 		rebaseLocation += delta;
3471 		uint64_t value;
3472 		memcpy(&value, rebaseLocation, sizeof(value));
3473 		delta = ((value & 0x7FF0000000000000ULL) >> 52) * sizeof(uint64_t);
3474 
3475 		// A pointer is one of :
3476 		// {
3477 		//   uint64_t    runtimeOffset   : 34,   // offset from the start of the shared cache
3478 		//               high8           :  8,
3479 		//               unused          : 10,
3480 		//               next            : 11,   // 8-byte stide
3481 		//               auth            :  1;   // == 0
3482 		// }
3483 		// {
3484 		//   uint64_t    runtimeOffset   : 34,   // offset from the start of the shared cache
3485 		//               diversity       : 16,
3486 		//               addrDiv         :  1,
3487 		//               keyIsData       :  1,   // implicitly always the 'A' key.  0 -> IA.  1 -> DA
3488 		//               next            : 11,   // 8-byte stide
3489 		//               auth            :  1;   // == 1
3490 		// }
3491 
3492 #if __has_feature(ptrauth_calls)
3493 		bool        addrDiv = ((value & (1ULL << 50)) != 0);
3494 		bool        keyIsData = ((value & (1ULL << 51)) != 0);
3495 		// the key is always A, and the bit tells us if its IA or ID
3496 		ptrauth_key key = keyIsData ? ptrauth_key_asda : ptrauth_key_asia;
3497 		uint16_t    diversity = (uint16_t)((value >> 34) & 0xFFFF);
3498 #endif /* __has_feature(ptrauth_calls) */
3499 		uint64_t    high8 = (value << 22) & 0xFF00000000000000ULL;
3500 		bool        isAuthenticated = (value & (1ULL << 63)) != 0;
3501 
3502 		// The new value for a rebase is the low 34-bits of the threaded value plus the base plus slide.
3503 		value = (value & 0x3FFFFFFFFULL) + value_add + slide_amount;
3504 		if (isAuthenticated) {
3505 #if __has_feature(ptrauth_calls)
3506 			uint64_t discriminator = diversity;
3507 			if (addrDiv) {
3508 				// First calculate a new discriminator using the address of where we are trying to store the value
3509 				uintptr_t pageOffset = rebaseLocation - page_content;
3510 				discriminator = __builtin_ptrauth_blend_discriminator((void*)(((uintptr_t)uservaddr) + pageOffset), discriminator);
3511 			}
3512 
3513 			if (jop_key != 0 && si->si_ptrauth && !arm_user_jop_disabled()) {
3514 				/*
3515 				 * these pointers are used in user mode. disable the kernel key diversification
3516 				 * so we can sign them for use in user mode.
3517 				 */
3518 				value = (uintptr_t)pmap_sign_user_ptr((void *)value, key, discriminator, jop_key);
3519 			}
3520 #endif /* __has_feature(ptrauth_calls) */
3521 		} else {
3522 			// the value already has the correct low bits, so just add in the high8 if it exists
3523 			value += high8;
3524 		}
3525 
3526 		memcpy(rebaseLocation, &value, sizeof(value));
3527 	} while (delta != 0);
3528 
3529 	return KERN_SUCCESS;
3530 }
3531 
3532 
3533 
3534 kern_return_t
vm_shared_region_slide_page(vm_shared_region_slide_info_t si,vm_offset_t vaddr,mach_vm_offset_t uservaddr,uint32_t pageIndex,uint64_t jop_key)3535 vm_shared_region_slide_page(
3536 	vm_shared_region_slide_info_t si,
3537 	vm_offset_t vaddr,
3538 	mach_vm_offset_t uservaddr,
3539 	uint32_t pageIndex,
3540 	uint64_t jop_key)
3541 {
3542 	switch (si->si_slide_info_entry->version) {
3543 	case 1:
3544 		return vm_shared_region_slide_page_v1(si, vaddr, pageIndex);
3545 	case 2:
3546 		return vm_shared_region_slide_page_v2(si, vaddr, pageIndex);
3547 	case 3:
3548 		return vm_shared_region_slide_page_v3(si, vaddr, uservaddr, pageIndex, jop_key);
3549 	case 4:
3550 		return vm_shared_region_slide_page_v4(si, vaddr, pageIndex);
3551 	case 5:
3552 		return vm_shared_region_slide_page_v5(si, vaddr, uservaddr, pageIndex, jop_key);
3553 	default:
3554 		return KERN_FAILURE;
3555 	}
3556 }
3557 
3558 /******************************************************************************/
3559 /* Comm page support                                                          */
3560 /******************************************************************************/
3561 
3562 SECURITY_READ_ONLY_LATE(ipc_port_t) commpage32_handle = IPC_PORT_NULL;
3563 SECURITY_READ_ONLY_LATE(ipc_port_t) commpage64_handle = IPC_PORT_NULL;
3564 SECURITY_READ_ONLY_LATE(vm_named_entry_t) commpage32_entry = NULL;
3565 SECURITY_READ_ONLY_LATE(vm_named_entry_t) commpage64_entry = NULL;
3566 SECURITY_READ_ONLY_LATE(vm_map_t) commpage32_map = VM_MAP_NULL;
3567 SECURITY_READ_ONLY_LATE(vm_map_t) commpage64_map = VM_MAP_NULL;
3568 
3569 SECURITY_READ_ONLY_LATE(ipc_port_t) commpage_text32_handle = IPC_PORT_NULL;
3570 SECURITY_READ_ONLY_LATE(ipc_port_t) commpage_text64_handle = IPC_PORT_NULL;
3571 SECURITY_READ_ONLY_LATE(vm_named_entry_t) commpage_text32_entry = NULL;
3572 SECURITY_READ_ONLY_LATE(vm_named_entry_t) commpage_text64_entry = NULL;
3573 SECURITY_READ_ONLY_LATE(vm_map_t) commpage_text32_map = VM_MAP_NULL;
3574 SECURITY_READ_ONLY_LATE(vm_map_t) commpage_text64_map = VM_MAP_NULL;
3575 
3576 SECURITY_READ_ONLY_LATE(user32_addr_t) commpage_text32_location = 0;
3577 SECURITY_READ_ONLY_LATE(user64_addr_t) commpage_text64_location = 0;
3578 
3579 #if defined(__i386__) || defined(__x86_64__)
3580 /*
3581  * Create a memory entry, VM submap and pmap for one commpage.
3582  */
3583 static void
_vm_commpage_init(ipc_port_t * handlep,vm_map_size_t size)3584 _vm_commpage_init(
3585 	ipc_port_t      *handlep,
3586 	vm_map_size_t   size)
3587 {
3588 	vm_named_entry_t        mem_entry;
3589 	vm_map_t                new_map;
3590 
3591 	SHARED_REGION_TRACE_DEBUG(
3592 		("commpage: -> _init(0x%llx)\n",
3593 		(long long)size));
3594 
3595 	pmap_t new_pmap = pmap_create_options(NULL, 0, 0);
3596 	if (new_pmap == NULL) {
3597 		panic("_vm_commpage_init: could not allocate pmap");
3598 	}
3599 	new_map = vm_map_create_options(new_pmap, 0, size, VM_MAP_CREATE_DEFAULT);
3600 
3601 	mem_entry = mach_memory_entry_allocate(handlep);
3602 	mem_entry->backing.map = new_map;
3603 	mem_entry->internal = TRUE;
3604 	mem_entry->is_sub_map = TRUE;
3605 	mem_entry->offset = 0;
3606 	mem_entry->protection = VM_PROT_ALL;
3607 	mem_entry->size = size;
3608 
3609 	SHARED_REGION_TRACE_DEBUG(
3610 		("commpage: _init(0x%llx) <- %p\n",
3611 		(long long)size, (void *)VM_KERNEL_ADDRPERM(*handlep)));
3612 }
3613 #endif
3614 
3615 
3616 /*
3617  * Initialize the comm text pages at boot time
3618  */
3619 void
vm_commpage_text_init(void)3620 vm_commpage_text_init(void)
3621 {
3622 	SHARED_REGION_TRACE_DEBUG(
3623 		("commpage text: ->init()\n"));
3624 #if defined(__i386__) || defined(__x86_64__)
3625 	/* create the 32 bit comm text page */
3626 	unsigned int offset = (random() % _PFZ32_SLIDE_RANGE) << PAGE_SHIFT; /* restricting to 32bMAX-2PAGE */
3627 	_vm_commpage_init(&commpage_text32_handle, _COMM_PAGE_TEXT_AREA_LENGTH);
3628 	commpage_text32_entry = mach_memory_entry_from_port(commpage_text32_handle);
3629 	commpage_text32_map = commpage_text32_entry->backing.map;
3630 	commpage_text32_location = (user32_addr_t) (_COMM_PAGE32_TEXT_START + offset);
3631 	/* XXX if (cpu_is_64bit_capable()) ? */
3632 	/* create the 64-bit comm page */
3633 	offset = (random() % _PFZ64_SLIDE_RANGE) << PAGE_SHIFT; /* restricting sliding upto 2Mb range */
3634 	_vm_commpage_init(&commpage_text64_handle, _COMM_PAGE_TEXT_AREA_LENGTH);
3635 	commpage_text64_entry = mach_memory_entry_from_port(commpage_text64_handle);
3636 	commpage_text64_map = commpage_text64_entry->backing.map;
3637 	commpage_text64_location = (user64_addr_t) (_COMM_PAGE64_TEXT_START + offset);
3638 #endif
3639 
3640 	commpage_text_populate();
3641 
3642 	/* populate the routines in here */
3643 	SHARED_REGION_TRACE_DEBUG(
3644 		("commpage text: init() <-\n"));
3645 }
3646 
3647 /*
3648  * Initialize the comm pages at boot time.
3649  */
3650 void
vm_commpage_init(void)3651 vm_commpage_init(void)
3652 {
3653 	SHARED_REGION_TRACE_DEBUG(
3654 		("commpage: -> init()\n"));
3655 
3656 #if defined(__i386__) || defined(__x86_64__)
3657 	/* create the 32-bit comm page */
3658 	_vm_commpage_init(&commpage32_handle, _COMM_PAGE32_AREA_LENGTH);
3659 	commpage32_entry = mach_memory_entry_from_port(commpage32_handle);
3660 	commpage32_map = commpage32_entry->backing.map;
3661 
3662 	/* XXX if (cpu_is_64bit_capable()) ? */
3663 	/* create the 64-bit comm page */
3664 	_vm_commpage_init(&commpage64_handle, _COMM_PAGE64_AREA_LENGTH);
3665 	commpage64_entry = mach_memory_entry_from_port(commpage64_handle);
3666 	commpage64_map = commpage64_entry->backing.map;
3667 
3668 #endif /* __i386__ || __x86_64__ */
3669 
3670 	/* populate them according to this specific platform */
3671 	commpage_populate();
3672 	__commpage_setup = 1;
3673 #if XNU_TARGET_OS_OSX
3674 	if (__system_power_source == 0) {
3675 		post_sys_powersource_internal(0, 1);
3676 	}
3677 #endif /* XNU_TARGET_OS_OSX */
3678 
3679 	SHARED_REGION_TRACE_DEBUG(
3680 		("commpage: init() <-\n"));
3681 }
3682 
3683 /*
3684  * Enter the appropriate comm page into the task's address space.
3685  * This is called at exec() time via vm_map_exec().
3686  */
3687 kern_return_t
vm_commpage_enter(vm_map_t map,task_t task,boolean_t is64bit)3688 vm_commpage_enter(
3689 	vm_map_t        map,
3690 	task_t          task,
3691 	boolean_t       is64bit)
3692 {
3693 #if   defined(__arm64__)
3694 #pragma unused(is64bit)
3695 	(void)task;
3696 	(void)map;
3697 	pmap_insert_commpage(vm_map_pmap(map));
3698 	return KERN_SUCCESS;
3699 #else
3700 	ipc_port_t              commpage_handle, commpage_text_handle;
3701 	vm_map_offset_t         commpage_address, objc_address, commpage_text_address;
3702 	vm_map_size_t           commpage_size, objc_size, commpage_text_size;
3703 	vm_map_kernel_flags_t   vmk_flags;
3704 	kern_return_t           kr;
3705 
3706 	SHARED_REGION_TRACE_DEBUG(
3707 		("commpage: -> enter(%p,%p)\n",
3708 		(void *)VM_KERNEL_ADDRPERM(map),
3709 		(void *)VM_KERNEL_ADDRPERM(task)));
3710 
3711 	commpage_text_size = _COMM_PAGE_TEXT_AREA_LENGTH;
3712 	/* the comm page is likely to be beyond the actual end of the VM map */
3713 	vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED();
3714 	vmk_flags.vmkf_beyond_max = TRUE;
3715 
3716 	/* select the appropriate comm page for this task */
3717 	assert(!(is64bit ^ vm_map_is_64bit(map)));
3718 	if (is64bit) {
3719 		commpage_handle = commpage64_handle;
3720 		commpage_address = (vm_map_offset_t) _COMM_PAGE64_BASE_ADDRESS;
3721 		commpage_size = _COMM_PAGE64_AREA_LENGTH;
3722 		objc_size = _COMM_PAGE64_OBJC_SIZE;
3723 		objc_address = _COMM_PAGE64_OBJC_BASE;
3724 		commpage_text_handle = commpage_text64_handle;
3725 		commpage_text_address = (vm_map_offset_t) commpage_text64_location;
3726 	} else {
3727 		commpage_handle = commpage32_handle;
3728 		commpage_address =
3729 		    (vm_map_offset_t)(unsigned) _COMM_PAGE32_BASE_ADDRESS;
3730 		commpage_size = _COMM_PAGE32_AREA_LENGTH;
3731 		objc_size = _COMM_PAGE32_OBJC_SIZE;
3732 		objc_address = _COMM_PAGE32_OBJC_BASE;
3733 		commpage_text_handle = commpage_text32_handle;
3734 		commpage_text_address = (vm_map_offset_t) commpage_text32_location;
3735 	}
3736 
3737 	if ((commpage_address & (pmap_commpage_size_min(map->pmap) - 1)) == 0 &&
3738 	    (commpage_size & (pmap_commpage_size_min(map->pmap) - 1)) == 0) {
3739 		/* the commpage is properly aligned or sized for pmap-nesting */
3740 		vmk_flags.vm_tag = VM_MEMORY_SHARED_PMAP;
3741 		vmk_flags.vmkf_nested_pmap = TRUE;
3742 	}
3743 
3744 	/* map the comm page in the task's address space */
3745 	assert(commpage_handle != IPC_PORT_NULL);
3746 	kr = mach_vm_map_kernel(
3747 		map,
3748 		vm_sanitize_wrap_addr_ref(&commpage_address),
3749 		commpage_size,
3750 		0,
3751 		vmk_flags,
3752 		commpage_handle,
3753 		0,
3754 		FALSE,
3755 		VM_PROT_READ,
3756 		VM_PROT_READ,
3757 		VM_INHERIT_SHARE);
3758 	if (kr != KERN_SUCCESS) {
3759 		SHARED_REGION_TRACE_ERROR(
3760 			("commpage: enter(%p,0x%llx,0x%llx) "
3761 			"commpage %p mapping failed 0x%x\n",
3762 			(void *)VM_KERNEL_ADDRPERM(map),
3763 			(long long)commpage_address,
3764 			(long long)commpage_size,
3765 			(void *)VM_KERNEL_ADDRPERM(commpage_handle), kr));
3766 	}
3767 
3768 	/* map the comm text page in the task's address space */
3769 	assert(commpage_text_handle != IPC_PORT_NULL);
3770 	kr = mach_vm_map_kernel(
3771 		map,
3772 		vm_sanitize_wrap_addr_ref(&commpage_text_address),
3773 		commpage_text_size,
3774 		0,
3775 		vmk_flags,
3776 		commpage_text_handle,
3777 		0,
3778 		FALSE,
3779 		VM_PROT_READ | VM_PROT_EXECUTE,
3780 		VM_PROT_READ | VM_PROT_EXECUTE,
3781 		VM_INHERIT_SHARE);
3782 	if (kr != KERN_SUCCESS) {
3783 		SHARED_REGION_TRACE_ERROR(
3784 			("commpage text: enter(%p,0x%llx,0x%llx) "
3785 			"commpage text %p mapping failed 0x%x\n",
3786 			(void *)VM_KERNEL_ADDRPERM(map),
3787 			(long long)commpage_text_address,
3788 			(long long)commpage_text_size,
3789 			(void *)VM_KERNEL_ADDRPERM(commpage_text_handle), kr));
3790 	}
3791 
3792 	/*
3793 	 * Since we're here, we also pre-allocate some virtual space for the
3794 	 * Objective-C run-time, if needed...
3795 	 */
3796 	if (objc_size != 0) {
3797 		kr = mach_vm_map_kernel(
3798 			map,
3799 			vm_sanitize_wrap_addr_ref(&objc_address),
3800 			objc_size,
3801 			0,
3802 			vmk_flags,
3803 			IPC_PORT_NULL,
3804 			0,
3805 			FALSE,
3806 			VM_PROT_ALL,
3807 			VM_PROT_ALL,
3808 			VM_INHERIT_DEFAULT);
3809 		if (kr != KERN_SUCCESS) {
3810 			SHARED_REGION_TRACE_ERROR(
3811 				("commpage: enter(%p,0x%llx,0x%llx) "
3812 				"objc mapping failed 0x%x\n",
3813 				(void *)VM_KERNEL_ADDRPERM(map),
3814 				(long long)objc_address,
3815 				(long long)objc_size, kr));
3816 		}
3817 	}
3818 
3819 	SHARED_REGION_TRACE_DEBUG(
3820 		("commpage: enter(%p,%p) <- 0x%x\n",
3821 		(void *)VM_KERNEL_ADDRPERM(map),
3822 		(void *)VM_KERNEL_ADDRPERM(task), kr));
3823 	return kr;
3824 #endif
3825 }
3826 
3827 int
vm_shared_region_slide(uint32_t slide,mach_vm_offset_t entry_start_address,mach_vm_size_t entry_size,mach_vm_offset_t slide_start,mach_vm_size_t slide_size,mach_vm_offset_t slid_mapping,memory_object_control_t sr_file_control,vm_prot_t prot)3828 vm_shared_region_slide(
3829 	uint32_t slide,
3830 	mach_vm_offset_t        entry_start_address,
3831 	mach_vm_size_t          entry_size,
3832 	mach_vm_offset_t        slide_start,
3833 	mach_vm_size_t          slide_size,
3834 	mach_vm_offset_t        slid_mapping,
3835 	memory_object_control_t sr_file_control,
3836 	vm_prot_t               prot)
3837 {
3838 	vm_shared_region_t      sr;
3839 	kern_return_t           error;
3840 
3841 	SHARED_REGION_TRACE_DEBUG(
3842 		("vm_shared_region_slide: -> slide %#x, entry_start %#llx, entry_size %#llx, slide_start %#llx, slide_size %#llx\n",
3843 		slide, entry_start_address, entry_size, slide_start, slide_size));
3844 
3845 	sr = vm_shared_region_get(current_task());
3846 	if (sr == NULL) {
3847 		printf("%s: no shared region?\n", __FUNCTION__);
3848 		SHARED_REGION_TRACE_DEBUG(
3849 			("vm_shared_region_slide: <- %d (no shared region)\n",
3850 			KERN_FAILURE));
3851 		return KERN_FAILURE;
3852 	}
3853 
3854 	/*
3855 	 * Protect from concurrent access.
3856 	 */
3857 	vm_shared_region_lock();
3858 	while (sr->sr_slide_in_progress) {
3859 		vm_shared_region_sleep(&sr->sr_slide_in_progress, THREAD_UNINT);
3860 	}
3861 
3862 	sr->sr_slide_in_progress = current_thread();
3863 	vm_shared_region_unlock();
3864 
3865 	error = vm_shared_region_slide_mapping(sr,
3866 	    (user_addr_t)slide_start,
3867 	    slide_size,
3868 	    entry_start_address,
3869 	    entry_size,
3870 	    slid_mapping,
3871 	    slide,
3872 	    sr_file_control,
3873 	    prot);
3874 	if (error) {
3875 		printf("slide_info initialization failed with kr=%d\n", error);
3876 	}
3877 
3878 	vm_shared_region_lock();
3879 
3880 	assert(sr->sr_slide_in_progress == current_thread());
3881 	sr->sr_slide_in_progress = THREAD_NULL;
3882 	vm_shared_region_wakeup(&sr->sr_slide_in_progress);
3883 
3884 #if XNU_TARGET_OS_OSX
3885 	if (error == KERN_SUCCESS) {
3886 		shared_region_completed_slide = TRUE;
3887 	}
3888 #endif /* XNU_TARGET_OS_OSX */
3889 	vm_shared_region_unlock();
3890 
3891 	vm_shared_region_deallocate(sr);
3892 
3893 	SHARED_REGION_TRACE_DEBUG(
3894 		("vm_shared_region_slide: <- %d\n",
3895 		error));
3896 
3897 	return error;
3898 }
3899 
3900 /*
3901  * Used during Authenticated Root Volume macOS boot.
3902  * Launchd re-execs itself and wants the new launchd to use
3903  * the shared cache from the new root volume. This call
3904  * makes all the existing shared caches stale to allow
3905  * that to happen.
3906  */
3907 void
vm_shared_region_pivot(void)3908 vm_shared_region_pivot(void)
3909 {
3910 	vm_shared_region_t      shared_region = NULL;
3911 
3912 	vm_shared_region_lock();
3913 
3914 	queue_iterate(&vm_shared_region_queue, shared_region, vm_shared_region_t, sr_q) {
3915 		assert(shared_region->sr_ref_count > 0);
3916 		shared_region->sr_stale = TRUE;
3917 		if (shared_region->sr_timer_call) {
3918 			/*
3919 			 * We have a shared region ready to be destroyed
3920 			 * and just waiting for a delayed timer to fire.
3921 			 * Marking it stale cements its ineligibility to
3922 			 * be used ever again. So let's shorten the timer
3923 			 * aggressively down to 10 milliseconds and get rid of it.
3924 			 * This is a single quantum and we don't need to go
3925 			 * shorter than this duration. We want it to be short
3926 			 * enough, however, because we could have an unmount
3927 			 * of the volume hosting this shared region just behind
3928 			 * us.
3929 			 */
3930 			uint64_t deadline;
3931 			assert(shared_region->sr_ref_count == 1);
3932 
3933 			/*
3934 			 * Free the old timer call. Returns with a reference held.
3935 			 * If the old timer has fired and is waiting for the vm_shared_region_lock
3936 			 * lock, we will just return with an additional ref_count i.e. 2.
3937 			 * The old timer will then fire and just drop the ref count down to 1
3938 			 * with no other modifications.
3939 			 */
3940 			vm_shared_region_reference_locked(shared_region);
3941 
3942 			/* set up the timer. Keep the reference from above for this timer.*/
3943 			shared_region->sr_timer_call = thread_call_allocate(
3944 				(thread_call_func_t) vm_shared_region_timeout,
3945 				(thread_call_param_t) shared_region);
3946 
3947 			/* schedule the timer */
3948 			clock_interval_to_deadline(10, /* 10 milliseconds */
3949 			    NSEC_PER_MSEC,
3950 			    &deadline);
3951 			thread_call_enter_delayed(shared_region->sr_timer_call,
3952 			    deadline);
3953 
3954 			SHARED_REGION_TRACE_DEBUG(
3955 				("shared_region: pivot(%p): armed timer\n",
3956 				(void *)VM_KERNEL_ADDRPERM(shared_region)));
3957 		}
3958 	}
3959 
3960 	vm_shared_region_unlock();
3961 }
3962 
3963 /*
3964  * Routine to mark any non-standard slide shared cache region as stale.
3965  * This causes the next "reslide" spawn to create a new shared region.
3966  */
3967 void
vm_shared_region_reslide_stale(boolean_t driverkit)3968 vm_shared_region_reslide_stale(boolean_t driverkit)
3969 {
3970 #if __has_feature(ptrauth_calls)
3971 	vm_shared_region_t      shared_region = NULL;
3972 
3973 	vm_shared_region_lock();
3974 
3975 	queue_iterate(&vm_shared_region_queue, shared_region, vm_shared_region_t, sr_q) {
3976 		assert(shared_region->sr_ref_count > 0);
3977 		if (shared_region->sr_driverkit == driverkit && !shared_region->sr_stale && shared_region->sr_reslide) {
3978 			shared_region->sr_stale = TRUE;
3979 			vm_shared_region_reslide_count++;
3980 		}
3981 	}
3982 
3983 	vm_shared_region_unlock();
3984 #else
3985 	(void)driverkit;
3986 #endif /* __has_feature(ptrauth_calls) */
3987 }
3988 
3989 /*
3990  * report if the task is using a reslide shared cache region.
3991  */
3992 bool
vm_shared_region_is_reslide(__unused struct task * task)3993 vm_shared_region_is_reslide(__unused struct task *task)
3994 {
3995 	bool is_reslide = FALSE;
3996 #if __has_feature(ptrauth_calls)
3997 	vm_shared_region_t sr = vm_shared_region_get(task);
3998 
3999 	if (sr != NULL) {
4000 		is_reslide = sr->sr_reslide;
4001 		vm_shared_region_deallocate(sr);
4002 	}
4003 #endif /* __has_feature(ptrauth_calls) */
4004 	return is_reslide;
4005 }
4006 
4007 /*
4008  * This is called from powermanagement code to let kernel know the current source of power.
4009  * 0 if it is external source (connected to power )
4010  * 1 if it is internal power source ie battery
4011  */
4012 void
4013 #if XNU_TARGET_OS_OSX
post_sys_powersource(int i)4014 post_sys_powersource(int i)
4015 #else /* XNU_TARGET_OS_OSX */
4016 post_sys_powersource(__unused int i)
4017 #endif /* XNU_TARGET_OS_OSX */
4018 {
4019 #if XNU_TARGET_OS_OSX
4020 	post_sys_powersource_internal(i, 0);
4021 #endif /* XNU_TARGET_OS_OSX */
4022 }
4023 
4024 
4025 #if XNU_TARGET_OS_OSX
4026 static void
post_sys_powersource_internal(int i,int internal)4027 post_sys_powersource_internal(int i, int internal)
4028 {
4029 	if (internal == 0) {
4030 		__system_power_source = i;
4031 	}
4032 }
4033 #endif /* XNU_TARGET_OS_OSX */
4034 
4035 void *
vm_shared_region_root_dir(struct vm_shared_region * sr)4036 vm_shared_region_root_dir(
4037 	struct vm_shared_region *sr)
4038 {
4039 	void *vnode;
4040 
4041 	vm_shared_region_lock();
4042 	vnode = sr->sr_root_dir;
4043 	vm_shared_region_unlock();
4044 	return vnode;
4045 }
4046