osfmk/vm/vm_map.c
1/*
2 * Copyright (c) 2000-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58/*
59 * File: vm/vm_map.c
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
61 * Date: 1985
62 *
63 * Virtual memory mapping module.
64 */
65
66#include <mach/vm_types.h>
67#include <mach_assert.h>
68
69#include <vm/vm_options.h>
70
71#include <libkern/OSAtomic.h>
72
73#include <mach/kern_return.h>
74#include <mach/port.h>
75#include <mach/vm_attributes.h>
76#include <mach/vm_param.h>
77#include <mach/vm_behavior.h>
78#include <mach/vm_statistics.h>
79#include <mach/memory_object.h>
80#include <mach/mach_vm_server.h>
81#include <machine/cpu_capabilities.h>
82#include <mach/sdt.h>
83
84#include <kern/assert.h>
85#include <kern/backtrace.h>
86#include <kern/counter.h>
87#include <kern/exc_guard.h>
88#include <kern/kalloc.h>
89#include <kern/zalloc_internal.h>
90#include <kern/telemetry.h>
91#include <kern/trap_telemetry.h>
92
93#include <vm/cpm_internal.h>
94#include <vm/vm_log.h>
95#include <vm/memory_types.h>
96#include <vm/vm_compressor_xnu.h>
97#include <vm/vm_compressor_pager_internal.h>
98#include <vm/vm_init_xnu.h>
99#include <vm/vm_fault_internal.h>
100#include <vm/vm_map_internal.h>
101#include <vm/vm_object_internal.h>
102#include <vm/vm_page_internal.h>
103#include <vm/vm_pageout.h>
104#include <vm/pmap.h>
105#include <vm/vm_kern_internal.h>
106#include <ipc/ipc_port.h>
107#include <kern/sched_prim.h>
108#include <kern/misc_protos.h>
109
110#include <mach/vm_map_server.h>
111#include <mach/mach_host_server.h>
112#include <vm/vm_memtag.h>
113#include <vm/vm_protos_internal.h>
114#include <vm/vm_purgeable_internal.h>
115
116#include <vm/vm_iokit.h>
117#include <vm/vm_lock_perf.h>
118#include <vm/vm_shared_region_internal.h>
119#include <vm/vm_map_store_internal.h>
120#include <vm/vm_memory_entry_xnu.h>
121#include <vm/memory_object_internal.h>
122#include <vm/vm_memory_entry.h>
123#include <vm/vm_sanitize_internal.h>
124#include <vm/vm_reclaim_xnu.h>
125#if DEVELOPMENT || DEBUG
126#include <vm/vm_compressor_info.h>
127#endif /* DEVELOPMENT || DEBUG */
128#include <ptrcheck.h>
129#include <san/kasan.h>
130
131#include <sys/resource.h>
132#include <sys/random.h>
133#include <sys/codesign.h>
134#include <sys/code_signing.h>
135#include <sys/mman.h>
136#include <sys/reboot.h>
137#include <sys/kdebug_triage.h>
138#include <sys/reason.h>
139
140#include <os/log.h>
141
142#include <libkern/section_keywords.h>
143#include <libkern/coreanalytics/coreanalytics.h>
144
145#include <os/hash.h>
146
147#if DEVELOPMENT || DEBUG
148extern int proc_selfcsflags(void);
149int vm_log_xnu_user_debug = 0;
150int panic_on_unsigned_execute = 0;
151int panic_on_mlock_failure = 0;
152#endif /* DEVELOPMENT || DEBUG */
153
154#if DEVELOPMENT || DEBUG
155int debug4k_filter = 0;
156char debug4k_proc_name[1024] = "";
157int debug4k_proc_filter = (int)-1 & ~(1 << __DEBUG4K_FAULT);
158int debug4k_panic_on_misaligned_sharing = 0;
159const char *debug4k_category_name[] = {
160 "error", /* 0 */
161 "life", /* 1 */
162 "load", /* 2 */
163 "fault", /* 3 */
164 "copy", /* 4 */
165 "share", /* 5 */
166 "adjust", /* 6 */
167 "pmap", /* 7 */
168 "mementry", /* 8 */
169 "iokit", /* 9 */
170 "upl", /* 10 */
171 "exc", /* 11 */
172 "vfs" /* 12 */
173};
174#endif /* DEVELOPMENT || DEBUG */
175int debug4k_no_cow_copyin = 0;
176
177
178#if __arm64__
179extern const int fourk_binary_compatibility_unsafe;
180#endif /* __arm64__ */
181extern int proc_selfpid(void);
182extern char *proc_name_address(void *p);
183extern const char *proc_best_name(struct proc *p);
184
185#if VM_MAP_DEBUG_APPLE_PROTECT
186int vm_map_debug_apple_protect = 0;
187#endif /* VM_MAP_DEBUG_APPLE_PROTECT */
188#if VM_MAP_DEBUG_FOURK
189int vm_map_debug_fourk = 0;
190#endif /* VM_MAP_DEBUG_FOURK */
191
192#if DEBUG || DEVELOPMENT
193static TUNABLE(bool, vm_map_executable_immutable,
194 "vm_map_executable_immutable", true);
195#else
196#define vm_map_executable_immutable true
197#endif
198
199/** Do not enforce the kernel allocation size limit */
200#define VM_MAP_KERNEL_ALLOC_LIMIT_MODE_BYPASS (0)
201/** Enforce the kernel allocation limit by refusing too large requests */
202#define VM_MAP_KERNEL_ALLOC_LIMIT_MODE_REJECT (1)
203/** Enforce the kernel allocation limit by panicking on any too large request */
204#define VM_MAP_KERNEL_ALLOC_LIMIT_MODE_PANIC (2)
205/** Do not enforce the kernel allocation limit but generate a telemetry trap */
206#define VM_MAP_KERNEL_ALLOC_LIMIT_MODE_TRAP (3)
207
208#if DEVELOPMENT || DEBUG
209static TUNABLE(int, vm_map_kernel_alloc_limit_mode,
210 "vm_map_kernel_alloc_limit_mode", VM_MAP_KERNEL_ALLOC_LIMIT_MODE_REJECT);
211#else
212#define vm_map_kernel_alloc_limit_mode VM_MAP_KERNEL_ALLOC_LIMIT_MODE_REJECT
213#endif
214
215SECURITY_READ_ONLY_EARLY(vm_packing_params_t) vm_map_entry_packing_params =
216 VM_PACKING_PARAMS(VM_ENTRY_PACKED_PTR);
217
218os_refgrp_decl(static, map_refgrp, "vm_map", NULL);
219
220extern u_int32_t random(void); /* from <libkern/libkern.h> */
221/* Internal prototypes
222 */
223
224typedef struct vm_map_zap {
225 vm_map_entry_t vmz_head;
226 vm_map_entry_t *vmz_tail;
227} *vm_map_zap_t;
228
229#define VM_MAP_ZAP_DECLARE(zap) \
230 struct vm_map_zap zap = { .vmz_tail = &zap.vmz_head }
231
232extern kern_return_t vm_map_wire_external(
233 vm_map_t map,
234 vm_map_offset_ut start_u,
235 vm_map_offset_ut end_u,
236 vm_prot_ut prot_u,
237 boolean_t user_wire) __exported;
238
239#if XNU_PLATFORM_MacOSX
240extern /* exported via Private.<arch>.MacOSX.exports on macOS */
241#else
242static
243#endif
244kern_return_t vm_map_copyin_common(
245 vm_map_t src_map,
246 vm_map_address_ut src_addr,
247 vm_map_size_ut len,
248 boolean_t src_destroy,
249 boolean_t src_volatile,
250 vm_map_copy_t *copy_result, /* OUT */
251 boolean_t use_maxprot);
252
253static vm_map_entry_t vm_map_entry_insert(
254 vm_map_t map,
255 vm_map_entry_t insp_entry,
256 vm_map_offset_t start,
257 vm_map_offset_t end,
258 vm_object_t object,
259 vm_object_offset_t offset,
260 vm_map_kernel_flags_t vmk_flags,
261 boolean_t needs_copy,
262 vm_prot_t cur_protection,
263 vm_prot_t max_protection,
264 vm_inherit_t inheritance);
265
266static void vm_map_simplify_range(
267 vm_map_t map,
268 vm_map_offset_t start,
269 vm_map_offset_t end); /* forward */
270
271static boolean_t vm_map_range_check(
272 vm_map_t map,
273 vm_map_offset_t start,
274 vm_map_offset_t end,
275 vm_map_entry_t *entry);
276
277static void vm_map_submap_pmap_clean(
278 vm_map_t map,
279 vm_map_offset_t start,
280 vm_map_offset_t end,
281 vm_map_t sub_map,
282 vm_map_offset_t offset);
283
284static void vm_map_pmap_enter(
285 vm_map_t map,
286 vm_map_offset_t addr,
287 vm_map_offset_t end_addr,
288 vm_object_t object,
289 vm_object_offset_t offset,
290 vm_prot_t protection);
291
292static void _vm_map_clip_end(
293 struct vm_map_header *map_header,
294 vm_map_entry_t entry,
295 vm_map_offset_t end);
296
297static void _vm_map_clip_start(
298 struct vm_map_header *map_header,
299 vm_map_entry_t entry,
300 vm_map_offset_t start);
301
302static kmem_return_t vm_map_delete(
303 vm_map_t map,
304 vm_map_offset_t start,
305 vm_map_offset_t end,
306 vmr_flags_t flags,
307 kmem_guard_t guard,
308 vm_map_zap_t zap);
309
310static void vm_map_copy_insert(
311 vm_map_t map,
312 vm_map_entry_t after_where,
313 vm_map_copy_t copy);
314
315static kern_return_t vm_map_copy_overwrite_unaligned(
316 vm_map_t dst_map,
317 vm_map_entry_t entry,
318 vm_map_copy_t copy,
319 vm_map_address_t start,
320 boolean_t discard_on_success);
321
322static kern_return_t vm_map_copy_overwrite_aligned(
323 vm_map_t dst_map,
324 vm_map_entry_t tmp_entry,
325 vm_map_copy_t copy,
326 vm_map_offset_t start,
327 pmap_t pmap);
328
329__options_closed_decl(vm_map_copyin_strategy, uint8_t, {
330 VM_MAP_COPYIN_STRATEGY_INVALID_ARGUMENT,
331 VM_MAP_COPYIN_STRATEGY_KERNEL_BUFFER,
332 VM_MAP_COPYIN_STRATEGY_VIRTUAL_COPY,
333});
334
335static kern_return_t vm_map_copyin_kernel_buffer(
336 vm_map_t src_map,
337 vm_map_address_t src_addr,
338 vm_map_size_t len,
339 vm_map_copyin_strategy strategy,
340 boolean_t src_destroy,
341 vm_map_copy_t *copy_result); /* OUT */
342
343static kern_return_t vm_map_copyout_kernel_buffer(
344 vm_map_t map,
345 vm_map_address_t *addr, /* IN/OUT */
346 vm_map_copy_t copy,
347 vm_map_size_t copy_size,
348 boolean_t overwrite,
349 boolean_t consume_on_success);
350
351static void vm_map_fork_share(
352 vm_map_t old_map,
353 vm_map_entry_t old_entry,
354 vm_map_t new_map);
355
356static boolean_t vm_map_fork_copy(
357 vm_map_t old_map,
358 vm_map_entry_t *old_entry_p,
359 vm_map_t new_map,
360 int vm_map_copyin_flags);
361
362static kern_return_t vm_map_wire_nested(
363 vm_map_t map,
364 vm_map_offset_t start,
365 vm_map_offset_t end,
366 vm_prot_t caller_prot,
367 vm_tag_t tag,
368 boolean_t user_wire,
369 pmap_t map_pmap,
370 vm_map_offset_t pmap_addr,
371 ppnum_t *physpage_p);
372
373static kern_return_t vm_map_unwire_nested(
374 vm_map_t map,
375 vm_map_offset_t start,
376 vm_map_offset_t end,
377 boolean_t user_wire,
378 pmap_t map_pmap,
379 vm_map_offset_t pmap_addr);
380
381static kern_return_t vm_map_overwrite_submap_recurse(
382 vm_map_t dst_map,
383 vm_map_offset_t dst_addr,
384 vm_map_size_t dst_size);
385
386static kern_return_t vm_map_copy_overwrite_nested(
387 vm_map_t dst_map,
388 vm_map_offset_t dst_addr,
389 vm_map_copy_t copy,
390 boolean_t interruptible,
391 pmap_t pmap,
392 boolean_t discard_on_success);
393
394static kern_return_t vm_map_remap_extract(
395 vm_map_t map,
396 vm_map_offset_t addr,
397 vm_map_size_t size,
398 boolean_t copy,
399 vm_map_copy_t map_copy,
400 vm_prot_t *cur_protection,
401 vm_prot_t *max_protection,
402 vm_inherit_t inheritance,
403 vm_map_kernel_flags_t vmk_flags);
404
405static void vm_map_region_look_for_page(
406 vm_map_t map,
407 vm_map_offset_t va,
408 vm_object_t object,
409 vm_object_offset_t offset,
410 int max_refcnt,
411 unsigned short depth,
412 vm_region_extended_info_t extended,
413 mach_msg_type_number_t count);
414
415static boolean_t vm_map_region_has_obj_ref(
416 vm_map_entry_t entry,
417 vm_object_t object);
418
419
420static kern_return_t vm_map_willneed(
421 vm_map_t map,
422 vm_map_offset_t start,
423 vm_map_offset_t end);
424
425static kern_return_t vm_map_reuse_pages(
426 vm_map_t map,
427 vm_map_offset_t start,
428 vm_map_offset_t end);
429
430static kern_return_t vm_map_reusable_pages(
431 vm_map_t map,
432 vm_map_offset_t start,
433 vm_map_offset_t end);
434
435static kern_return_t vm_map_can_reuse(
436 vm_map_t map,
437 vm_map_offset_t start,
438 vm_map_offset_t end);
439
440static kern_return_t vm_map_zero(
441 vm_map_t map,
442 vm_map_offset_t start,
443 vm_map_offset_t end);
444
445static kern_return_t vm_map_random_address_for_size(
446 vm_map_t map,
447 vm_map_offset_t *address,
448 vm_map_size_t size,
449 vm_map_kernel_flags_t vmk_flags);
450
451
452#if CONFIG_MAP_RANGES
453
454static vm_map_range_id_t vm_map_user_range_resolve(
455 vm_map_t map,
456 mach_vm_address_t addr,
457 mach_vm_address_t size,
458 mach_vm_range_t range);
459
460#endif /* CONFIG_MAP_RANGES */
461#if MACH_ASSERT
462static kern_return_t vm_map_pageout(
463 vm_map_t map,
464 vm_map_offset_t start,
465 vm_map_offset_t end);
466#endif /* MACH_ASSERT */
467
468kern_return_t vm_map_corpse_footprint_collect(
469 vm_map_t old_map,
470 vm_map_entry_t old_entry,
471 vm_map_t new_map);
472void vm_map_corpse_footprint_collect_done(
473 vm_map_t new_map);
474void vm_map_corpse_footprint_destroy(
475 vm_map_t map);
476kern_return_t vm_map_corpse_footprint_query_page_info(
477 vm_map_t map,
478 vm_map_offset_t va,
479 int *disposition_p);
480static void vm_map_footprint_query_page_info_exclusive(
481 vm_map_t map,
482 vm_map_entry_t map_entry,
483 vm_map_offset_t curr_s_offset,
484 int *disposition_p);
485
486#if CONFIG_MAP_RANGES
487static void vm_map_range_map_init(void);
488#endif /* CONFIG_MAP_RANGES */
489
490pid_t find_largest_process_vm_map_entries(void);
491
492uint8_t vm_map_entry_info_flags(
493 vm_map_entry_t entry);
494
495
496#if DEBUG || DEVELOPMENT
497#define panic_on_release_builds(format, ...) \
498 ({})
499#else /* not DEBUG || DEVELOPMENT */
500#define panic_on_release_builds(format, ...) \
501 panic(format __VA_OPT__(,) __VA_ARGS__)
502#endif /* not DEBUG || DEVELOPMENT */
503
504__attribute__((always_inline))
505int
506vm_map_kernel_flags_vmflags(vm_map_kernel_flags_t vmk_flags)
507{
508 int flags = vmk_flags.__vm_flags & VM_FLAGS_ANY_MASK;
509
510 /* in vmk flags the meaning of fixed/anywhere is inverted */
511 return flags ^ (VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE);
512}
513
514__attribute__((always_inline, overloadable))
515void
516vm_map_kernel_flags_set_vmflags(
517 vm_map_kernel_flags_t *vmk_flags,
518 int vm_flags,
519 vm_tag_t vm_tag)
520{
521 vm_flags ^= (VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE);
522 vmk_flags->__vm_flags &= ~VM_FLAGS_ANY_MASK;
523 vmk_flags->__vm_flags |= (vm_flags & VM_FLAGS_ANY_MASK);
524 vmk_flags->vm_tag = vm_tag;
525}
526
527__attribute__((always_inline, overloadable))
528void
529vm_map_kernel_flags_set_vmflags(
530 vm_map_kernel_flags_t *vmk_flags,
531 int vm_flags_and_tag)
532{
533 vm_flags_and_tag ^= (VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE);
534 vmk_flags->__vm_flags &= ~VM_FLAGS_ANY_MASK;
535 vmk_flags->__vm_flags |= (vm_flags_and_tag & VM_FLAGS_ANY_MASK);
536 VM_GET_FLAGS_ALIAS(vm_flags_and_tag, vmk_flags->vm_tag);
537}
538
539__attribute__((always_inline))
540void
541vm_map_kernel_flags_and_vmflags(
542 vm_map_kernel_flags_t *vmk_flags,
543 int vm_flags_mask)
544{
545 /* this function doesn't handle the inverted FIXED/ANYWHERE */
546 assert(vm_flags_mask & VM_FLAGS_ANYWHERE);
547 vmk_flags->__vm_flags &= vm_flags_mask;
548}
549
550__attribute__((always_inline))
551bool
552vm_map_kernel_flags_check_vm_and_kflags(
553 vm_map_kernel_flags_t vmk_flags,
554 int vm_flags_mask)
555{
556 return (vmk_flags.__vm_flags & ~vm_flags_mask) == 0;
557}
558
559bool
560vm_map_kernel_flags_check_vmflags(
561 vm_map_kernel_flags_t vmk_flags,
562 int vm_flags_mask)
563{
564 int vmflags = vmk_flags.__vm_flags & VM_FLAGS_ANY_MASK;
565
566 /* Note: up to 16 still has good calling conventions */
567 static_assert(sizeof(vm_map_kernel_flags_t) == 16);
568
569#if DEBUG || DEVELOPMENT
570 /*
571 * All of this compiles to nothing if all checks pass.
572 */
573#define check(field, value) ({ \
574 vm_map_kernel_flags_t fl = VM_MAP_KERNEL_FLAGS_NONE; \
575 fl.__vm_flags = (value); \
576 fl.field = 0; \
577 assert(fl.__vm_flags == 0); \
578})
579
580 /* bits 0-7 */
581 check(vmf_fixed, VM_FLAGS_ANYWHERE); // kind of a lie this is inverted
582 check(vmf_purgeable, VM_FLAGS_PURGABLE);
583 check(vmf_4gb_chunk, VM_FLAGS_4GB_CHUNK);
584 check(vmf_random_addr, VM_FLAGS_RANDOM_ADDR);
585 check(vmf_no_cache, VM_FLAGS_NO_CACHE);
586 check(vmf_resilient_codesign, VM_FLAGS_RESILIENT_CODESIGN);
587 check(vmf_resilient_media, VM_FLAGS_RESILIENT_MEDIA);
588 check(vmf_permanent, VM_FLAGS_PERMANENT);
589
590 /* bits 8-15 */
591 check(vmf_tpro, VM_FLAGS_TPRO);
592 check(vmf_overwrite, VM_FLAGS_OVERWRITE);
593
594 /* bits 16-23 */
595 check(vmf_superpage_size, VM_FLAGS_SUPERPAGE_MASK);
596 check(vmf_return_data_addr, VM_FLAGS_RETURN_DATA_ADDR);
597 check(vmf_return_4k_data_addr, VM_FLAGS_RETURN_4K_DATA_ADDR);
598
599 {
600 vm_map_kernel_flags_t fl = VM_MAP_KERNEL_FLAGS_NONE;
601
602 /* check user tags will never clip */
603 fl.vm_tag = VM_MEMORY_COUNT - 1;
604 assert(fl.vm_tag == VM_MEMORY_COUNT - 1);
605
606 /* check kernel tags will never clip */
607 fl.vm_tag = VM_MAX_TAG_VALUE - 1;
608 assert(fl.vm_tag == VM_MAX_TAG_VALUE - 1);
609 }
610
611
612#undef check
613#endif /* DEBUG || DEVELOPMENT */
614
615 return (vmflags & ~vm_flags_mask) == 0;
616}
617
618/*
619 * Macros to copy a vm_map_entry. We must be careful to correctly
620 * manage the wired page count. vm_map_entry_copy() creates a new
621 * map entry to the same memory - the wired count in the new entry
622 * must be set to zero. vm_map_entry_copy_full() creates a new
623 * entry that is identical to the old entry. This preserves the
624 * wire count; it's used for map splitting and zone changing in
625 * vm_map_copyout.
626 */
627
628static inline void
629vm_map_entry_copy_csm_assoc(
630 vm_map_t map __unused,
631 vm_map_entry_t new __unused,
632 vm_map_entry_t old __unused)
633{
634#if CODE_SIGNING_MONITOR
635 /* when code signing monitor is enabled, we want to reset on copy */
636 new->csm_associated = FALSE;
637#else
638 /* when code signing monitor is not enabled, assert as a sanity check */
639 assert(new->csm_associated == FALSE);
640#endif
641#if DEVELOPMENT || DEBUG
642 if (new->vme_xnu_user_debug && vm_log_xnu_user_debug) {
643 printf("FBDP %d[%s] %s:%d map %p entry %p [ 0x%llx 0x%llx ] vme_xnu_user_debug\n",
644 proc_selfpid(),
645 (get_bsdtask_info(current_task())
646 ? proc_name_address(get_bsdtask_info(current_task()))
647 : "?"),
648 __FUNCTION__, __LINE__,
649 map, new, new->vme_start, new->vme_end);
650 }
651#endif /* DEVELOPMENT || DEBUG */
652#if XNU_TARGET_OS_OSX
653 /*
654 * On macOS, entries with "vme_xnu_user_debug" can be copied during fork()
655 * and we want the child's entry to keep its "vme_xnu_user_debug" to avoid
656 * trigggering CSM assertions when the child accesses its mapping.
657 */
658#else /* XNU_TARGET_OS_OSX */
659 new->vme_xnu_user_debug = FALSE;
660#endif /* XNU_TARGET_OS_OSX */
661}
662
663/*
664 * The "used_for_jit" flag was copied from OLD to NEW in vm_map_entry_copy().
665 * But for security reasons on some platforms, we don't want the
666 * new mapping to be "used for jit", so we reset the flag here.
667 */
668static inline void
669vm_map_entry_copy_code_signing(
670 vm_map_t map,
671 vm_map_entry_t new,
672 vm_map_entry_t old __unused)
673{
674 if (VM_MAP_POLICY_ALLOW_JIT_COPY(map)) {
675 assert(new->used_for_jit == old->used_for_jit);
676 } else {
677 if (old->used_for_jit) {
678 DTRACE_VM3(cs_wx,
679 uint64_t, new->vme_start,
680 uint64_t, new->vme_end,
681 vm_prot_t, new->protection);
682 printf("CODE SIGNING: %d[%s] %s: curprot cannot be write+execute. %s\n",
683 proc_selfpid(),
684 (get_bsdtask_info(current_task())
685 ? proc_name_address(get_bsdtask_info(current_task()))
686 : "?"),
687 __FUNCTION__,
688 "removing execute access");
689 new->protection &= ~VM_PROT_EXECUTE;
690 new->max_protection &= ~VM_PROT_EXECUTE;
691 }
692 new->used_for_jit = FALSE;
693 }
694}
695
696static inline void
697vm_map_entry_copy_full(
698 vm_map_entry_t new,
699 vm_map_entry_t old)
700{
701#if MAP_ENTRY_CREATION_DEBUG
702 btref_put(new->vme_creation_bt);
703 btref_retain(old->vme_creation_bt);
704#endif
705#if MAP_ENTRY_INSERTION_DEBUG
706 btref_put(new->vme_insertion_bt);
707 btref_retain(old->vme_insertion_bt);
708#endif
709#if VM_BTLOG_TAGS
710 /* Discard the btref that might be in the new entry */
711 if (new->vme_kernel_object) {
712 btref_put(new->vme_tag_btref);
713 }
714 /* Retain the btref in the old entry to account for its copy */
715 if (old->vme_kernel_object) {
716 btref_retain(old->vme_tag_btref);
717 }
718#endif /* VM_BTLOG_TAGS */
719 *new = *old;
720}
721
722static inline void
723vm_map_entry_copy(
724 vm_map_t map,
725 vm_map_entry_t new,
726 vm_map_entry_t old)
727{
728 vm_map_entry_copy_full(new, old);
729
730 new->is_shared = FALSE;
731 new->needs_wakeup = FALSE;
732 new->in_transition = FALSE;
733 new->wired_count = 0;
734 new->user_wired_count = 0;
735 new->vme_permanent = FALSE;
736 vm_map_entry_copy_code_signing(map, new, old);
737 vm_map_entry_copy_csm_assoc(map, new, old);
738 if (new->iokit_acct) {
739 assertf(!new->use_pmap, "old %p new %p\n", old, new);
740 new->iokit_acct = FALSE;
741 new->use_pmap = TRUE;
742 }
743 new->vme_resilient_codesign = FALSE;
744 new->vme_resilient_media = FALSE;
745 new->vme_atomic = FALSE;
746 new->vme_no_copy_on_read = FALSE;
747}
748
749/*
750 * Normal lock_read_to_write() returns FALSE/0 on failure.
751 * These functions evaluate to zero on success and non-zero value on failure.
752 */
753__attribute__((always_inline))
754int
755vm_map_lock_read_to_write(vm_map_t map)
756{
757 vmlp_lock_event_locked(VMLP_EVENT_LOCK_TRY_UPGRADE, map);
758 assert(!vm_map_is_sealed(map));
759 if (lck_rw_lock_shared_to_exclusive(&(map)->lock)) {
760 DTRACE_VM(vm_map_lock_upgrade);
761 vmlp_lock_event_locked(VMLP_EVENT_LOCK_GOT_UPGRADE, map);
762 return 0;
763 }
764 vmlp_lock_event_unlocked(VMLP_EVENT_LOCK_FAIL_UPGRADE, map);
765 return 1;
766}
767
768__attribute__((always_inline))
769boolean_t
770vm_map_try_lock(vm_map_t map)
771{
772 vmlp_lock_event_unlocked(VMLP_EVENT_LOCK_TRY_EXCL, map);
773 if (lck_rw_try_lock_exclusive(&(map)->lock)) {
774 DTRACE_VM(vm_map_lock_w);
775 vmlp_lock_event_locked(VMLP_EVENT_LOCK_GOT_EXCL, map);
776 return TRUE;
777 }
778 vmlp_lock_event_unlocked(VMLP_EVENT_LOCK_FAIL_EXCL, map);
779 return FALSE;
780}
781
782__attribute__((always_inline))
783boolean_t
784vm_map_try_lock_read(vm_map_t map)
785{
786 vmlp_lock_event_unlocked(VMLP_EVENT_LOCK_TRY_SH, map);
787 if (lck_rw_try_lock_shared(&(map)->lock)) {
788 DTRACE_VM(vm_map_lock_r);
789 vmlp_lock_event_locked(VMLP_EVENT_LOCK_GOT_SH, map);
790 return TRUE;
791 }
792 vmlp_lock_event_unlocked(VMLP_EVENT_LOCK_FAIL_SH, map);
793 return FALSE;
794}
795
796/*!
797 * @function kdp_vm_map_is_acquired_exclusive
798 *
799 * @abstract
800 * Checks if vm map is acquired exclusive.
801 *
802 * @discussion
803 * NOT SAFE: To be used only by kernel debugger.
804 *
805 * @param map map to check
806 *
807 * @returns TRUE if the map is acquired exclusively.
808 */
809boolean_t
810kdp_vm_map_is_acquired_exclusive(vm_map_t map)
811{
812 return kdp_lck_rw_lock_is_acquired_exclusive(&map->lock);
813}
814
815/*
816 * Routines to get the page size the caller should
817 * use while inspecting the target address space.
818 * Use the "_safely" variant if the caller is dealing with a user-provided
819 * array whose size depends on the page size, to avoid any overflow or
820 * underflow of a user-allocated buffer.
821 */
822int
823vm_self_region_page_shift_safely(
824 vm_map_t target_map)
825{
826 int effective_page_shift = 0;
827
828 if (PAGE_SIZE == (4096)) {
829 /* x86_64 and 4k watches: always use 4k */
830 return PAGE_SHIFT;
831 }
832 /* did caller provide an explicit page size for this thread to use? */
833 effective_page_shift = thread_self_region_page_shift();
834 if (effective_page_shift) {
835 /* use the explicitly-provided page size */
836 return effective_page_shift;
837 }
838 /* no explicit page size: use the caller's page size... */
839 effective_page_shift = VM_MAP_PAGE_SHIFT(current_map());
840 if (effective_page_shift == VM_MAP_PAGE_SHIFT(target_map)) {
841 /* page size match: safe to use */
842 return effective_page_shift;
843 }
844 /* page size mismatch */
845 return -1;
846}
847int
848vm_self_region_page_shift(
849 vm_map_t target_map)
850{
851 int effective_page_shift;
852
853 effective_page_shift = vm_self_region_page_shift_safely(target_map);
854 if (effective_page_shift == -1) {
855 /* no safe value but OK to guess for caller */
856 effective_page_shift = MIN(VM_MAP_PAGE_SHIFT(current_map()),
857 VM_MAP_PAGE_SHIFT(target_map));
858 }
859 return effective_page_shift;
860}
861
862
863/*
864 * Decide if we want to allow processes to execute from their data or stack areas.
865 * override_nx() returns true if we do. Data/stack execution can be enabled independently
866 * for 32 and 64 bit processes. Set the VM_ABI_32 or VM_ABI_64 flags in allow_data_exec
867 * or allow_stack_exec to enable data execution for that type of data area for that particular
868 * ABI (or both by or'ing the flags together). These are initialized in the architecture
869 * specific pmap files since the default behavior varies according to architecture. The
870 * main reason it varies is because of the need to provide binary compatibility with old
871 * applications that were written before these restrictions came into being. In the old
872 * days, an app could execute anything it could read, but this has slowly been tightened
873 * up over time. The default behavior is:
874 *
875 * 32-bit PPC apps may execute from both stack and data areas
876 * 32-bit Intel apps may exeucte from data areas but not stack
877 * 64-bit PPC/Intel apps may not execute from either data or stack
878 *
879 * An application on any architecture may override these defaults by explicitly
880 * adding PROT_EXEC permission to the page in question with the mprotect(2)
881 * system call. This code here just determines what happens when an app tries to
882 * execute from a page that lacks execute permission.
883 *
884 * Note that allow_data_exec or allow_stack_exec may also be modified by sysctl to change the
885 * default behavior for both 32 and 64 bit apps on a system-wide basis. Furthermore,
886 * a Mach-O header flag bit (MH_NO_HEAP_EXECUTION) can be used to forcibly disallow
887 * execution from data areas for a particular binary even if the arch normally permits it. As
888 * a final wrinkle, a posix_spawn attribute flag can be used to negate this opt-in header bit
889 * to support some complicated use cases, notably browsers with out-of-process plugins that
890 * are not all NX-safe.
891 */
892
893extern int allow_data_exec, allow_stack_exec;
894
895int
896override_nx(vm_map_t map, uint32_t user_tag) /* map unused on arm */
897{
898 int current_abi;
899
900 if (map->pmap == kernel_pmap) {
901 return FALSE;
902 }
903
904 /*
905 * Determine if the app is running in 32 or 64 bit mode.
906 */
907
908 if (vm_map_is_64bit(map)) {
909 current_abi = VM_ABI_64;
910 } else {
911 current_abi = VM_ABI_32;
912 }
913
914 /*
915 * Determine if we should allow the execution based on whether it's a
916 * stack or data area and the current architecture.
917 */
918
919 if (user_tag == VM_MEMORY_STACK) {
920 return allow_stack_exec & current_abi;
921 }
922
923 return (allow_data_exec & current_abi) && (map->map_disallow_data_exec == FALSE);
924}
925
926
927/*
928 * Virtual memory maps provide for the mapping, protection,
929 * and sharing of virtual memory objects. In addition,
930 * this module provides for an efficient virtual copy of
931 * memory from one map to another.
932 *
933 * Synchronization is required prior to most operations.
934 *
935 * Maps consist of an ordered doubly-linked list of simple
936 * entries; a single hint is used to speed up lookups.
937 *
938 * Sharing maps have been deleted from this version of Mach.
939 * All shared objects are now mapped directly into the respective
940 * maps. This requires a change in the copy on write strategy;
941 * the asymmetric (delayed) strategy is used for shared temporary
942 * objects instead of the symmetric (shadow) strategy. All maps
943 * are now "top level" maps (either task map, kernel map or submap
944 * of the kernel map).
945 *
946 * Since portions of maps are specified by start/end addreses,
947 * which may not align with existing map entries, all
948 * routines merely "clip" entries to these start/end values.
949 * [That is, an entry is split into two, bordering at a
950 * start or end value.] Note that these clippings may not
951 * always be necessary (as the two resulting entries are then
952 * not changed); however, the clipping is done for convenience.
953 * No attempt is currently made to "glue back together" two
954 * abutting entries.
955 *
956 * The symmetric (shadow) copy strategy implements virtual copy
957 * by copying VM object references from one map to
958 * another, and then marking both regions as copy-on-write.
959 * It is important to note that only one writeable reference
960 * to a VM object region exists in any map when this strategy
961 * is used -- this means that shadow object creation can be
962 * delayed until a write operation occurs. The symmetric (delayed)
963 * strategy allows multiple maps to have writeable references to
964 * the same region of a vm object, and hence cannot delay creating
965 * its copy objects. See vm_object_copy_quickly() in vm_object.c.
966 * Copying of permanent objects is completely different; see
967 * vm_object_copy_strategically() in vm_object.c.
968 */
969
970ZONE_DECLARE_ID(ZONE_ID_VM_MAP_COPY, struct vm_map_copy);
971
972#define VM_MAP_ZONE_NAME "maps"
973#define VM_MAP_ZFLAGS (ZC_NOENCRYPT | ZC_VM)
974
975#define VM_MAP_ENTRY_ZONE_NAME "VM map entries"
976#define VM_MAP_ENTRY_ZFLAGS (ZC_NOENCRYPT | ZC_VM)
977
978#define VM_MAP_HOLES_ZONE_NAME "VM map holes"
979#define VM_MAP_HOLES_ZFLAGS (ZC_NOENCRYPT | ZC_VM)
980
981/*
982 * Asserts that a vm_map_copy object is coming from the
983 * vm_map_copy_zone to ensure that it isn't a fake constructed
984 * anywhere else.
985 */
986void
987vm_map_copy_require(struct vm_map_copy *copy)
988{
989 zone_id_require(ZONE_ID_VM_MAP_COPY, sizeof(struct vm_map_copy), copy);
990}
991
992/*
993 * vm_map_require:
994 *
995 * Ensures that the argument is memory allocated from the genuine
996 * vm map zone. (See zone_id_require_allow_foreign).
997 */
998void
999vm_map_require(vm_map_t map)
1000{
1001 zone_id_require(ZONE_ID_VM_MAP, sizeof(struct _vm_map), map);
1002}
1003
1004#define VM_MAP_EARLY_COUNT_MAX 16
1005static __startup_data vm_offset_t map_data;
1006static __startup_data vm_size_t map_data_size;
1007static __startup_data vm_offset_t kentry_data;
1008static __startup_data vm_size_t kentry_data_size;
1009static __startup_data vm_offset_t map_holes_data;
1010static __startup_data vm_size_t map_holes_data_size;
1011static __startup_data vm_map_t *early_map_owners[VM_MAP_EARLY_COUNT_MAX];
1012static __startup_data uint32_t early_map_count;
1013
1014#if XNU_TARGET_OS_OSX
1015#define NO_COALESCE_LIMIT ((1024 * 128) - 1)
1016#else /* XNU_TARGET_OS_OSX */
1017#define NO_COALESCE_LIMIT 0
1018#endif /* XNU_TARGET_OS_OSX */
1019
1020/* Skip acquiring locks if we're in the midst of a kernel core dump */
1021unsigned int not_in_kdp = 1;
1022
1023unsigned int vm_map_set_cache_attr_count = 0;
1024
1025kern_return_t
1026vm_map_set_cache_attr(
1027 vm_map_t map,
1028 vm_map_offset_t va)
1029{
1030 vm_map_entry_t map_entry;
1031 vm_object_t object;
1032 kern_return_t kr = KERN_SUCCESS;
1033
1034 vmlp_api_start(VM_MAP_SET_CACHE_ATTR);
1035
1036 vm_map_lock_read(map);
1037
1038 if (!vm_map_lookup_entry(map, va, &map_entry) ||
1039 map_entry->is_sub_map) {
1040 /*
1041 * that memory is not properly mapped
1042 */
1043 kr = KERN_INVALID_ARGUMENT;
1044 goto done;
1045 }
1046
1047 vmlp_range_event_entry(map, map_entry);
1048
1049 object = VME_OBJECT(map_entry);
1050
1051 if (object == VM_OBJECT_NULL) {
1052 /*
1053 * there should be a VM object here at this point
1054 */
1055 kr = KERN_INVALID_ARGUMENT;
1056 goto done;
1057 }
1058 vm_object_lock(object);
1059 object->set_cache_attr = TRUE;
1060 vm_object_unlock(object);
1061
1062 vm_map_set_cache_attr_count++;
1063done:
1064 vm_map_unlock_read(map);
1065
1066 vmlp_api_end(VM_MAP_SET_CACHE_ATTR, kr);
1067 return kr;
1068}
1069
1070
1071#if CONFIG_CODE_DECRYPTION
1072/*
1073 * vm_map_apple_protected:
1074 * This remaps the requested part of the object with an object backed by
1075 * the decrypting pager.
1076 * crypt_info contains entry points and session data for the crypt module.
1077 * The crypt_info block will be copied by vm_map_apple_protected. The data structures
1078 * referenced in crypt_info must remain valid until crypt_info->crypt_end() is called.
1079 */
1080kern_return_t
1081vm_map_apple_protected(
1082 vm_map_t map,
1083 vm_map_offset_t start,
1084 vm_map_offset_t end,
1085 vm_object_offset_t crypto_backing_offset,
1086 struct pager_crypt_info *crypt_info,
1087 uint32_t cryptid)
1088{
1089 boolean_t map_locked;
1090 kern_return_t kr;
1091 vm_map_entry_t map_entry;
1092 struct vm_map_entry tmp_entry;
1093 memory_object_t unprotected_mem_obj;
1094 vm_object_t protected_object;
1095 vm_map_offset_t map_addr;
1096 vm_map_offset_t start_aligned, end_aligned;
1097 vm_object_offset_t crypto_start, crypto_end;
1098 boolean_t cache_pager;
1099
1100 vmlp_api_start(VM_MAP_APPLE_PROTECTED);
1101
1102 map_locked = FALSE;
1103 unprotected_mem_obj = MEMORY_OBJECT_NULL;
1104
1105 if (__improbable(vm_map_range_overflows(map, start, end - start))) {
1106 vmlp_api_end(VM_MAP_APPLE_PROTECTED, KERN_INVALID_ADDRESS);
1107 return KERN_INVALID_ADDRESS;
1108 }
1109 start_aligned = vm_map_trunc_page(start, PAGE_MASK_64);
1110 end_aligned = vm_map_round_page(end, PAGE_MASK_64);
1111 start_aligned = vm_map_trunc_page(start_aligned, VM_MAP_PAGE_MASK(map));
1112 end_aligned = vm_map_round_page(end_aligned, VM_MAP_PAGE_MASK(map));
1113
1114#if __arm64__
1115 /*
1116 * "start" and "end" might be 4K-aligned but not 16K-aligned,
1117 * so we might have to loop and establish up to 3 mappings:
1118 *
1119 * + the first 16K-page, which might overlap with the previous
1120 * 4K-aligned mapping,
1121 * + the center,
1122 * + the last 16K-page, which might overlap with the next
1123 * 4K-aligned mapping.
1124 * Each of these mapping might be backed by a vnode pager (if
1125 * properly page-aligned) or a "fourk_pager", itself backed by a
1126 * vnode pager (if 4K-aligned but not page-aligned).
1127 */
1128#endif /* __arm64__ */
1129
1130 map_addr = start_aligned;
1131 for (map_addr = start_aligned;
1132 map_addr < end;
1133 map_addr = tmp_entry.vme_end) {
1134 vm_map_lock(map);
1135 map_locked = TRUE;
1136
1137 /* lookup the protected VM object */
1138 if (!vm_map_lookup_entry(map,
1139 map_addr,
1140 &map_entry) ||
1141 map_entry->is_sub_map ||
1142 VME_OBJECT(map_entry) == VM_OBJECT_NULL) {
1143 /* that memory is not properly mapped */
1144 kr = KERN_INVALID_ARGUMENT;
1145 goto done;
1146 }
1147
1148 /* ensure mapped memory is mapped as executable except
1149 * except for model decryption flow */
1150 if ((cryptid != CRYPTID_MODEL_ENCRYPTION) &&
1151 !(map_entry->protection & VM_PROT_EXECUTE)) {
1152 kr = KERN_INVALID_ARGUMENT;
1153 goto done;
1154 }
1155
1156 /* get the protected object to be decrypted */
1157 protected_object = VME_OBJECT(map_entry);
1158 if (protected_object == VM_OBJECT_NULL) {
1159 /* there should be a VM object here at this point */
1160 kr = KERN_INVALID_ARGUMENT;
1161 goto done;
1162 }
1163 /* ensure protected object stays alive while map is unlocked */
1164 vm_object_reference(protected_object);
1165
1166 /* limit the map entry to the area we want to cover */
1167 vm_map_clip_start(map, map_entry, start_aligned);
1168 vm_map_clip_end(map, map_entry, end_aligned);
1169
1170 tmp_entry = *map_entry;
1171 vmlp_range_event_entry(map, &tmp_entry);
1172 map_entry = VM_MAP_ENTRY_NULL; /* not valid after unlocking map */
1173 vm_map_unlock(map);
1174 map_locked = FALSE;
1175
1176 /*
1177 * This map entry might be only partially encrypted
1178 * (if not fully "page-aligned").
1179 */
1180 crypto_start = 0;
1181 crypto_end = tmp_entry.vme_end - tmp_entry.vme_start;
1182 if (tmp_entry.vme_start < start) {
1183 if (tmp_entry.vme_start != start_aligned) {
1184 kr = KERN_INVALID_ADDRESS;
1185 vm_object_deallocate(protected_object);
1186 goto done;
1187 }
1188 crypto_start += (start - tmp_entry.vme_start);
1189 }
1190 if (tmp_entry.vme_end > end) {
1191 if (tmp_entry.vme_end != end_aligned) {
1192 kr = KERN_INVALID_ADDRESS;
1193 vm_object_deallocate(protected_object);
1194 goto done;
1195 }
1196 crypto_end -= (tmp_entry.vme_end - end);
1197 }
1198
1199 /*
1200 * This "extra backing offset" is needed to get the decryption
1201 * routine to use the right key. It adjusts for the possibly
1202 * relative offset of an interposed "4K" pager...
1203 */
1204 if (crypto_backing_offset == (vm_object_offset_t) -1) {
1205 crypto_backing_offset = VME_OFFSET(&tmp_entry);
1206 }
1207
1208 cache_pager = TRUE;
1209#if XNU_TARGET_OS_OSX
1210 if (vm_map_is_alien(map)) {
1211 cache_pager = FALSE;
1212 }
1213#endif /* XNU_TARGET_OS_OSX */
1214
1215 /*
1216 * Lookup (and create if necessary) the protected memory object
1217 * matching that VM object.
1218 * If successful, this also grabs a reference on the memory object,
1219 * to guarantee that it doesn't go away before we get a chance to map
1220 * it.
1221 */
1222 unprotected_mem_obj = apple_protect_pager_setup(
1223 protected_object,
1224 VME_OFFSET(&tmp_entry),
1225 crypto_backing_offset,
1226 crypt_info,
1227 crypto_start,
1228 crypto_end,
1229 cache_pager);
1230
1231 /* release extra ref on protected object */
1232 vm_object_deallocate(protected_object);
1233
1234 if (unprotected_mem_obj == NULL) {
1235 kr = KERN_FAILURE;
1236 goto done;
1237 }
1238
1239 /* can overwrite an immutable mapping */
1240 vm_map_kernel_flags_t vmk_flags = {
1241 .vmf_fixed = true,
1242 .vmf_overwrite = true,
1243 .vmkf_overwrite_immutable = true,
1244 };
1245 /* make the new mapping as "permanent" as the one it replaces */
1246 vmk_flags.vmf_permanent = tmp_entry.vme_permanent;
1247
1248 /* map this memory object in place of the current one */
1249 map_addr = tmp_entry.vme_start;
1250 kr = mach_vm_map_kernel(map,
1251 vm_sanitize_wrap_addr_ref(&map_addr),
1252 (tmp_entry.vme_end -
1253 tmp_entry.vme_start),
1254 (mach_vm_offset_t) 0,
1255 vmk_flags,
1256 (ipc_port_t)(uintptr_t) unprotected_mem_obj,
1257 0,
1258 TRUE,
1259 tmp_entry.protection,
1260 tmp_entry.max_protection,
1261 tmp_entry.inheritance);
1262 assertf(kr == KERN_SUCCESS,
1263 "kr = 0x%x\n", kr);
1264 assertf(map_addr == tmp_entry.vme_start,
1265 "map_addr=0x%llx vme_start=0x%llx tmp_entry=%p\n",
1266 (uint64_t)map_addr,
1267 (uint64_t) tmp_entry.vme_start,
1268 &tmp_entry);
1269
1270#if VM_MAP_DEBUG_APPLE_PROTECT
1271 if (vm_map_debug_apple_protect) {
1272 printf("APPLE_PROTECT: map %p [0x%llx:0x%llx] pager %p:"
1273 " backing:[object:%p,offset:0x%llx,"
1274 "crypto_backing_offset:0x%llx,"
1275 "crypto_start:0x%llx,crypto_end:0x%llx]\n",
1276 map,
1277 (uint64_t) map_addr,
1278 (uint64_t) (map_addr + (tmp_entry.vme_end -
1279 tmp_entry.vme_start)),
1280 unprotected_mem_obj,
1281 protected_object,
1282 VME_OFFSET(&tmp_entry),
1283 crypto_backing_offset,
1284 crypto_start,
1285 crypto_end);
1286 }
1287#endif /* VM_MAP_DEBUG_APPLE_PROTECT */
1288
1289 /*
1290 * Release the reference obtained by
1291 * apple_protect_pager_setup().
1292 * The mapping (if it succeeded) is now holding a reference on
1293 * the memory object.
1294 */
1295 memory_object_deallocate(unprotected_mem_obj);
1296 unprotected_mem_obj = MEMORY_OBJECT_NULL;
1297
1298 /* continue with next map entry */
1299 crypto_backing_offset += (tmp_entry.vme_end -
1300 tmp_entry.vme_start);
1301 crypto_backing_offset -= crypto_start;
1302 }
1303 kr = KERN_SUCCESS;
1304
1305done:
1306 if (map_locked) {
1307 vm_map_unlock(map);
1308 }
1309 vmlp_api_end(VM_MAP_APPLE_PROTECTED, kr);
1310 return kr;
1311}
1312#endif /* CONFIG_CODE_DECRYPTION */
1313
1314
1315LCK_GRP_DECLARE(vm_map_lck_grp, "vm_map");
1316LCK_ATTR_DECLARE(vm_map_lck_attr, 0, 0);
1317LCK_ATTR_DECLARE(vm_map_lck_rw_attr, 0, LCK_ATTR_DEBUG);
1318
1319#if XNU_TARGET_OS_OSX
1320#define MALLOC_NO_COW_DEFAULT 1
1321#define MALLOC_NO_COW_EXCEPT_FORK_DEFAULT 1
1322#else /* XNU_TARGET_OS_OSX */
1323#define MALLOC_NO_COW_DEFAULT 1
1324#define MALLOC_NO_COW_EXCEPT_FORK_DEFAULT 0
1325#endif /* XNU_TARGET_OS_OSX */
1326TUNABLE(int, malloc_no_cow, "malloc_no_cow", MALLOC_NO_COW_DEFAULT);
1327TUNABLE(int, malloc_no_cow_except_fork, "malloc_no_cow_except_fork", MALLOC_NO_COW_EXCEPT_FORK_DEFAULT);
1328uint64_t vm_memory_malloc_no_cow_mask = 0ULL;
1329#if DEBUG
1330int vm_check_map_sanity = 0;
1331#endif
1332
1333/*
1334 * vm_map_init:
1335 *
1336 * Initialize the vm_map module. Must be called before
1337 * any other vm_map routines.
1338 *
1339 * Map and entry structures are allocated from zones -- we must
1340 * initialize those zones.
1341 *
1342 * There are three zones of interest:
1343 *
1344 * vm_map_zone: used to allocate maps.
1345 * vm_map_entry_zone: used to allocate map entries.
1346 *
1347 * LP32:
1348 * vm_map_entry_reserved_zone: fallback zone for kernel map entries
1349 *
1350 * The kernel allocates map entries from a special zone that is initially
1351 * "crammed" with memory. It would be difficult (perhaps impossible) for
1352 * the kernel to allocate more memory to a entry zone when it became
1353 * empty since the very act of allocating memory implies the creation
1354 * of a new entry.
1355 */
1356__startup_func
1357void
1358vm_map_init(void)
1359{
1360
1361#if MACH_ASSERT
1362 PE_parse_boot_argn("debug4k_filter", &debug4k_filter,
1363 sizeof(debug4k_filter));
1364#endif /* MACH_ASSERT */
1365
1366 zone_create_ext(VM_MAP_ZONE_NAME, sizeof(struct _vm_map),
1367 VM_MAP_ZFLAGS, ZONE_ID_VM_MAP, NULL);
1368
1369 /*
1370 * Don't quarantine because we always need elements available
1371 * Disallow GC on this zone... to aid the GC.
1372 */
1373 zone_create_ext(VM_MAP_ENTRY_ZONE_NAME,
1374 sizeof(struct vm_map_entry), VM_MAP_ENTRY_ZFLAGS,
1375 ZONE_ID_VM_MAP_ENTRY, ^(zone_t z) {
1376 z->z_elems_rsv = (uint16_t)(32 *
1377 (ml_early_cpu_max_number() + 1));
1378 });
1379
1380 zone_create_ext(VM_MAP_HOLES_ZONE_NAME,
1381 sizeof(struct vm_map_links), VM_MAP_HOLES_ZFLAGS,
1382 ZONE_ID_VM_MAP_HOLES, ^(zone_t z) {
1383 z->z_elems_rsv = (uint16_t)(16 * 1024 / zone_elem_outer_size(z));
1384 });
1385
1386 zone_create_ext("VM map copies", sizeof(struct vm_map_copy),
1387 ZC_NOENCRYPT, ZONE_ID_VM_MAP_COPY, NULL);
1388
1389 /*
1390 * Add the stolen memory to zones, adjust zone size and stolen counts.
1391 */
1392 zone_cram_early(vm_map_zone, map_data, map_data_size);
1393 zone_cram_early(vm_map_entry_zone, kentry_data, kentry_data_size);
1394 zone_cram_early(vm_map_holes_zone, map_holes_data, map_holes_data_size);
1395 printf("VM boostrap: %d maps, %d entries and %d holes available\n",
1396 zone_count_free(vm_map_zone),
1397 zone_count_free(vm_map_entry_zone),
1398 zone_count_free(vm_map_holes_zone));
1399
1400 /*
1401 * Since these are covered by zones, remove them from stolen page accounting.
1402 */
1403 VM_PAGE_MOVE_STOLEN(atop_64(map_data_size) + atop_64(kentry_data_size) + atop_64(map_holes_data_size));
1404
1405#if VM_MAP_DEBUG_APPLE_PROTECT
1406 PE_parse_boot_argn("vm_map_debug_apple_protect",
1407 &vm_map_debug_apple_protect,
1408 sizeof(vm_map_debug_apple_protect));
1409#endif /* VM_MAP_DEBUG_APPLE_PROTECT */
1410#if VM_MAP_DEBUG_APPLE_FOURK
1411 PE_parse_boot_argn("vm_map_debug_fourk",
1412 &vm_map_debug_fourk,
1413 sizeof(vm_map_debug_fourk));
1414#endif /* VM_MAP_DEBUG_FOURK */
1415
1416 if (malloc_no_cow) {
1417 vm_memory_malloc_no_cow_mask = 0ULL;
1418 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC;
1419 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_SMALL;
1420 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_MEDIUM;
1421#if XNU_TARGET_OS_OSX
1422 /*
1423 * On macOS, keep copy-on-write for MALLOC_LARGE because
1424 * realloc() may use vm_copy() to transfer the old contents
1425 * to the new location.
1426 */
1427#else /* XNU_TARGET_OS_OSX */
1428 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_LARGE;
1429 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_LARGE_REUSABLE;
1430 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_LARGE_REUSED;
1431#endif /* XNU_TARGET_OS_OSX */
1432// vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_HUGE;
1433// vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_REALLOC;
1434 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_TINY;
1435 vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_MALLOC_NANO;
1436// vm_memory_malloc_no_cow_mask |= 1ULL << VM_MEMORY_TCMALLOC;
1437 PE_parse_boot_argn("vm_memory_malloc_no_cow_mask",
1438 &vm_memory_malloc_no_cow_mask,
1439 sizeof(vm_memory_malloc_no_cow_mask));
1440 }
1441
1442#if CONFIG_MAP_RANGES
1443 vm_map_range_map_init();
1444#endif /* CONFIG_MAP_RANGES */
1445
1446#if DEBUG
1447 PE_parse_boot_argn("vm_check_map_sanity", &vm_check_map_sanity, sizeof(vm_check_map_sanity));
1448 if (vm_check_map_sanity) {
1449 kprintf("VM sanity checking enabled\n");
1450 } else {
1451 kprintf("VM sanity checking disabled. Set bootarg vm_check_map_sanity=1 to enable\n");
1452 }
1453#endif /* DEBUG */
1454
1455#if DEVELOPMENT || DEBUG
1456 PE_parse_boot_argn("panic_on_unsigned_execute",
1457 &panic_on_unsigned_execute,
1458 sizeof(panic_on_unsigned_execute));
1459 PE_parse_boot_argn("panic_on_mlock_failure",
1460 &panic_on_mlock_failure,
1461 sizeof(panic_on_mlock_failure));
1462#endif /* DEVELOPMENT || DEBUG */
1463}
1464
1465__startup_func
1466static void
1467vm_map_steal_memory(void)
1468{
1469
1470 /*
1471 * We need to reserve enough memory to support boostraping VM maps
1472 * and the zone subsystem.
1473 *
1474 * The VM Maps that need to function before zones can support them
1475 * are the ones registered with vm_map_will_allocate_early_map(),
1476 * which are:
1477 * - the kernel map
1478 * - the various submaps used by zones (meta, ...)
1479 *
1480 * We also need enough entries and holes to support them
1481 * until zone_metadata_init() is called, which is when
1482 * the zone allocator becomes capable of expanding dynamically.
1483 *
1484 * We need:
1485 * - VM_MAP_EARLY_COUNT_MAX worth of VM Maps.
1486 * - To allow for 3-4 entries per map, but the kernel map
1487 * needs a multiple of VM_MAP_EARLY_COUNT_MAX entries
1488 * to describe the submaps, so double it (and make it 8x too)
1489 * - To allow for holes between entries,
1490 * hence needs the same budget as entries
1491 */
1492 map_data_size = zone_get_early_alloc_size(VM_MAP_ZONE_NAME,
1493 sizeof(struct _vm_map), VM_MAP_ZFLAGS,
1494 VM_MAP_EARLY_COUNT_MAX);
1495
1496 kentry_data_size = zone_get_early_alloc_size(VM_MAP_ENTRY_ZONE_NAME,
1497 sizeof(struct vm_map_entry), VM_MAP_ENTRY_ZFLAGS,
1498 8 * VM_MAP_EARLY_COUNT_MAX);
1499
1500 map_holes_data_size = zone_get_early_alloc_size(VM_MAP_HOLES_ZONE_NAME,
1501 sizeof(struct vm_map_links), VM_MAP_HOLES_ZFLAGS,
1502 8 * VM_MAP_EARLY_COUNT_MAX);
1503
1504 /*
1505 * Steal a contiguous range of memory so that a simple range check
1506 * can validate early addresses being freed/crammed to these
1507 * zones
1508 */
1509 map_data = zone_early_mem_init(map_data_size + kentry_data_size +
1510 map_holes_data_size);
1511 kentry_data = map_data + map_data_size;
1512 map_holes_data = kentry_data + kentry_data_size;
1513}
1514STARTUP(PMAP_STEAL, STARTUP_RANK_FIRST, vm_map_steal_memory);
1515
1516__startup_func
1517static void
1518vm_kernel_boostraped(void)
1519{
1520 zone_enable_caching(&zone_array[ZONE_ID_VM_MAP_ENTRY]);
1521 zone_enable_caching(&zone_array[ZONE_ID_VM_MAP_HOLES]);
1522 zone_enable_caching(&zone_array[ZONE_ID_VM_MAP_COPY]);
1523
1524 printf("VM bootstrap done: %d maps, %d entries and %d holes left\n",
1525 zone_count_free(vm_map_zone),
1526 zone_count_free(vm_map_entry_zone),
1527 zone_count_free(vm_map_holes_zone));
1528}
1529STARTUP(ZALLOC, STARTUP_RANK_SECOND, vm_kernel_boostraped);
1530
1531void
1532vm_map_disable_hole_optimization(vm_map_t map)
1533{
1534 vm_map_entry_t head_entry, hole_entry, next_hole_entry;
1535
1536 if (map->holelistenabled) {
1537 head_entry = hole_entry = CAST_TO_VM_MAP_ENTRY(map->holes_list);
1538
1539 while (hole_entry != NULL) {
1540 next_hole_entry = hole_entry->vme_next;
1541
1542 hole_entry->vme_next = NULL;
1543 VME_PREV_SET(hole_entry, NULL);
1544 zfree_id(ZONE_ID_VM_MAP_HOLES, hole_entry);
1545
1546 if (next_hole_entry == head_entry) {
1547 hole_entry = NULL;
1548 } else {
1549 hole_entry = next_hole_entry;
1550 }
1551 }
1552
1553 map->holes_list = NULL;
1554 map->holelistenabled = FALSE;
1555
1556 map->first_free = vm_map_to_entry(map);
1557 SAVE_HINT_HOLE_WRITE(map, NULL);
1558 }
1559}
1560
1561boolean_t
1562vm_kernel_map_is_kernel(vm_map_t map)
1563{
1564 return map->pmap == kernel_pmap;
1565}
1566
1567/*
1568 * vm_map_create:
1569 *
1570 * Creates and returns a new empty VM map with
1571 * the given physical map structure, and having
1572 * the given lower and upper address bounds.
1573 */
1574
1575extern vm_map_t vm_map_create_external(
1576 pmap_t pmap,
1577 vm_map_offset_t min_off,
1578 vm_map_offset_t max_off,
1579 boolean_t pageable);
1580
1581vm_map_t
1582vm_map_create_external(
1583 pmap_t pmap,
1584 vm_map_offset_t min,
1585 vm_map_offset_t max,
1586 boolean_t pageable)
1587{
1588 vm_map_create_options_t options = VM_MAP_CREATE_DEFAULT;
1589
1590 if (pageable) {
1591 options |= VM_MAP_CREATE_PAGEABLE;
1592 }
1593 return vm_map_create_options(pmap, min, max, options);
1594}
1595
1596__startup_func
1597void
1598vm_map_will_allocate_early_map(vm_map_t *owner)
1599{
1600 if (early_map_count >= VM_MAP_EARLY_COUNT_MAX) {
1601 panic("VM_MAP_EARLY_COUNT_MAX is too low");
1602 }
1603
1604 early_map_owners[early_map_count++] = owner;
1605}
1606
1607__startup_func
1608void
1609vm_map_relocate_early_maps(vm_offset_t delta)
1610{
1611 for (uint32_t i = 0; i < early_map_count; i++) {
1612 vm_address_t addr = (vm_address_t)*early_map_owners[i];
1613
1614 *early_map_owners[i] = (vm_map_t)(addr + delta);
1615 }
1616
1617 early_map_count = ~0u;
1618}
1619
1620/*
1621 * Routine: vm_map_relocate_early_elem
1622 *
1623 * Purpose:
1624 * Early zone elements are allocated in a temporary part
1625 * of the address space.
1626 *
1627 * Once the zones live in their final place, the early
1628 * VM maps, map entries and map holes need to be relocated.
1629 *
1630 * It involves rewriting any vm_map_t, vm_map_entry_t or
1631 * pointers to vm_map_links. Other pointers to other types
1632 * are fine.
1633 *
1634 * Fortunately, pointers to those types are self-contained
1635 * in those zones, _except_ for pointers to VM maps,
1636 * which are tracked during early boot and fixed with
1637 * vm_map_relocate_early_maps().
1638 */
1639__startup_func
1640void
1641vm_map_relocate_early_elem(
1642 uint32_t zone_id,
1643 vm_offset_t new_addr,
1644 vm_offset_t delta)
1645{
1646#define relocate(type_t, field) ({ \
1647 typeof(((type_t)NULL)->field) *__field = &((type_t)new_addr)->field; \
1648 if (*__field) { \
1649 *__field = (typeof(*__field))((vm_offset_t)*__field + delta); \
1650 } \
1651})
1652
1653 switch (zone_id) {
1654 case ZONE_ID_VM_MAP:
1655 case ZONE_ID_VM_MAP_ENTRY:
1656 case ZONE_ID_VM_MAP_HOLES:
1657 break;
1658
1659 default:
1660 panic("Unexpected zone ID %d", zone_id);
1661 }
1662
1663 if (zone_id == ZONE_ID_VM_MAP) {
1664 struct vm_map_header * hdr_ptr = &((vm_map_t)new_addr)->hdr;
1665 if (VMH_PREV(hdr_ptr)) {
1666 VMH_PREV_SET(hdr_ptr, (vm_map_entry_t)(((vm_offset_t) VMH_PREV(hdr_ptr)) + delta));
1667 }
1668 relocate(vm_map_t, hdr.links.next);
1669 ((vm_map_t)new_addr)->pmap = kernel_pmap;
1670#ifdef VM_MAP_STORE_USE_RB
1671 relocate(vm_map_t, hdr.rb_head_store.rbh_root);
1672#endif /* VM_MAP_STORE_USE_RB */
1673 relocate(vm_map_t, hint);
1674 relocate(vm_map_t, hole_hint);
1675 relocate(vm_map_t, first_free);
1676 return;
1677 }
1678
1679 struct vm_map_links * links_ptr = ((struct vm_map_links *)new_addr);
1680 if (VML_PREV(links_ptr)) {
1681 VML_PREV_SET(links_ptr, (vm_map_entry_t) (((vm_offset_t) VML_PREV(links_ptr)) + delta));
1682 }
1683 relocate(struct vm_map_links *, next);
1684
1685 if (zone_id == ZONE_ID_VM_MAP_ENTRY) {
1686#ifdef VM_MAP_STORE_USE_RB
1687 relocate(vm_map_entry_t, store.entry.rbe_left);
1688 relocate(vm_map_entry_t, store.entry.rbe_right);
1689 relocate(vm_map_entry_t, store.entry.rbe_parent);
1690#endif /* VM_MAP_STORE_USE_RB */
1691 if (((vm_map_entry_t)new_addr)->is_sub_map) {
1692 /* no object to relocate because we haven't made any */
1693 ((vm_map_entry_t)new_addr)->vme_submap +=
1694 delta >> VME_SUBMAP_SHIFT;
1695 }
1696#if MAP_ENTRY_CREATION_DEBUG
1697 relocate(vm_map_entry_t, vme_creation_maphdr);
1698#endif /* MAP_ENTRY_CREATION_DEBUG */
1699 }
1700
1701#undef relocate
1702}
1703
1704/*
1705 * Generate a serial ID to identify a newly allocated vm_map
1706 */
1707static uintptr_t vm_map_serial_current = 0;
1708vm_map_serial_t vm_map_serial_generate(void);
1709void vm_map_assign_serial(vm_map_t, vm_map_serial_t);
1710
1711vm_map_serial_t
1712vm_map_serial_generate(void)
1713{
1714 vm_map_serial_t serial = (void *)os_atomic_inc(&vm_map_serial_current, relaxed);
1715 return serial;
1716}
1717
1718void
1719vm_map_assign_serial(vm_map_t map, vm_map_serial_t serial)
1720{
1721 map->serial_id = serial;
1722#if CONFIG_SPTM
1723 /* Copy through our ID to the pmap (only available on SPTM systems) */
1724 if (map->pmap) {
1725 map->pmap->associated_vm_map_serial_id = map->serial_id;
1726 }
1727#endif /* CONFIG_SPTM */
1728}
1729
1730vm_map_t
1731vm_map_create_options(
1732 pmap_t pmap,
1733 vm_map_offset_t min,
1734 vm_map_offset_t max,
1735 vm_map_create_options_t options)
1736{
1737 vm_map_t result;
1738
1739#if DEBUG || DEVELOPMENT
1740 if (__improbable(startup_phase < STARTUP_SUB_ZALLOC)) {
1741 if (early_map_count != ~0u && early_map_count !=
1742 zone_count_allocated(vm_map_zone) + 1) {
1743 panic("allocating %dth early map, owner not known",
1744 zone_count_allocated(vm_map_zone) + 1);
1745 }
1746 if (early_map_count != ~0u && pmap && pmap != kernel_pmap) {
1747 panic("allocating %dth early map for non kernel pmap",
1748 early_map_count);
1749 }
1750 }
1751#endif /* DEBUG || DEVELOPMENT */
1752
1753 result = zalloc_id(ZONE_ID_VM_MAP, Z_WAITOK | Z_NOFAIL | Z_ZERO);
1754
1755 vm_map_store_init(&result->hdr);
1756 result->hdr.entries_pageable = (bool)(options & VM_MAP_CREATE_PAGEABLE);
1757 vm_map_set_page_shift(result, PAGE_SHIFT);
1758
1759 result->size_limit = RLIM_INFINITY; /* default unlimited */
1760 result->data_limit = RLIM_INFINITY; /* default unlimited */
1761 result->user_wire_limit = MACH_VM_MAX_ADDRESS; /* default limit is unlimited */
1762 os_ref_init_count_raw(&result->map_refcnt, &map_refgrp, 1);
1763
1764 result->pmap = pmap;
1765
1766 /*
1767 * Immediately give ourselves an ID
1768 * Unless this map is being created as part of a fork, in which case
1769 * the caller will reassign the ID of the parent (so don't waste an
1770 * increment here).
1771 * Reusing parent IDs on fork enacts our policy that fork() pairs share
1772 * a domain and can freely alias tagged MTE mappings between themselves.
1773 */
1774 if ((options & VM_MAP_CREATE_VIA_FORK) == 0) {
1775 vm_map_assign_serial(result, vm_map_serial_generate());
1776 }
1777
1778 result->min_offset = min;
1779 result->max_offset = max;
1780 result->first_free = vm_map_to_entry(result);
1781 result->hint = vm_map_to_entry(result);
1782
1783 if (options & VM_MAP_CREATE_NEVER_FAULTS) {
1784 assert(pmap == kernel_pmap);
1785 result->never_faults = true;
1786 }
1787
1788 /* "has_corpse_footprint" and "holelistenabled" are mutually exclusive */
1789 if (options & VM_MAP_CREATE_CORPSE_FOOTPRINT) {
1790 result->has_corpse_footprint = true;
1791 } else if (!(options & VM_MAP_CREATE_DISABLE_HOLELIST)) {
1792 struct vm_map_links *hole_entry;
1793
1794 hole_entry = zalloc_id(ZONE_ID_VM_MAP_HOLES, Z_WAITOK | Z_NOFAIL);
1795 hole_entry->start = min;
1796 /*
1797 * Holes can be used to track ranges all the way up to
1798 * MACH_VM_MAX_ADDRESS or more (e.g. kernel map).
1799 */
1800 hole_entry->end = MAX(max, (vm_map_offset_t)MACH_VM_MAX_ADDRESS);
1801 result->holes_list = result->hole_hint = hole_entry;
1802 VML_PREV_SET(hole_entry, CAST_TO_VM_MAP_ENTRY(hole_entry));
1803 hole_entry->next = CAST_TO_VM_MAP_ENTRY(hole_entry);
1804 result->holelistenabled = true;
1805 }
1806
1807 vm_map_lock_init(result);
1808
1809 return result;
1810}
1811
1812/*
1813 * Adjusts a submap that was made by kmem_suballoc()
1814 * before it knew where it would be mapped,
1815 * so that it has the right min/max offsets.
1816 *
1817 * We do not need to hold any locks:
1818 * only the caller knows about this map,
1819 * and it is not published on any entry yet.
1820 */
1821static void
1822vm_map_adjust_offsets(
1823 vm_map_t map,
1824 vm_map_offset_t min_off,
1825 vm_map_offset_t max_off)
1826{
1827 assert(map->min_offset == 0);
1828 assert(map->max_offset == max_off - min_off);
1829 assert(map->hdr.nentries == 0);
1830 assert(os_ref_get_count_raw(&map->map_refcnt) == 2);
1831
1832 map->min_offset = min_off;
1833 map->max_offset = max_off;
1834
1835 if (map->holelistenabled) {
1836 struct vm_map_links *hole = map->holes_list;
1837
1838 hole->start = min_off;
1839#if defined(__arm64__)
1840 hole->end = max_off;
1841#else
1842 hole->end = MAX(max_off, (vm_map_offset_t)MACH_VM_MAX_ADDRESS);
1843#endif
1844 }
1845}
1846
1847
1848vm_map_size_t
1849vm_map_adjusted_size(vm_map_t map)
1850{
1851 const struct vm_reserved_region *regions = NULL;
1852 size_t num_regions = 0;
1853 mach_vm_size_t reserved_size = 0, map_size = 0;
1854
1855 if (map == NULL || (map->size == 0)) {
1856 return 0;
1857 }
1858
1859 map_size = map->size;
1860
1861 if (map->reserved_regions == FALSE || !vm_map_is_exotic(map) || map->terminated) {
1862 /*
1863 * No special reserved regions or not an exotic map or the task
1864 * is terminating and these special regions might have already
1865 * been deallocated.
1866 */
1867 return map_size;
1868 }
1869
1870 num_regions = ml_get_vm_reserved_regions(vm_map_is_64bit(map), ®ions);
1871 assert((num_regions == 0) || (num_regions > 0 && regions != NULL));
1872
1873 while (num_regions) {
1874 reserved_size += regions[--num_regions].vmrr_size;
1875 }
1876
1877 /*
1878 * There are a few places where the map is being switched out due to
1879 * 'termination' without that bit being set (e.g. exec and corpse purging).
1880 * In those cases, we could have the map's regions being deallocated on
1881 * a core while some accounting process is trying to get the map's size.
1882 * So this assert can't be enabled till all those places are uniform in
1883 * their use of the 'map->terminated' bit.
1884 *
1885 * assert(map_size >= reserved_size);
1886 */
1887
1888 return (map_size >= reserved_size) ? (map_size - reserved_size) : map_size;
1889}
1890
1891/*
1892 * vm_map_entry_create: [ internal use only ]
1893 *
1894 * Allocates a VM map entry for insertion in the
1895 * given map (or map copy). No fields are filled.
1896 *
1897 * The VM entry will be zero initialized, except for:
1898 * - behavior set to VM_BEHAVIOR_DEFAULT
1899 * - inheritance set to VM_INHERIT_DEFAULT
1900 */
1901#define vm_map_entry_create(map) _vm_map_entry_create(&(map)->hdr)
1902
1903#define vm_map_copy_entry_create(copy) _vm_map_entry_create(&(copy)->cpy_hdr)
1904
1905static vm_map_entry_t
1906_vm_map_entry_create(
1907 struct vm_map_header *map_header __unused)
1908{
1909 vm_map_entry_t entry = NULL;
1910
1911 entry = zalloc_id(ZONE_ID_VM_MAP_ENTRY, Z_WAITOK | Z_ZERO);
1912
1913 /*
1914 * Help the compiler with what we know to be true,
1915 * so that the further bitfields inits have good codegen.
1916 *
1917 * See rdar://87041299
1918 */
1919 __builtin_assume(entry->vme_object_value == 0);
1920 __builtin_assume(*(uint64_t *)(&entry->vme_object_value + 1) == 0);
1921 __builtin_assume(*(uint64_t *)(&entry->vme_object_value + 2) == 0);
1922
1923 static_assert(VM_MAX_TAG_VALUE <= VME_ALIAS_MASK,
1924 "VME_ALIAS_MASK covers tags");
1925
1926 static_assert(VM_BEHAVIOR_DEFAULT == 0,
1927 "can skip zeroing of the behavior field");
1928 entry->inheritance = VM_INHERIT_DEFAULT;
1929
1930#if MAP_ENTRY_CREATION_DEBUG
1931 entry->vme_creation_maphdr = map_header;
1932 entry->vme_creation_bt = btref_get(__builtin_frame_address(0),
1933 BTREF_GET_NOWAIT);
1934#endif
1935 return entry;
1936}
1937
1938/*
1939 * vm_map_entry_dispose: [ internal use only ]
1940 *
1941 * Inverse of vm_map_entry_create.
1942 *
1943 * write map lock held so no need to
1944 * do anything special to insure correctness
1945 * of the stores
1946 */
1947static void
1948vm_map_entry_dispose(
1949 vm_map_entry_t entry)
1950{
1951#if VM_BTLOG_TAGS
1952 if (entry->vme_kernel_object) {
1953 btref_put(entry->vme_tag_btref);
1954 }
1955#endif /* VM_BTLOG_TAGS */
1956#if MAP_ENTRY_CREATION_DEBUG
1957 btref_put(entry->vme_creation_bt);
1958#endif
1959#if MAP_ENTRY_INSERTION_DEBUG
1960 btref_put(entry->vme_insertion_bt);
1961#endif
1962 zfree(vm_map_entry_zone, entry);
1963}
1964
1965#define vm_map_copy_entry_dispose(copy_entry) \
1966 vm_map_entry_dispose(copy_entry)
1967
1968static vm_map_entry_t
1969vm_map_zap_first_entry(
1970 vm_map_zap_t list)
1971{
1972 return list->vmz_head;
1973}
1974
1975static vm_map_entry_t
1976vm_map_zap_last_entry(
1977 vm_map_zap_t list)
1978{
1979 assert(vm_map_zap_first_entry(list));
1980 return __container_of(list->vmz_tail, struct vm_map_entry, vme_next);
1981}
1982
1983static void
1984vm_map_zap_append(
1985 vm_map_zap_t list,
1986 vm_map_entry_t entry)
1987{
1988 entry->vme_next = VM_MAP_ENTRY_NULL;
1989 *list->vmz_tail = entry;
1990 list->vmz_tail = &entry->vme_next;
1991}
1992
1993static vm_map_entry_t
1994vm_map_zap_pop(
1995 vm_map_zap_t list)
1996{
1997 vm_map_entry_t head = list->vmz_head;
1998
1999 if (head != VM_MAP_ENTRY_NULL &&
2000 (list->vmz_head = head->vme_next) == VM_MAP_ENTRY_NULL) {
2001 list->vmz_tail = &list->vmz_head;
2002 }
2003
2004 return head;
2005}
2006
2007static void
2008vm_map_zap_dispose(
2009 vm_map_zap_t list)
2010{
2011 vm_map_entry_t entry;
2012
2013 while ((entry = vm_map_zap_pop(list))) {
2014 if (entry->is_sub_map) {
2015 vm_map_deallocate(VME_SUBMAP(entry));
2016 } else {
2017 vm_object_deallocate(VME_OBJECT(entry));
2018 }
2019
2020 vm_map_entry_dispose(entry);
2021 }
2022}
2023
2024#if MACH_ASSERT
2025static boolean_t first_free_check = FALSE;
2026boolean_t
2027first_free_is_valid(
2028 vm_map_t map)
2029{
2030 if (!first_free_check) {
2031 return TRUE;
2032 }
2033
2034 return first_free_is_valid_store( map );
2035}
2036#endif /* MACH_ASSERT */
2037
2038
2039#define vm_map_copy_entry_link(copy, after_where, entry) \
2040 _vm_map_store_entry_link(&(copy)->cpy_hdr, after_where, (entry))
2041
2042#define vm_map_copy_entry_unlink(copy, entry) \
2043 _vm_map_store_entry_unlink(&(copy)->cpy_hdr, (entry), false)
2044
2045/*
2046 * vm_map_destroy:
2047 *
2048 * Actually destroy a map.
2049 */
2050void
2051vm_map_destroy(
2052 vm_map_t map)
2053{
2054 /* final cleanup: this is not allowed to fail */
2055 vmr_flags_t flags = VM_MAP_REMOVE_NO_FLAGS;
2056
2057 VM_MAP_ZAP_DECLARE(zap);
2058
2059 vmlp_api_start(VM_MAP_DESTROY);
2060 vmlp_range_event_all(map);
2061
2062 if (vm_map_is_sealed(map)) {
2063 vm_map_lock_unseal(map);
2064 assert(!vm_map_is_sealed(map));
2065 } else {
2066 vm_map_lock(map);
2067 }
2068
2069 map->terminated = true;
2070 /* clean up regular map entries */
2071 (void)vm_map_delete(map, map->min_offset, map->max_offset, flags,
2072 KMEM_GUARD_NONE, &zap);
2073 /* clean up leftover special mappings (commpage, GPU carveout, etc...) */
2074 (void)vm_map_delete(map, 0x0, 0xFFFFFFFFFFFFF000ULL, flags,
2075 KMEM_GUARD_NONE, &zap);
2076
2077 vm_map_disable_hole_optimization(map);
2078 vm_map_corpse_footprint_destroy(map);
2079
2080 vm_map_unlock(map);
2081
2082 vm_map_zap_dispose(&zap);
2083
2084 assert(map->hdr.nentries == 0);
2085
2086 if (map->pmap) {
2087 pmap_destroy(map->pmap);
2088 }
2089
2090 lck_rw_destroy(&map->lock, &vm_map_lck_grp);
2091
2092#if CONFIG_MAP_RANGES
2093 kfree_data(map->extra_ranges,
2094 map->extra_ranges_count * sizeof(struct vm_map_user_range));
2095#endif
2096
2097 zfree_id(ZONE_ID_VM_MAP, map);
2098 vmlp_api_end(VM_MAP_DESTROY, 0);
2099}
2100
2101/*
2102 * Returns pid of the task with the largest number of VM map entries.
2103 * Used in the zone-map-exhaustion jetsam path.
2104 */
2105pid_t
2106find_largest_process_vm_map_entries(void)
2107{
2108 pid_t victim_pid = -1;
2109 int max_vm_map_entries = 0;
2110 task_t task = TASK_NULL;
2111 queue_head_t *task_list = &tasks;
2112
2113 lck_mtx_lock(&tasks_threads_lock);
2114 queue_iterate(task_list, task, task_t, tasks) {
2115 if (task == kernel_task || !task->active) {
2116 continue;
2117 }
2118
2119 vm_map_t task_map = task->map;
2120 if (task_map != VM_MAP_NULL) {
2121 int task_vm_map_entries = task_map->hdr.nentries;
2122 if (task_vm_map_entries > max_vm_map_entries) {
2123 max_vm_map_entries = task_vm_map_entries;
2124 victim_pid = pid_from_task(task);
2125 }
2126 }
2127 }
2128 lck_mtx_unlock(&tasks_threads_lock);
2129
2130 printf("zone_map_exhaustion: victim pid %d, vm region count: %d\n", victim_pid, max_vm_map_entries);
2131 return victim_pid;
2132}
2133
2134
2135/*
2136 * vm_map_lookup_entry: [ internal use only ]
2137 *
2138 * Calls into the vm map store layer to find the map
2139 * entry containing (or immediately preceding) the
2140 * specified address in the given map; the entry is returned
2141 * in the "entry" parameter. The boolean
2142 * result indicates whether the address is
2143 * actually contained in the map.
2144 */
2145boolean_t
2146vm_map_lookup_entry(
2147 vm_map_t map,
2148 vm_map_offset_t address,
2149 vm_map_entry_t *entry) /* OUT */
2150{
2151 bool result = false;
2152
2153#if KASAN_TBI
2154 if (VM_KERNEL_ADDRESS(address)) {
2155 address = vm_memtag_canonicalize_kernel(address);
2156 }
2157#endif /* KASAN_TBI */
2158
2159 result = vm_map_store_lookup_entry( map, address, entry );
2160
2161 return result;
2162}
2163
2164boolean_t
2165vm_map_lookup_entry_or_next(
2166 vm_map_t map,
2167 vm_map_offset_t address,
2168 vm_map_entry_t *entry) /* OUT */
2169{
2170 if (vm_map_lookup_entry(map, address, entry)) {
2171 return true;
2172 }
2173
2174 *entry = (*entry)->vme_next;
2175 return false;
2176}
2177
2178/*
2179 * Routine: vm_map_range_invalid_panic
2180 * Purpose:
2181 * Panic on detection of an invalid range id.
2182 */
2183__abortlike
2184static void
2185vm_map_range_invalid_panic(
2186 vm_map_t map,
2187 vm_map_range_id_t range_id)
2188{
2189 panic("invalid range ID (%u) for map %p", range_id, map);
2190}
2191
2192/*
2193 * Routine: vm_map_get_range
2194 * Purpose:
2195 * Adjust bounds based on security policy.
2196 */
2197static struct mach_vm_range
2198vm_map_get_range(
2199 vm_map_t map,
2200 vm_map_address_t *address,
2201 vm_map_kernel_flags_t *vmk_flags,
2202 vm_map_size_t size,
2203 bool *is_ptr)
2204{
2205 struct mach_vm_range effective_range = {};
2206 vm_map_range_id_t range_id = vmk_flags->vmkf_range_id;
2207
2208 if (map == kernel_map) {
2209 effective_range = kmem_ranges[range_id];
2210
2211 if (startup_phase >= STARTUP_SUB_KMEM) {
2212 /*
2213 * Hint provided by caller is zeroed as the range is restricted to a
2214 * subset of the entire kernel_map VA, which could put the hint outside
2215 * the range, causing vm_map_store_find_space to fail.
2216 */
2217 *address = 0ull;
2218 /*
2219 * Ensure that range_id passed in by the caller is within meaningful
2220 * bounds. Range id of KMEM_RANGE_ID_NONE will cause vm_map_locate_space
2221 * to fail as the corresponding range is invalid. Range id larger than
2222 * KMEM_RANGE_ID_MAX will lead to an OOB access.
2223 */
2224 if ((range_id == KMEM_RANGE_ID_NONE) ||
2225 (range_id > KMEM_RANGE_ID_MAX)) {
2226 vm_map_range_invalid_panic(map, range_id);
2227 }
2228
2229 /*
2230 * Pointer ranges use kmem_locate_space to do allocations.
2231 *
2232 * Non pointer fronts look like [ Small | Large | Permanent ]
2233 * Adjust range for allocations larger than KMEM_SMALLMAP_THRESHOLD.
2234 * Allocations smaller than KMEM_SMALLMAP_THRESHOLD are allowed to
2235 * use the entire range.
2236 */
2237 if (range_id < KMEM_RANGE_ID_SPRAYQTN) {
2238 *is_ptr = true;
2239 } else if (size >= KMEM_SMALLMAP_THRESHOLD) {
2240 effective_range = kmem_large_ranges[range_id];
2241 }
2242 }
2243#if CONFIG_MAP_RANGES
2244 } else if (map->uses_user_ranges) {
2245 switch (range_id) {
2246 case UMEM_RANGE_ID_DEFAULT:
2247 effective_range = map->default_range;
2248 break;
2249 case UMEM_RANGE_ID_HEAP:
2250 effective_range = map->data_range;
2251 break;
2252 case UMEM_RANGE_ID_LARGE_FILE:
2253 if (map->large_file_range.min_address != map->large_file_range.max_address) {
2254 /* large file range is configured and should be used */
2255 effective_range = map->large_file_range;
2256 } else {
2257 /*
2258 * the user asking for this user range might not have the
2259 * permissions to use the large file range (i.e., it doesn't
2260 * hold the correct entitlement), so we give it the data range
2261 * instead
2262 */
2263 effective_range = map->data_range;
2264 }
2265 break;
2266 case UMEM_RANGE_ID_FIXED:
2267 /*
2268 * anywhere allocations with an address in "FIXED"
2269 * makes no sense, leave the range empty
2270 */
2271 break;
2272
2273 default:
2274 vm_map_range_invalid_panic(map, range_id);
2275 }
2276#endif /* CONFIG_MAP_RANGES */
2277 } else {
2278 /*
2279 * If minimum is 0, bump it up by PAGE_SIZE. We want to limit
2280 * allocations of PAGEZERO to explicit requests since its
2281 * normal use is to catch dereferences of NULL and many
2282 * applications also treat pointers with a value of 0 as
2283 * special and suddenly having address 0 contain useable
2284 * memory would tend to confuse those applications.
2285 */
2286 effective_range.min_address = MAX(map->min_offset, VM_MAP_PAGE_SIZE(map));
2287 effective_range.max_address = map->max_offset;
2288 }
2289
2290 return effective_range;
2291}
2292
2293kern_return_t
2294vm_map_locate_space_anywhere(
2295 vm_map_t map,
2296 vm_map_size_t size,
2297 vm_map_offset_t mask,
2298 vm_map_kernel_flags_t vmk_flags,
2299 vm_map_offset_t *start_inout,
2300 vm_map_entry_t *entry_out)
2301{
2302 struct mach_vm_range effective_range = {};
2303 vm_map_size_t guard_offset;
2304 vm_map_offset_t hint, limit;
2305 vm_map_entry_t entry;
2306 bool is_kmem_ptr_range = false;
2307
2308 /*
2309 * Only supported by vm_map_enter() with a fixed address.
2310 */
2311 assert(!vmk_flags.vmf_fixed);
2312 assert(!vmk_flags.vmkf_beyond_max);
2313
2314 if (__improbable(map->wait_for_space)) {
2315 /*
2316 * support for "wait_for_space" is minimal,
2317 * its only consumer is the ipc_kernel_copy_map.
2318 */
2319 assert(!map->holelistenabled &&
2320 !vmk_flags.vmkf_last_free &&
2321 !vmk_flags.vmkf_keep_map_locked &&
2322 !vmk_flags.vmkf_map_jit &&
2323 !vmk_flags.vmf_random_addr &&
2324 *start_inout <= map->min_offset);
2325 } else if (vmk_flags.vmkf_last_free) {
2326 assert(!vmk_flags.vmkf_map_jit &&
2327 !vmk_flags.vmf_random_addr);
2328 }
2329
2330 if (vmk_flags.vmkf_guard_before) {
2331 guard_offset = VM_MAP_PAGE_SIZE(map);
2332 assert(size > guard_offset);
2333 size -= guard_offset;
2334 } else {
2335 assert(size != 0);
2336 guard_offset = 0;
2337 }
2338
2339 if (__improbable(!vm_map_is_map_size_valid(
2340 map, size, vmk_flags.vmkf_no_soft_limit))) {
2341 return KERN_NO_SPACE;
2342 }
2343
2344 /*
2345 * Validate range_id from flags and get associated range
2346 */
2347 effective_range = vm_map_get_range(map, start_inout, &vmk_flags, size,
2348 &is_kmem_ptr_range);
2349
2350 if (is_kmem_ptr_range) {
2351 return kmem_locate_space(size + guard_offset, vmk_flags.vmkf_range_id,
2352 vmk_flags.vmkf_last_free, start_inout, entry_out);
2353 }
2354
2355#if XNU_TARGET_OS_OSX
2356 if (__improbable(vmk_flags.vmkf_32bit_map_va)) {
2357 assert(map != kernel_map);
2358 effective_range.max_address = MIN(map->max_offset, 0x00000000FFFFF000ULL);
2359 }
2360#endif /* XNU_TARGET_OS_OSX */
2361
2362again:
2363 if (vmk_flags.vmkf_last_free) {
2364 hint = *start_inout;
2365
2366 if (hint == 0 || hint > effective_range.max_address) {
2367 hint = effective_range.max_address;
2368 }
2369 if (hint <= effective_range.min_address) {
2370 return KERN_NO_SPACE;
2371 }
2372 limit = effective_range.min_address;
2373 } else {
2374 hint = *start_inout;
2375
2376 if (vmk_flags.vmkf_map_jit) {
2377 if (map->jit_entry_exists &&
2378 !VM_MAP_POLICY_ALLOW_MULTIPLE_JIT(map)) {
2379 return KERN_INVALID_ARGUMENT;
2380 }
2381 if (VM_MAP_POLICY_ALLOW_JIT_RANDOM_ADDRESS(map)) {
2382 vmk_flags.vmf_random_addr = true;
2383 }
2384 }
2385
2386 if (vmk_flags.vmf_random_addr) {
2387 kern_return_t kr;
2388
2389 kr = vm_map_random_address_for_size(map, &hint, size, vmk_flags);
2390 if (kr != KERN_SUCCESS) {
2391 return kr;
2392 }
2393 }
2394#if __x86_64__
2395 else if ((hint == 0 || hint == vm_map_min(map)) &&
2396 !map->disable_vmentry_reuse &&
2397 map->vmmap_high_start != 0) {
2398 hint = map->vmmap_high_start;
2399 }
2400#endif /* __x86_64__ */
2401
2402 if (hint < effective_range.min_address) {
2403 hint = effective_range.min_address;
2404 }
2405 if (effective_range.max_address <= hint) {
2406 return KERN_NO_SPACE;
2407 }
2408
2409 limit = effective_range.max_address;
2410 }
2411 entry = vm_map_store_find_space(map,
2412 hint, limit, vmk_flags.vmkf_last_free,
2413 guard_offset, size, mask,
2414 start_inout);
2415
2416 if (__improbable(entry == NULL)) {
2417 if (map->wait_for_space &&
2418 guard_offset + size <=
2419 effective_range.max_address - effective_range.min_address) {
2420 assert_wait((event_t)map, THREAD_ABORTSAFE);
2421 vm_map_unlock(map);
2422 thread_block(THREAD_CONTINUE_NULL);
2423 vm_map_lock(map);
2424 goto again;
2425 }
2426 return KERN_NO_SPACE;
2427 }
2428
2429 if (entry_out) {
2430 *entry_out = entry;
2431 }
2432 return KERN_SUCCESS;
2433}
2434
2435/*!
2436 * @function vm_map_locate_space_fixed()
2437 *
2438 * @brief
2439 * Locate (no reservation) a range in the specified VM map at a fixed address.
2440 *
2441 * @param map the map to scan for memory, must be locked.
2442 * @param start the fixed address trying to be reserved
2443 * @param size the size of the allocation to make.
2444 * @param mask an alignment mask the allocation must respect,
2445 * @param vmk_flags the vm map kernel flags to influence this call.
2446 * vmk_flags.vmf_anywhere must not be set.
2447 * @param entry_out the entry right before the hole.
2448 * @param zap_list a zap list of entries to clean up after the call.
2449 *
2450 * @returns
2451 * - KERN_SUCCESS in case of success and no conflicting entry is found,
2452 * in which case entry_out is set to the entry before the hole.
2453 *
2454 * - KERN_MEMORY_PRESENT if a conflicting entry is found,
2455 * in which case entry_out is set the conflicting entry,
2456 * the callers MUST handle this error explicitly.
2457 *
2458 * - KERN_INVALID_ADDRESS if the specified @c start or @c size
2459 * would result in a mapping outside of the map.
2460 *
2461 * - KERN_NO_SPACE for various cases of unrecoverable failures.
2462 */
2463static kern_return_t
2464vm_map_locate_space_fixed(
2465 vm_map_t map,
2466 vm_map_offset_t start,
2467 vm_map_size_t size,
2468 vm_map_offset_t mask,
2469 vm_map_kernel_flags_t vmk_flags,
2470 vm_map_entry_t *entry_out,
2471 vm_map_zap_t zap_list)
2472{
2473 vm_map_offset_t effective_min_offset, effective_max_offset;
2474 vm_map_entry_t entry;
2475 vm_map_offset_t end;
2476
2477 assert(vmk_flags.vmf_fixed);
2478
2479 effective_min_offset = map->min_offset;
2480 effective_max_offset = map->max_offset;
2481
2482 if (vmk_flags.vmkf_beyond_max) {
2483 /*
2484 * Allow an insertion beyond the map's max offset.
2485 */
2486 effective_max_offset = 0x00000000FFFFF000ULL;
2487 if (vm_map_is_64bit(map)) {
2488 effective_max_offset = 0xFFFFFFFFFFFFF000ULL;
2489 }
2490#if XNU_TARGET_OS_OSX
2491 } else if (__improbable(vmk_flags.vmkf_32bit_map_va)) {
2492 effective_max_offset = MIN(map->max_offset, 0x00000000FFFFF000ULL);
2493#endif /* XNU_TARGET_OS_OSX */
2494 }
2495
2496 if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT &&
2497 !vmk_flags.vmf_overwrite &&
2498 map->pmap == kernel_pmap &&
2499 vmk_flags.vm_tag == VM_MEMORY_REALLOC) {
2500 /*
2501 * Force realloc() to switch to a new allocation,
2502 * to prevent 4k-fragmented virtual ranges.
2503 */
2504// DEBUG4K_ERROR("no realloc in place");
2505 return KERN_NO_SPACE;
2506 }
2507
2508 /*
2509 * Verify that:
2510 * the address doesn't itself violate
2511 * the mask requirement.
2512 */
2513
2514 if ((start & mask) != 0) {
2515 return KERN_NO_SPACE;
2516 }
2517
2518 if (__improbable(!vm_map_is_map_size_valid(
2519 map, size, vmk_flags.vmkf_no_soft_limit))) {
2520 return KERN_NO_SPACE;
2521 }
2522
2523#if CONFIG_MAP_RANGES
2524 if (map->uses_user_ranges) {
2525 struct mach_vm_range r;
2526
2527 vm_map_user_range_resolve(map, start, 1, &r);
2528 if (r.max_address == 0) {
2529 return KERN_INVALID_ADDRESS;
2530 }
2531 effective_min_offset = r.min_address;
2532 effective_max_offset = r.max_address;
2533 }
2534#endif /* CONFIG_MAP_RANGES */
2535
2536 if ((startup_phase >= STARTUP_SUB_KMEM) && !vmk_flags.vmkf_submap &&
2537 (map == kernel_map)) {
2538 mach_vm_range_t r = kmem_validate_range_for_overwrite(start, size);
2539 effective_min_offset = r->min_address;
2540 effective_max_offset = r->max_address;
2541 }
2542
2543 /*
2544 * ... the address is within bounds
2545 */
2546
2547 end = start + size;
2548
2549 if ((start < effective_min_offset) ||
2550 (end > effective_max_offset) ||
2551 (start >= end)) {
2552 return KERN_INVALID_ADDRESS;
2553 }
2554
2555 if (vmk_flags.vmf_overwrite) {
2556 vmr_flags_t remove_flags = VM_MAP_REMOVE_TO_OVERWRITE;
2557 kern_return_t remove_kr;
2558
2559 /*
2560 * Fixed mapping and "overwrite" flag: attempt to
2561 * remove all existing mappings in the specified
2562 * address range, saving them in our "zap_list".
2563 *
2564 * This avoids releasing the VM map lock in
2565 * vm_map_entry_delete() and allows atomicity
2566 * when we want to replace some mappings with a new one.
2567 * It also allows us to restore the old VM mappings if the
2568 * new mapping fails.
2569 */
2570 remove_flags |= VM_MAP_REMOVE_NO_YIELD;
2571
2572 if (vmk_flags.vmkf_overwrite_immutable) {
2573 /* we can overwrite immutable mappings */
2574 remove_flags |= VM_MAP_REMOVE_IMMUTABLE;
2575 }
2576 if (vmk_flags.vmkf_remap_prot_copy) {
2577 remove_flags |= VM_MAP_REMOVE_IMMUTABLE_CODE;
2578 }
2579 remove_kr = vm_map_delete(map, start, end, remove_flags,
2580 KMEM_GUARD_NONE, zap_list).kmr_return;
2581 if (remove_kr) {
2582 /* XXX FBDP restore zap_list? */
2583 return remove_kr;
2584 }
2585 }
2586
2587 /*
2588 * ... the starting address isn't allocated
2589 */
2590
2591 if (vm_map_lookup_entry(map, start, &entry)) {
2592 *entry_out = entry;
2593 return KERN_MEMORY_PRESENT;
2594 }
2595
2596 /*
2597 * ... the next region doesn't overlap the
2598 * end point.
2599 */
2600
2601 if ((entry->vme_next != vm_map_to_entry(map)) &&
2602 (entry->vme_next->vme_start < end)) {
2603 return KERN_NO_SPACE;
2604 }
2605
2606 *entry_out = entry;
2607 return KERN_SUCCESS;
2608}
2609
2610/*
2611 * Routine: vm_map_find_space
2612 * Purpose:
2613 * Allocate a range in the specified virtual address map,
2614 * returning the entry allocated for that range.
2615 * Used by kmem_alloc, etc.
2616 *
2617 * The map must be NOT be locked. It will be returned locked
2618 * on KERN_SUCCESS, unlocked on failure.
2619 *
2620 * If an entry is allocated, the object/offset fields
2621 * are initialized to zero.
2622 */
2623kern_return_t
2624vm_map_find_space(
2625 vm_map_t map,
2626 vm_map_offset_t hint_address,
2627 vm_map_size_t size,
2628 vm_map_offset_t mask,
2629 vm_map_kernel_flags_t vmk_flags,
2630 vm_map_entry_t *o_entry) /* OUT */
2631{
2632 vm_map_entry_t new_entry, entry;
2633 kern_return_t kr;
2634
2635 vmlp_api_start(VM_MAP_FIND_SPACE);
2636
2637 if (size == 0) {
2638 vmlp_api_end(VM_MAP_FIND_SPACE, KERN_INVALID_ARGUMENT);
2639 return KERN_INVALID_ARGUMENT;
2640 }
2641
2642 new_entry = vm_map_entry_create(map);
2643 new_entry->use_pmap = true;
2644 new_entry->protection = VM_PROT_DEFAULT;
2645 new_entry->max_protection = VM_PROT_ALL;
2646
2647 if (vmk_flags.vmf_permanent) {
2648 new_entry->vme_permanent = true;
2649 }
2650
2651 vm_map_lock(map);
2652
2653 kr = vm_map_locate_space_anywhere(map, size, mask, vmk_flags,
2654 &hint_address, &entry);
2655 if (kr != KERN_SUCCESS) {
2656 vm_map_unlock(map);
2657 vm_map_entry_dispose(new_entry);
2658 vmlp_api_end(VM_MAP_FIND_SPACE, kr);
2659 return kr;
2660 }
2661 new_entry->vme_start = hint_address;
2662 new_entry->vme_end = hint_address + size;
2663
2664 /*
2665 * At this point,
2666 *
2667 * - new_entry's "vme_start" and "vme_end" should define
2668 * the endpoints of the available new range,
2669 *
2670 * - and "entry" should refer to the region before
2671 * the new range,
2672 *
2673 * - and the map should still be locked.
2674 */
2675
2676 assert(page_aligned(new_entry->vme_start));
2677 assert(page_aligned(new_entry->vme_end));
2678 assert(VM_MAP_PAGE_ALIGNED(new_entry->vme_start, VM_MAP_PAGE_MASK(map)));
2679 assert(VM_MAP_PAGE_ALIGNED(new_entry->vme_end, VM_MAP_PAGE_MASK(map)));
2680
2681
2682 /*
2683 * Insert the new entry into the list
2684 */
2685
2686 vm_map_store_entry_link(map, entry, new_entry,
2687 VM_MAP_KERNEL_FLAGS_NONE);
2688 map->size += size;
2689 vmlp_range_event_entry(map, new_entry);
2690
2691 /*
2692 * Update the lookup hint
2693 */
2694 SAVE_HINT_MAP_WRITE(map, new_entry);
2695
2696 *o_entry = new_entry;
2697 vmlp_api_end(VM_MAP_FIND_SPACE, KERN_SUCCESS);
2698 return KERN_SUCCESS;
2699}
2700
2701int vm_map_pmap_enter_print = FALSE;
2702int vm_map_pmap_enter_enable = FALSE;
2703
2704/*
2705 * Routine: vm_map_pmap_enter [internal only]
2706 *
2707 * Description:
2708 * Force pages from the specified object to be entered into
2709 * the pmap at the specified address if they are present.
2710 * As soon as a page not found in the object the scan ends.
2711 *
2712 * Returns:
2713 * Nothing.
2714 *
2715 * In/out conditions:
2716 * The source map should not be locked on entry.
2717 */
2718__unused static void
2719vm_map_pmap_enter(
2720 vm_map_t map,
2721 vm_map_offset_t addr,
2722 vm_map_offset_t end_addr,
2723 vm_object_t object,
2724 vm_object_offset_t offset,
2725 vm_prot_t protection)
2726{
2727 int type_of_fault;
2728 kern_return_t kr;
2729 uint8_t object_lock_type = 0;
2730 struct vm_object_fault_info fault_info = {
2731 .interruptible = THREAD_UNINT,
2732 };
2733
2734 if (map->pmap == 0) {
2735 return;
2736 }
2737
2738 assert(VM_MAP_PAGE_SHIFT(map) == PAGE_SHIFT);
2739
2740 while (addr < end_addr) {
2741 vm_page_t m;
2742
2743
2744 /*
2745 * TODO:
2746 * From vm_map_enter(), we come into this function without the map
2747 * lock held or the object lock held.
2748 * We haven't taken a reference on the object either.
2749 * We should do a proper lookup on the map to make sure
2750 * that things are sane before we go locking objects that
2751 * could have been deallocated from under us.
2752 */
2753
2754 object_lock_type = OBJECT_LOCK_EXCLUSIVE;
2755 vm_object_lock(object);
2756
2757 m = vm_page_lookup(object, offset);
2758
2759 if (m == VM_PAGE_NULL || m->vmp_busy || vm_page_is_fictitious(m) ||
2760 (m->vmp_unusual && (VMP_ERROR_GET(m) || m->vmp_restart || m->vmp_absent))) {
2761 vm_object_unlock(object);
2762 return;
2763 }
2764
2765 if (vm_map_pmap_enter_print) {
2766 printf("vm_map_pmap_enter:");
2767 printf("map: %p, addr: %llx, object: %p, offset: %llx\n",
2768 map, (unsigned long long)addr, object, (unsigned long long)offset);
2769 }
2770 type_of_fault = DBG_CACHE_HIT_FAULT;
2771 bool page_sleep_needed = false;
2772 kr = vm_fault_enter(m, map->pmap,
2773 addr,
2774 PAGE_SIZE, 0,
2775 protection, protection,
2776 VM_PAGE_WIRED(m),
2777 VM_KERN_MEMORY_NONE, /* tag - not wiring */
2778 &fault_info,
2779 NULL, /* need_retry */
2780 &type_of_fault,
2781 &object_lock_type, /* Exclusive lock mode. Will remain unchanged.*/
2782 &page_sleep_needed);
2783
2784 vm_object_unlock(object);
2785 assert(!page_sleep_needed);
2786
2787 offset += PAGE_SIZE_64;
2788 addr += PAGE_SIZE;
2789 }
2790}
2791
2792#define MAX_TRIES_TO_GET_RANDOM_ADDRESS 1000
2793static kern_return_t
2794vm_map_random_address_for_size(
2795 vm_map_t map,
2796 vm_map_offset_t *address,
2797 vm_map_size_t size,
2798 vm_map_kernel_flags_t vmk_flags)
2799{
2800 kern_return_t kr = KERN_SUCCESS;
2801 int tries = 0;
2802 vm_map_offset_t random_addr = 0;
2803 vm_map_offset_t hole_end;
2804
2805 vm_map_entry_t next_entry = VM_MAP_ENTRY_NULL;
2806 vm_map_entry_t prev_entry = VM_MAP_ENTRY_NULL;
2807 vm_map_size_t vm_hole_size = 0;
2808 vm_map_size_t addr_space_size;
2809 bool is_kmem_ptr;
2810 struct mach_vm_range effective_range;
2811
2812 effective_range = vm_map_get_range(map, address, &vmk_flags, size,
2813 &is_kmem_ptr);
2814
2815 addr_space_size = effective_range.max_address - effective_range.min_address;
2816 if (size >= addr_space_size) {
2817 return KERN_NO_SPACE;
2818 }
2819 addr_space_size -= size;
2820
2821 assert(VM_MAP_PAGE_ALIGNED(size, VM_MAP_PAGE_MASK(map)));
2822
2823 while (tries < MAX_TRIES_TO_GET_RANDOM_ADDRESS) {
2824 if (startup_phase < STARTUP_SUB_ZALLOC) {
2825 random_addr = (vm_map_offset_t)early_random();
2826 } else {
2827 random_addr = (vm_map_offset_t)random();
2828 }
2829 random_addr <<= VM_MAP_PAGE_SHIFT(map);
2830 random_addr = vm_map_trunc_page(
2831 effective_range.min_address + (random_addr % addr_space_size),
2832 VM_MAP_PAGE_MASK(map));
2833
2834 if (vm_map_lookup_entry(map, random_addr, &prev_entry) == FALSE) {
2835 if (prev_entry == vm_map_to_entry(map)) {
2836 next_entry = vm_map_first_entry(map);
2837 } else {
2838 next_entry = prev_entry->vme_next;
2839 }
2840 if (next_entry == vm_map_to_entry(map)) {
2841 hole_end = vm_map_max(map);
2842 } else {
2843 hole_end = next_entry->vme_start;
2844 }
2845 vm_hole_size = hole_end - random_addr;
2846 if (vm_hole_size >= size) {
2847 *address = random_addr;
2848 break;
2849 }
2850 }
2851 tries++;
2852 }
2853
2854 if (tries == MAX_TRIES_TO_GET_RANDOM_ADDRESS) {
2855 kr = KERN_NO_SPACE;
2856 }
2857 return kr;
2858}
2859
2860static boolean_t
2861vm_memory_malloc_no_cow(
2862 int alias)
2863{
2864 uint64_t alias_mask;
2865
2866 if (!malloc_no_cow) {
2867 return FALSE;
2868 }
2869 if (alias > 63) {
2870 return FALSE;
2871 }
2872 alias_mask = 1ULL << alias;
2873 if (alias_mask & vm_memory_malloc_no_cow_mask) {
2874 return TRUE;
2875 }
2876 return FALSE;
2877}
2878
2879uint64_t vm_map_enter_RLIMIT_AS_count = 0;
2880uint64_t vm_map_enter_RLIMIT_DATA_count = 0;
2881/*
2882 * Routine: vm_map_enter
2883 *
2884 * Description:
2885 * Allocate a range in the specified virtual address map.
2886 * The resulting range will refer to memory defined by
2887 * the given memory object and offset into that object.
2888 *
2889 * Arguments are as defined in the vm_map call.
2890 */
2891static unsigned int vm_map_enter_restore_successes = 0;
2892static unsigned int vm_map_enter_restore_failures = 0;
2893kern_return_t
2894vm_map_enter(
2895 vm_map_t map,
2896 vm_map_offset_t *address, /* IN/OUT */
2897 vm_map_size_t size,
2898 vm_map_offset_t mask,
2899 vm_map_kernel_flags_t vmk_flags,
2900 vm_object_t object,
2901 vm_object_offset_t offset,
2902 boolean_t needs_copy,
2903 vm_prot_t cur_protection,
2904 vm_prot_t max_protection,
2905 vm_inherit_t inheritance)
2906{
2907 vm_map_entry_t entry, new_entry;
2908 vm_map_offset_t start, tmp_start, tmp_offset;
2909 vm_map_offset_t end, tmp_end;
2910 vm_map_offset_t tmp2_start, tmp2_end;
2911 vm_map_offset_t step;
2912 kern_return_t result = KERN_SUCCESS;
2913 bool map_locked = FALSE;
2914 bool pmap_empty = TRUE;
2915 bool new_mapping_established = FALSE;
2916 const bool keep_map_locked = vmk_flags.vmkf_keep_map_locked;
2917 const bool anywhere = !vmk_flags.vmf_fixed;
2918 const bool purgable = vmk_flags.vmf_purgeable;
2919 const bool no_cache = vmk_flags.vmf_no_cache;
2920 const bool is_submap = vmk_flags.vmkf_submap;
2921 const bool permanent = vmk_flags.vmf_permanent;
2922 const bool no_copy_on_read = vmk_flags.vmkf_no_copy_on_read;
2923 const bool entry_for_jit = vmk_flags.vmkf_map_jit;
2924 const bool iokit_acct = vmk_flags.vmkf_iokit_acct;
2925 const bool resilient_codesign = vmk_flags.vmf_resilient_codesign;
2926 const bool resilient_media = vmk_flags.vmf_resilient_media;
2927 const bool entry_for_tpro = vmk_flags.vmf_tpro;
2928 const unsigned int superpage_size = vmk_flags.vmf_superpage_size;
2929 const vm_tag_t alias = vmk_flags.vm_tag;
2930 vm_tag_t user_alias;
2931 kern_return_t kr;
2932 vm_map_size_t chunk_size = 0;
2933 vm_object_t caller_object;
2934 VM_MAP_ZAP_DECLARE(zap_old_list);
2935 VM_MAP_ZAP_DECLARE(zap_new_list);
2936
2937 vmlp_api_start(VM_MAP_ENTER);
2938
2939 caller_object = object;
2940
2941 assertf(vmk_flags.__vmkf_unused2 == 0, "vmk_flags unused2=0x%llx\n", vmk_flags.__vmkf_unused2);
2942
2943 if (vmk_flags.vmf_4gb_chunk) {
2944#if defined(__LP64__)
2945 chunk_size = (4ULL * 1024 * 1024 * 1024); /* max. 4GB chunks for the new allocation */
2946#else /* __LP64__ */
2947 chunk_size = ANON_CHUNK_SIZE;
2948#endif /* __LP64__ */
2949 } else {
2950 chunk_size = ANON_CHUNK_SIZE;
2951 }
2952
2953
2954
2955 if (superpage_size) {
2956 if (object != VM_OBJECT_NULL) {
2957 /* caller can't provide their own VM object */
2958 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
2959 return KERN_INVALID_ARGUMENT;
2960 }
2961 switch (superpage_size) {
2962 /*
2963 * Note that the current implementation only supports
2964 * a single size for superpages, SUPERPAGE_SIZE, per
2965 * architecture. As soon as more sizes are supposed
2966 * to be supported, SUPERPAGE_SIZE has to be replaced
2967 * with a lookup of the size depending on superpage_size.
2968 */
2969#ifdef __x86_64__
2970 case SUPERPAGE_SIZE_ANY:
2971 /* handle it like 2 MB and round up to page size */
2972 size = (size + 2 * 1024 * 1024 - 1) & ~(2 * 1024 * 1024 - 1);
2973 OS_FALLTHROUGH;
2974 case SUPERPAGE_SIZE_2MB:
2975 break;
2976#endif
2977 default:
2978 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
2979 return KERN_INVALID_ARGUMENT;
2980 }
2981 mask = SUPERPAGE_SIZE - 1;
2982 if (size & (SUPERPAGE_SIZE - 1)) {
2983 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
2984 return KERN_INVALID_ARGUMENT;
2985 }
2986 inheritance = VM_INHERIT_NONE; /* fork() children won't inherit superpages */
2987 }
2988
2989
2990 if ((cur_protection & VM_PROT_WRITE) &&
2991 (cur_protection & VM_PROT_EXECUTE) &&
2992#if XNU_TARGET_OS_OSX
2993 map->pmap != kernel_pmap &&
2994 (cs_process_global_enforcement() ||
2995 (vmk_flags.vmkf_cs_enforcement_override
2996 ? vmk_flags.vmkf_cs_enforcement
2997 : (vm_map_cs_enforcement(map)
2998#if __arm64__
2999 || !VM_MAP_IS_EXOTIC(map)
3000#endif /* __arm64__ */
3001 ))) &&
3002#endif /* XNU_TARGET_OS_OSX */
3003#if CODE_SIGNING_MONITOR
3004 (csm_address_space_exempt(map->pmap) != KERN_SUCCESS) &&
3005#endif
3006 (VM_MAP_POLICY_WX_FAIL(map) ||
3007 VM_MAP_POLICY_WX_STRIP_X(map)) &&
3008 !entry_for_jit) {
3009 boolean_t vm_protect_wx_fail = VM_MAP_POLICY_WX_FAIL(map);
3010
3011 DTRACE_VM3(cs_wx,
3012 uint64_t, 0,
3013 uint64_t, 0,
3014 vm_prot_t, cur_protection);
3015 printf("CODE SIGNING: %d[%s] %s: curprot cannot be write+execute. %s\n",
3016 proc_selfpid(),
3017 (get_bsdtask_info(current_task())
3018 ? proc_name_address(get_bsdtask_info(current_task()))
3019 : "?"),
3020 __FUNCTION__,
3021 (vm_protect_wx_fail ? "failing" : "turning off execute"));
3022 cur_protection &= ~VM_PROT_EXECUTE;
3023 if (vm_protect_wx_fail) {
3024 vmlp_api_end(VM_MAP_ENTER, KERN_PROTECTION_FAILURE);
3025 return KERN_PROTECTION_FAILURE;
3026 }
3027 }
3028
3029 if (entry_for_jit
3030 && cur_protection != VM_PROT_ALL) {
3031 /*
3032 * Native macOS processes and all non-macOS processes are
3033 * expected to create JIT regions via mmap(MAP_JIT, RWX) but
3034 * the RWX requirement was not enforced, and thus, we must live
3035 * with our sins. We are now dealing with a JIT mapping without
3036 * RWX.
3037 *
3038 * We deal with these by letting the MAP_JIT stick in order
3039 * to avoid CS violations when these pages are mapped executable
3040 * down the line. In order to appease the page table monitor (you
3041 * know what I'm talking about), these pages will end up being
3042 * marked as XNU_USER_DEBUG, which will be allowed because we
3043 * don't enforce the code signing monitor on macOS systems. If
3044 * the user-space application ever changes permissions to RWX,
3045 * which they are allowed to since the mapping was originally
3046 * created with MAP_JIT, then they'll switch over to using the
3047 * XNU_USER_JIT type, and won't be allowed to downgrade any
3048 * more after that.
3049 *
3050 * When not on macOS, a MAP_JIT mapping without VM_PROT_ALL is
3051 * strictly disallowed.
3052 */
3053
3054#if XNU_TARGET_OS_OSX
3055 /*
3056 * Continue to allow non-RWX JIT
3057 */
3058#else
3059 /* non-macOS: reject JIT regions without RWX */
3060 DTRACE_VM3(cs_wx,
3061 uint64_t, 0,
3062 uint64_t, 0,
3063 vm_prot_t, cur_protection);
3064 printf("CODE SIGNING: %d[%s] %s(%d): JIT requires RWX: failing. \n",
3065 proc_selfpid(),
3066 (get_bsdtask_info(current_task())
3067 ? proc_name_address(get_bsdtask_info(current_task()))
3068 : "?"),
3069 __FUNCTION__,
3070 cur_protection);
3071 vmlp_api_end(VM_MAP_ENTER, KERN_PROTECTION_FAILURE);
3072 return KERN_PROTECTION_FAILURE;
3073#endif
3074 }
3075
3076 /*
3077 * If the task has requested executable lockdown,
3078 * deny any new executable mapping.
3079 */
3080 if (map->map_disallow_new_exec == TRUE) {
3081 if (cur_protection & VM_PROT_EXECUTE) {
3082 vmlp_api_end(VM_MAP_ENTER, KERN_PROTECTION_FAILURE);
3083 return KERN_PROTECTION_FAILURE;
3084 }
3085 }
3086
3087 if (resilient_codesign) {
3088 assert(!is_submap);
3089 int reject_prot = (needs_copy ? VM_PROT_ALLEXEC : (VM_PROT_WRITE | VM_PROT_ALLEXEC));
3090 if ((cur_protection | max_protection) & reject_prot) {
3091 vmlp_api_end(VM_MAP_ENTER, KERN_PROTECTION_FAILURE);
3092 return KERN_PROTECTION_FAILURE;
3093 }
3094 }
3095
3096 if (resilient_media) {
3097 assert(!is_submap);
3098// assert(!needs_copy);
3099 if (object != VM_OBJECT_NULL &&
3100 !object->internal) {
3101 /*
3102 * This mapping is directly backed by an external
3103 * memory manager (e.g. a vnode pager for a file):
3104 * we would not have any safe place to inject
3105 * a zero-filled page if an actual page is not
3106 * available, without possibly impacting the actual
3107 * contents of the mapped object (e.g. the file),
3108 * so we can't provide any media resiliency here.
3109 */
3110 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3111 return KERN_INVALID_ARGUMENT;
3112 }
3113 }
3114
3115 if (entry_for_tpro) {
3116 /*
3117 * TPRO overrides the effective permissions of the region
3118 * and explicitly maps as RW. Ensure we have been passed
3119 * the expected permissions. We accept `cur_protections`
3120 * RO as that will be handled on fault.
3121 */
3122 if (!(max_protection & VM_PROT_READ) ||
3123 !(max_protection & VM_PROT_WRITE) ||
3124 !(cur_protection & VM_PROT_READ)) {
3125 vmlp_api_end(VM_MAP_ENTER, KERN_PROTECTION_FAILURE);
3126 return KERN_PROTECTION_FAILURE;
3127 }
3128
3129 /*
3130 * We can now downgrade the cur_protection to RO. This is a mild lie
3131 * to the VM layer. But TPRO will be responsible for toggling the
3132 * protections between RO/RW
3133 */
3134 cur_protection = VM_PROT_READ;
3135 }
3136
3137 if (is_submap) {
3138 vm_map_t submap;
3139 if (purgable) {
3140 /* submaps can not be purgeable */
3141 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3142 return KERN_INVALID_ARGUMENT;
3143 }
3144 if (object == VM_OBJECT_NULL) {
3145 /* submaps can not be created lazily */
3146 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3147 return KERN_INVALID_ARGUMENT;
3148 }
3149 submap = (vm_map_t) object;
3150 if (VM_MAP_PAGE_SHIFT(submap) != VM_MAP_PAGE_SHIFT(map)) {
3151 /* page size mismatch */
3152 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3153 return KERN_INVALID_ARGUMENT;
3154 }
3155 }
3156 if (vmk_flags.vmkf_already) {
3157 /*
3158 * VM_FLAGS_ALREADY says that it's OK if the same mapping
3159 * is already present. For it to be meaningul, the requested
3160 * mapping has to be at a fixed address (!VM_FLAGS_ANYWHERE) and
3161 * we shouldn't try and remove what was mapped there first
3162 * (!VM_FLAGS_OVERWRITE).
3163 */
3164 if (!vmk_flags.vmf_fixed || vmk_flags.vmf_overwrite) {
3165 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3166 return KERN_INVALID_ARGUMENT;
3167 }
3168 }
3169
3170 if (size == 0 ||
3171 (offset & MIN(VM_MAP_PAGE_MASK(map), PAGE_MASK_64)) != 0) {
3172 *address = 0;
3173 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3174 return KERN_INVALID_ARGUMENT;
3175 }
3176
3177 if (map->pmap == kernel_pmap) {
3178 user_alias = VM_KERN_MEMORY_NONE;
3179 } else {
3180 user_alias = alias;
3181 }
3182
3183 if (user_alias == VM_MEMORY_MALLOC_MEDIUM) {
3184 chunk_size = MALLOC_MEDIUM_CHUNK_SIZE;
3185 }
3186
3187#define RETURN(value) { result = value; goto BailOut; }
3188
3189 assertf(VM_MAP_PAGE_ALIGNED(*address, VM_MAP_PAGE_MASK(map)), "0x%llx", (uint64_t)*address);
3190 assertf(VM_MAP_PAGE_ALIGNED(size, VM_MAP_PAGE_MASK(map)), "0x%llx", (uint64_t)size);
3191
3192 /*
3193 * Only zero-fill objects are allowed to be purgable.
3194 * LP64todo - limit purgable objects to 32-bits for now
3195 */
3196 if (purgable &&
3197 (offset != 0 ||
3198 (object != VM_OBJECT_NULL &&
3199 (object->vo_size != size ||
3200 object->purgable == VM_PURGABLE_DENY))
3201#if __LP64__
3202 || size > ANON_MAX_SIZE
3203#endif
3204 )) {
3205 vmlp_api_end(VM_MAP_ENTER, KERN_INVALID_ARGUMENT);
3206 return KERN_INVALID_ARGUMENT;
3207 }
3208
3209 if (__improbable(!vm_map_is_map_size_valid(
3210 map, size, vmk_flags.vmkf_no_soft_limit))) {
3211 return KERN_NO_SPACE;
3212 }
3213
3214 vm_map_lock(map);
3215 map_locked = TRUE;
3216
3217
3218 if (anywhere) {
3219 result = vm_map_locate_space_anywhere(map, size, mask, vmk_flags,
3220 address, &entry);
3221 start = *address;
3222 } else {
3223 start = *address;
3224 result = vm_map_locate_space_fixed(map, start, size, mask,
3225 vmk_flags, &entry, &zap_old_list);
3226 }
3227
3228 vmlp_range_event(map, start, size);
3229 end = start + size;
3230
3231 assert(VM_MAP_PAGE_ALIGNED(start, VM_MAP_PAGE_MASK(map)));
3232
3233 /*
3234 * Check if what's already there is what we want.
3235 */
3236 if (result == KERN_MEMORY_PRESENT) {
3237 assert(!anywhere);
3238 if (!(vmk_flags.vmkf_already)) {
3239 RETURN(KERN_NO_SPACE);
3240 }
3241 tmp_start = start;
3242 tmp_offset = offset;
3243 if (entry->vme_start < start) {
3244 tmp_start -= start - entry->vme_start;
3245 tmp_offset -= start - entry->vme_start;
3246 }
3247 for (; entry->vme_start < end;
3248 entry = entry->vme_next) {
3249 /*
3250 * Check if the mapping's attributes
3251 * match the existing map entry.
3252 */
3253 if (entry == vm_map_to_entry(map) ||
3254 entry->vme_start != tmp_start ||
3255 entry->is_sub_map != is_submap ||
3256 VME_OFFSET(entry) != tmp_offset ||
3257 entry->needs_copy != needs_copy ||
3258 entry->protection != cur_protection ||
3259 entry->max_protection != max_protection ||
3260 entry->inheritance != inheritance ||
3261 entry->iokit_acct != iokit_acct ||
3262 VME_ALIAS(entry) != alias) {
3263 /* not the same mapping ! */
3264 RETURN(KERN_NO_SPACE);
3265 }
3266 /*
3267 * Check if the same object is being mapped.
3268 */
3269 if (is_submap) {
3270 if (VME_SUBMAP(entry) !=
3271 (vm_map_t) object) {
3272 /* not the same submap */
3273 RETURN(KERN_NO_SPACE);
3274 }
3275 } else {
3276 if (VME_OBJECT(entry) != object) {
3277 /* not the same VM object... */
3278 vm_object_t obj2;
3279
3280 obj2 = VME_OBJECT(entry);
3281 if ((obj2 == VM_OBJECT_NULL || obj2->internal) &&
3282 (object == VM_OBJECT_NULL || object->internal)) {
3283 /*
3284 * ... but both are
3285 * anonymous memory,
3286 * so equivalent.
3287 */
3288 } else {
3289 RETURN(KERN_NO_SPACE);
3290 }
3291 }
3292 }
3293
3294 tmp_offset += entry->vme_end - entry->vme_start;
3295 tmp_start += entry->vme_end - entry->vme_start;
3296 if (entry->vme_end >= end) {
3297 /* reached the end of our mapping */
3298 break;
3299 }
3300 }
3301 /* it all matches: let's use what's already there ! */
3302 RETURN(KERN_MEMORY_PRESENT);
3303 }
3304
3305 if (result != KERN_SUCCESS) {
3306 goto BailOut;
3307 }
3308
3309
3310 /*
3311 * At this point,
3312 * "start" and "end" should define the endpoints of the
3313 * available new range, and
3314 * "entry" should refer to the region before the new
3315 * range, and
3316 *
3317 * the map should be locked.
3318 */
3319
3320 /*
3321 * See whether we can avoid creating a new entry (and object) by
3322 * extending one of our neighbors. [So far, we only attempt to
3323 * extend from below.] Note that we can never extend/join
3324 * purgable objects because they need to remain distinct
3325 * entities in order to implement their "volatile object"
3326 * semantics.
3327 */
3328
3329 if (purgable ||
3330 entry_for_jit ||
3331 entry_for_tpro ||
3332 vm_memory_malloc_no_cow(user_alias)) {
3333 if (superpage_size) {
3334 /*
3335 * For "super page" allocations, we will allocate
3336 * special physically-contiguous VM objects later on,
3337 * so we should not have flags instructing us to create
3338 * a differently special VM object here.
3339 */
3340 RETURN(KERN_INVALID_ARGUMENT);
3341 }
3342
3343 if (object == VM_OBJECT_NULL) {
3344 assert(!superpage_size);
3345 object = vm_object_allocate(size, map->serial_id);
3346 vm_object_lock(object);
3347 object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
3348 VM_OBJECT_SET_TRUE_SHARE(object, FALSE);
3349 if (malloc_no_cow_except_fork &&
3350 !purgable &&
3351 !entry_for_jit &&
3352 !entry_for_tpro &&
3353 vm_memory_malloc_no_cow(user_alias)) {
3354 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY_FORK;
3355 VM_OBJECT_SET_TRUE_SHARE(object, TRUE);
3356 }
3357 if (entry_for_jit) {
3358 object->vo_inherit_copy_none = true;
3359 }
3360 if (purgable) {
3361 task_t owner;
3362 VM_OBJECT_SET_PURGABLE(object, VM_PURGABLE_NONVOLATILE);
3363 if (map->pmap == kernel_pmap) {
3364 /*
3365 * Purgeable mappings made in a kernel
3366 * map are "owned" by the kernel itself
3367 * rather than the current user task
3368 * because they're likely to be used by
3369 * more than this user task (see
3370 * execargs_purgeable_allocate(), for
3371 * example).
3372 */
3373 owner = kernel_task;
3374 } else {
3375 owner = current_task();
3376 }
3377 assert(object->vo_owner == NULL);
3378 assert(object->resident_page_count == 0);
3379 assert(object->wired_page_count == 0);
3380 vm_purgeable_nonvolatile_enqueue(object, owner);
3381 }
3382 vm_object_unlock(object);
3383 offset = (vm_object_offset_t)0;
3384 }
3385 } else if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) {
3386 /* no coalescing if address space uses sub-pages */
3387 } else if ((is_submap == FALSE) &&
3388 (object == VM_OBJECT_NULL) &&
3389 (entry != vm_map_to_entry(map)) &&
3390 (entry->vme_end == start) &&
3391 (!entry->is_shared) &&
3392 (!entry->is_sub_map) &&
3393 (!entry->in_transition) &&
3394 (!entry->needs_wakeup) &&
3395 (entry->behavior == VM_BEHAVIOR_DEFAULT) &&
3396 (entry->protection == cur_protection) &&
3397 (entry->max_protection == max_protection) &&
3398 (entry->inheritance == inheritance) &&
3399 ((user_alias == VM_MEMORY_REALLOC) ||
3400 (VME_ALIAS(entry) == alias)) &&
3401 (entry->no_cache == no_cache) &&
3402 (entry->vme_permanent == permanent) &&
3403 /* no coalescing for immutable executable mappings */
3404 !((entry->protection & VM_PROT_EXECUTE) &&
3405 entry->vme_permanent) &&
3406 (!entry->superpage_size && !superpage_size) &&
3407 (!entry->zero_wired_pages) &&
3408 (!entry->used_for_jit && !entry_for_jit) &&
3409#if __arm64e__
3410 (!entry->used_for_tpro && !entry_for_tpro) &&
3411#endif
3412 (!entry->csm_associated) &&
3413 (entry->iokit_acct == iokit_acct) &&
3414 (!entry->vme_resilient_codesign) &&
3415 (!entry->vme_resilient_media) &&
3416 (!entry->vme_atomic) &&
3417 (entry->vme_no_copy_on_read == no_copy_on_read) &&
3418
3419 ((entry->vme_end - entry->vme_start) + size <=
3420 (user_alias == VM_MEMORY_REALLOC ?
3421 ANON_CHUNK_SIZE :
3422 NO_COALESCE_LIMIT)) &&
3423
3424 (entry->wired_count == 0)) { /* implies user_wired_count == 0 */
3425 if (vm_object_coalesce(VME_OBJECT(entry),
3426 VM_OBJECT_NULL,
3427 VME_OFFSET(entry),
3428 (vm_object_offset_t) 0,
3429 (vm_map_size_t)(entry->vme_end - entry->vme_start),
3430 (vm_map_size_t)(end - entry->vme_end))) {
3431 /*
3432 * Coalesced the two objects - can extend
3433 * the previous map entry to include the
3434 * new range.
3435 */
3436 map->size += (end - entry->vme_end);
3437 assert(entry->vme_start < end);
3438 assert(VM_MAP_PAGE_ALIGNED(end,
3439 VM_MAP_PAGE_MASK(map)));
3440 if (__improbable(vm_debug_events)) {
3441 DTRACE_VM5(map_entry_extend, vm_map_t, map, vm_map_entry_t, entry, vm_address_t, entry->vme_start, vm_address_t, entry->vme_end, vm_address_t, end);
3442 }
3443 entry->vme_end = end;
3444 if (map->holelistenabled) {
3445 vm_map_store_update_first_free(map, entry, TRUE);
3446 } else {
3447 vm_map_store_update_first_free(map, map->first_free, TRUE);
3448 }
3449 new_mapping_established = TRUE;
3450 RETURN(KERN_SUCCESS);
3451 }
3452 }
3453
3454 step = superpage_size ? SUPERPAGE_SIZE : (end - start);
3455 new_entry = NULL;
3456
3457 if (vmk_flags.vmkf_submap_adjust) {
3458 vm_map_adjust_offsets((vm_map_t)caller_object, start, end);
3459 offset = start;
3460 }
3461
3462 for (tmp2_start = start; tmp2_start < end; tmp2_start += step) {
3463 tmp2_end = tmp2_start + step;
3464 /*
3465 * Create a new entry
3466 *
3467 * XXX FBDP
3468 * The reserved "page zero" in each process's address space can
3469 * be arbitrarily large. Splitting it into separate objects and
3470 * therefore different VM map entries serves no purpose and just
3471 * slows down operations on the VM map, so let's not split the
3472 * allocation into chunks if the max protection is NONE. That
3473 * memory should never be accessible, so it will never get to the
3474 * default pager.
3475 */
3476 tmp_start = tmp2_start;
3477 if (!is_submap &&
3478 object == VM_OBJECT_NULL &&
3479 size > chunk_size &&
3480 max_protection != VM_PROT_NONE &&
3481 superpage_size == 0) {
3482 tmp_end = tmp_start + chunk_size;
3483 } else {
3484 tmp_end = tmp2_end;
3485 }
3486 do {
3487 if (!is_submap &&
3488 object != VM_OBJECT_NULL &&
3489 object->internal &&
3490 offset + (tmp_end - tmp_start) > object->vo_size) {
3491// printf("FBDP object %p size 0x%llx overmapping offset 0x%llx size 0x%llx\n", object, object->vo_size, offset, (uint64_t)(tmp_end - tmp_start));
3492 DTRACE_VM5(vm_map_enter_overmap,
3493 vm_map_t, map,
3494 vm_map_address_t, tmp_start,
3495 vm_map_address_t, tmp_end,
3496 vm_object_offset_t, offset,
3497 vm_object_size_t, object->vo_size);
3498 }
3499 new_entry = vm_map_entry_insert(map,
3500 entry, tmp_start, tmp_end,
3501 object, offset, vmk_flags,
3502 needs_copy,
3503 cur_protection, max_protection,
3504 (entry_for_jit && !VM_MAP_POLICY_ALLOW_JIT_INHERIT(map) ?
3505 VM_INHERIT_NONE : inheritance));
3506
3507 assert(!is_kernel_object(object) || (VM_KERN_MEMORY_NONE != alias));
3508
3509 if (resilient_codesign) {
3510 int reject_prot = (needs_copy ? VM_PROT_ALLEXEC : (VM_PROT_WRITE | VM_PROT_ALLEXEC));
3511 if (!((cur_protection | max_protection) & reject_prot)) {
3512 new_entry->vme_resilient_codesign = TRUE;
3513 }
3514 }
3515
3516 if (resilient_media &&
3517 (object == VM_OBJECT_NULL ||
3518 object->internal)) {
3519 new_entry->vme_resilient_media = TRUE;
3520 }
3521
3522 assert(!new_entry->iokit_acct);
3523 if (!is_submap &&
3524 object != VM_OBJECT_NULL &&
3525 object->internal &&
3526 (object->purgable != VM_PURGABLE_DENY ||
3527 object->vo_ledger_tag)) {
3528 assert(new_entry->use_pmap);
3529 assert(!new_entry->iokit_acct);
3530 /*
3531 * Turn off pmap accounting since
3532 * purgeable (or tagged) objects have their
3533 * own ledgers.
3534 */
3535 new_entry->use_pmap = FALSE;
3536 } else if (!is_submap &&
3537 iokit_acct &&
3538 object != VM_OBJECT_NULL &&
3539 object->internal) {
3540 /* alternate accounting */
3541 assert(!new_entry->iokit_acct);
3542 assert(new_entry->use_pmap);
3543 new_entry->iokit_acct = TRUE;
3544 new_entry->use_pmap = FALSE;
3545 DTRACE_VM4(
3546 vm_map_iokit_mapped_region,
3547 vm_map_t, map,
3548 vm_map_offset_t, new_entry->vme_start,
3549 vm_map_offset_t, new_entry->vme_end,
3550 int, VME_ALIAS(new_entry));
3551 vm_map_iokit_mapped_region(
3552 map,
3553 (new_entry->vme_end -
3554 new_entry->vme_start));
3555 } else if (!is_submap) {
3556 assert(!new_entry->iokit_acct);
3557 assert(new_entry->use_pmap);
3558 }
3559
3560 if (is_submap) {
3561 vm_map_t submap;
3562 boolean_t submap_is_64bit;
3563 boolean_t use_pmap;
3564
3565 assert(new_entry->is_sub_map);
3566 assert(!new_entry->use_pmap);
3567 assert(!new_entry->iokit_acct);
3568 submap = (vm_map_t) object;
3569 submap_is_64bit = vm_map_is_64bit(submap);
3570 use_pmap = vmk_flags.vmkf_nested_pmap;
3571#ifndef NO_NESTED_PMAP
3572 if (use_pmap && submap->pmap == NULL) {
3573 ledger_t ledger = map->pmap->ledger;
3574 /* we need a sub pmap to nest... */
3575 submap->pmap = pmap_create_options(ledger, 0,
3576 submap_is_64bit ? PMAP_CREATE_64BIT | PMAP_CREATE_NESTED : PMAP_CREATE_NESTED);
3577 if (submap->pmap == NULL) {
3578 /* let's proceed without nesting... */
3579 }
3580#if defined(__arm64__)
3581 else {
3582 /*
3583 * When a nested pmap is created within vm_shared_region_create, we
3584 * need to call csm_setup_nested_address_space, but the same doesn't
3585 * need to happen here.
3586 *
3587 * We only enter the parent if-block if use_pmap is set to true, which
3588 * is based on vmkf_nested_pmap. This flag is only set by two functions,
3589 * vm_shared_region_enter, and vm_commpage_enter. The former performs a
3590 * shared region lookup, which uses vm_shared_region_create. This path
3591 * already creates a pmap, so submap->pmap != NULL. The latter doesn't
3592 * go through the VM layer on arm64 systems anymore. As a result, there
3593 * is no case on arm64 where a nested pmap is actually in this path.
3594 */
3595 pmap_set_nested(submap->pmap);
3596 }
3597#endif
3598 }
3599 if (use_pmap && submap->pmap != NULL) {
3600 if (VM_MAP_PAGE_SHIFT(map) != VM_MAP_PAGE_SHIFT(submap)) {
3601 DEBUG4K_ERROR("map %p (%d) submap %p (%d): incompatible page sizes\n", map, VM_MAP_PAGE_SHIFT(map), submap, VM_MAP_PAGE_SHIFT(submap));
3602 kr = KERN_FAILURE;
3603 } else {
3604 kr = pmap_nest(map->pmap,
3605 submap->pmap,
3606 tmp_start,
3607 tmp_end - tmp_start);
3608 }
3609 if (kr != KERN_SUCCESS) {
3610 printf("vm_map_enter: "
3611 "pmap_nest(0x%llx,0x%llx) "
3612 "error 0x%x\n",
3613 (long long)tmp_start,
3614 (long long)tmp_end,
3615 kr);
3616 } else {
3617 /* we're now nested ! */
3618 new_entry->use_pmap = TRUE;
3619 pmap_empty = FALSE;
3620 }
3621 }
3622#endif /* NO_NESTED_PMAP */
3623 }
3624 entry = new_entry;
3625
3626 if (superpage_size) {
3627 vm_page_t pages, m;
3628 vm_object_t sp_object;
3629 vm_object_offset_t sp_offset;
3630
3631 assert(object == VM_OBJECT_NULL);
3632 VME_OFFSET_SET(entry, 0);
3633
3634 /* allocate one superpage */
3635 kr = cpm_allocate(SUPERPAGE_SIZE, &pages, 0, SUPERPAGE_NBASEPAGES - 1, TRUE, 0);
3636 if (kr != KERN_SUCCESS) {
3637 /* deallocate whole range... */
3638 new_mapping_established = TRUE;
3639 /* ... but only up to "tmp_end" */
3640 size -= end - tmp_end;
3641 RETURN(kr);
3642 }
3643
3644 /* create one vm_object per superpage */
3645 sp_object = vm_object_allocate((vm_map_size_t)(entry->vme_end - entry->vme_start), map->serial_id);
3646 vm_object_lock(sp_object);
3647 sp_object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
3648 VM_OBJECT_SET_PHYS_CONTIGUOUS(sp_object, TRUE);
3649 sp_object->vo_shadow_offset = (vm_object_offset_t)VM_PAGE_GET_PHYS_PAGE(pages) * PAGE_SIZE;
3650 VME_OBJECT_SET(entry, sp_object, false, 0);
3651 assert(entry->use_pmap);
3652
3653 /* enter the base pages into the object */
3654 for (sp_offset = 0;
3655 sp_offset < SUPERPAGE_SIZE;
3656 sp_offset += PAGE_SIZE) {
3657 m = pages;
3658 pmap_zero_page(VM_PAGE_GET_PHYS_PAGE(m));
3659 pages = NEXT_PAGE(m);
3660 *(NEXT_PAGE_PTR(m)) = VM_PAGE_NULL;
3661 vm_page_insert_wired(m, sp_object, sp_offset, VM_KERN_MEMORY_OSFMK);
3662 }
3663 vm_object_unlock(sp_object);
3664 }
3665 } while (tmp_end != tmp2_end &&
3666 (tmp_start = tmp_end) &&
3667 (tmp_end = (tmp2_end - tmp_end > chunk_size) ?
3668 tmp_end + chunk_size : tmp2_end));
3669 }
3670
3671 new_mapping_established = TRUE;
3672
3673
3674BailOut:
3675 assert(map_locked == TRUE);
3676
3677 /*
3678 * Address space limit enforcement (RLIMIT_AS and RLIMIT_DATA):
3679 * If we have identified and possibly established the new mapping(s),
3680 * make sure we did not go beyond the address space limit.
3681 */
3682 if (result == KERN_SUCCESS) {
3683 if (map->size_limit != RLIM_INFINITY &&
3684 map->size > map->size_limit) {
3685 /*
3686 * Establishing the requested mappings would exceed
3687 * the process's RLIMIT_AS limit: fail with
3688 * KERN_NO_SPACE.
3689 */
3690 result = KERN_NO_SPACE;
3691 printf("%d[%s] %s: map size 0x%llx over RLIMIT_AS 0x%llx\n",
3692 proc_selfpid(),
3693 (get_bsdtask_info(current_task())
3694 ? proc_name_address(get_bsdtask_info(current_task()))
3695 : "?"),
3696 __FUNCTION__,
3697 (uint64_t) map->size,
3698 (uint64_t) map->size_limit);
3699 DTRACE_VM2(vm_map_enter_RLIMIT_AS,
3700 vm_map_size_t, map->size,
3701 uint64_t, map->size_limit);
3702 vm_map_enter_RLIMIT_AS_count++;
3703 } else if (map->data_limit != RLIM_INFINITY &&
3704 map->size > map->data_limit) {
3705 /*
3706 * Establishing the requested mappings would exceed
3707 * the process's RLIMIT_DATA limit: fail with
3708 * KERN_NO_SPACE.
3709 */
3710 result = KERN_NO_SPACE;
3711 printf("%d[%s] %s: map size 0x%llx over RLIMIT_DATA 0x%llx\n",
3712 proc_selfpid(),
3713 (get_bsdtask_info(current_task())
3714 ? proc_name_address(get_bsdtask_info(current_task()))
3715 : "?"),
3716 __FUNCTION__,
3717 (uint64_t) map->size,
3718 (uint64_t) map->data_limit);
3719 DTRACE_VM2(vm_map_enter_RLIMIT_DATA,
3720 vm_map_size_t, map->size,
3721 uint64_t, map->data_limit);
3722 vm_map_enter_RLIMIT_DATA_count++;
3723 }
3724 }
3725
3726 if (result == KERN_SUCCESS) {
3727 vm_prot_t pager_prot;
3728 memory_object_t pager;
3729
3730#if DEBUG
3731 if (pmap_empty &&
3732 !(vmk_flags.vmkf_no_pmap_check)) {
3733 assert(pmap_is_empty(map->pmap,
3734 *address,
3735 *address + size));
3736 }
3737#endif /* DEBUG */
3738
3739 /*
3740 * For "named" VM objects, let the pager know that the
3741 * memory object is being mapped. Some pagers need to keep
3742 * track of this, to know when they can reclaim the memory
3743 * object, for example.
3744 * VM calls memory_object_map() for each mapping (specifying
3745 * the protection of each mapping) and calls
3746 * memory_object_last_unmap() when all the mappings are gone.
3747 */
3748 pager_prot = max_protection;
3749 if (needs_copy) {
3750 /*
3751 * Copy-On-Write mapping: won't modify
3752 * the memory object.
3753 */
3754 pager_prot &= ~VM_PROT_WRITE;
3755 }
3756 if (!is_submap &&
3757 object != VM_OBJECT_NULL &&
3758 object->named &&
3759 object->pager != MEMORY_OBJECT_NULL) {
3760 vm_object_lock(object);
3761 pager = object->pager;
3762 if (object->named &&
3763 pager != MEMORY_OBJECT_NULL) {
3764 assert(object->pager_ready);
3765 vm_object_mapping_wait(object, THREAD_UNINT);
3766 /* object might have lost its pager while waiting */
3767 pager = object->pager;
3768 if (object->named && pager != MEMORY_OBJECT_NULL) {
3769 vm_object_mapping_begin(object);
3770 vm_object_unlock(object);
3771
3772 kr = memory_object_map(pager, pager_prot);
3773 assert(kr == KERN_SUCCESS);
3774
3775 vm_object_lock(object);
3776 vm_object_mapping_end(object);
3777 }
3778 }
3779 vm_object_unlock(object);
3780 }
3781 }
3782
3783 assert(map_locked == TRUE);
3784
3785 if (new_mapping_established) {
3786 /*
3787 * If we release the map lock for any reason below,
3788 * another thread could deallocate our new mapping,
3789 * releasing the caller's reference on "caller_object",
3790 * which was transferred to the mapping.
3791 * If this was the only reference, the object could be
3792 * destroyed.
3793 *
3794 * We need to take an extra reference on "caller_object"
3795 * to keep it alive if we need to return the caller's
3796 * reference to the caller in case of failure.
3797 */
3798 if (is_submap) {
3799 vm_map_reference((vm_map_t)caller_object);
3800 } else {
3801 vm_object_reference(caller_object);
3802 }
3803 }
3804
3805 if (!keep_map_locked) {
3806 vm_map_unlock(map);
3807 map_locked = FALSE;
3808 entry = VM_MAP_ENTRY_NULL;
3809 new_entry = VM_MAP_ENTRY_NULL;
3810 }
3811
3812 /*
3813 * We can't hold the map lock if we enter this block.
3814 */
3815
3816 if (result == KERN_SUCCESS) {
3817 /* Wire down the new entry if the user
3818 * requested all new map entries be wired.
3819 */
3820 if ((map->wiring_required) || (superpage_size)) {
3821 assert(!keep_map_locked);
3822 pmap_empty = FALSE; /* pmap won't be empty */
3823 kr = vm_map_wire_nested(map, start, end,
3824 cur_protection, VM_KERN_MEMORY_MLOCK,
3825 TRUE, PMAP_NULL, 0, NULL);
3826 result = kr;
3827 }
3828
3829 }
3830
3831 if (result != KERN_SUCCESS) {
3832 if (new_mapping_established) {
3833 vmr_flags_t remove_flags = VM_MAP_REMOVE_NO_FLAGS;
3834
3835 /*
3836 * We have to get rid of the new mappings since we
3837 * won't make them available to the user.
3838 * Try and do that atomically, to minimize the risk
3839 * that someone else create new mappings that range.
3840 */
3841 if (!map_locked) {
3842 vm_map_lock(map);
3843 map_locked = TRUE;
3844 }
3845 remove_flags |= VM_MAP_REMOVE_NO_YIELD;
3846 if (permanent) {
3847 remove_flags |= VM_MAP_REMOVE_IMMUTABLE;
3848 }
3849 (void) vm_map_delete(map,
3850 *address, *address + size,
3851 remove_flags,
3852 KMEM_GUARD_NONE, &zap_new_list);
3853 }
3854
3855 if (vm_map_zap_first_entry(&zap_old_list)) {
3856 vm_map_entry_t entry1, entry2;
3857
3858 /*
3859 * The new mapping failed. Attempt to restore
3860 * the old mappings, saved in the "zap_old_map".
3861 */
3862 if (!map_locked) {
3863 vm_map_lock(map);
3864 map_locked = TRUE;
3865 }
3866
3867 /* first check if the coast is still clear */
3868 start = vm_map_zap_first_entry(&zap_old_list)->vme_start;
3869 end = vm_map_zap_last_entry(&zap_old_list)->vme_end;
3870
3871 if (vm_map_lookup_entry(map, start, &entry1) ||
3872 vm_map_lookup_entry(map, end, &entry2) ||
3873 entry1 != entry2) {
3874 /*
3875 * Part of that range has already been
3876 * re-mapped: we can't restore the old
3877 * mappings...
3878 */
3879 vm_map_enter_restore_failures++;
3880 } else {
3881 /*
3882 * Transfer the saved map entries from
3883 * "zap_old_map" to the original "map",
3884 * inserting them all after "entry1".
3885 */
3886 while ((entry2 = vm_map_zap_pop(&zap_old_list))) {
3887 vm_map_size_t entry_size;
3888
3889 entry_size = (entry2->vme_end -
3890 entry2->vme_start);
3891 vm_map_store_entry_link(map, entry1, entry2,
3892 VM_MAP_KERNEL_FLAGS_NONE);
3893 map->size += entry_size;
3894 entry1 = entry2;
3895 }
3896 if (map->wiring_required) {
3897 /*
3898 * XXX TODO: we should rewire the
3899 * old pages here...
3900 */
3901 }
3902 vm_map_enter_restore_successes++;
3903 }
3904 }
3905 }
3906
3907 /*
3908 * The caller is responsible for releasing the lock if it requested to
3909 * keep the map locked.
3910 */
3911 if (map_locked && !keep_map_locked) {
3912 vm_map_unlock(map);
3913 }
3914
3915 vm_map_zap_dispose(&zap_old_list);
3916 vm_map_zap_dispose(&zap_new_list);
3917
3918 if (new_mapping_established) {
3919 /*
3920 * The caller had a reference on "caller_object" and we
3921 * transferred that reference to the mapping.
3922 * We also took an extra reference on "caller_object" to keep
3923 * it alive while the map was unlocked.
3924 */
3925 if (result == KERN_SUCCESS) {
3926 /*
3927 * On success, the caller's reference on the object gets
3928 * tranferred to the mapping.
3929 * Release our extra reference.
3930 */
3931 if (is_submap) {
3932 vm_map_deallocate((vm_map_t)caller_object);
3933 } else {
3934 vm_object_deallocate(caller_object);
3935 }
3936 } else {
3937 /*
3938 * On error, the caller expects to still have a
3939 * reference on the object it gave us.
3940 * Let's use our extra reference for that.
3941 */
3942 }
3943 }
3944
3945 vmlp_api_end(VM_MAP_ENTER, result);
3946 return result;
3947
3948#undef RETURN
3949}
3950
3951/*
3952 * Counters for the prefault optimization.
3953 */
3954int64_t vm_prefault_nb_pages = 0;
3955int64_t vm_prefault_nb_bailout = 0;
3956int64_t vm_prefault_nb_no_page = 0;
3957int64_t vm_prefault_nb_wrong_page = 0;
3958
3959
3960static kern_return_t
3961vm_map_enter_adjust_offset(
3962 vm_object_offset_t *obj_offs,
3963 vm_object_offset_t *obj_end,
3964 vm_object_offset_t quantity)
3965{
3966 if (os_add_overflow(*obj_offs, quantity, obj_offs) ||
3967 os_add_overflow(*obj_end, quantity, obj_end) ||
3968 vm_map_round_page_mask(*obj_end, PAGE_MASK) == 0) {
3969 return KERN_INVALID_ARGUMENT;
3970 }
3971
3972 return KERN_SUCCESS;
3973}
3974
3975static __attribute__((always_inline, warn_unused_result))
3976kern_return_t
3977vm_map_enter_mem_object_sanitize(
3978 vm_map_t target_map,
3979 vm_map_offset_ut address_u,
3980 vm_map_size_ut initial_size_u,
3981 vm_map_offset_ut mask_u,
3982 vm_object_offset_ut offset_u,
3983 vm_prot_ut cur_protection_u,
3984 vm_prot_ut max_protection_u,
3985 vm_inherit_ut inheritance_u,
3986 vm_map_kernel_flags_t vmk_flags,
3987 ipc_port_t port,
3988 vm_map_address_t *map_addr,
3989 vm_map_size_t *map_size,
3990 vm_map_offset_t *mask,
3991 vm_object_offset_t *obj_offs,
3992 vm_object_offset_t *obj_end,
3993 vm_object_size_t *obj_size,
3994 vm_prot_t *cur_protection,
3995 vm_prot_t *max_protection,
3996 vm_inherit_t *inheritance)
3997{
3998 kern_return_t result;
3999
4000 result = vm_sanitize_cur_and_max_prots(cur_protection_u, max_protection_u,
4001 VM_SANITIZE_CALLER_ENTER_MEM_OBJ, target_map,
4002 VM_PROT_IS_MASK, cur_protection,
4003 max_protection);
4004 if (__improbable(result != KERN_SUCCESS)) {
4005 return result;
4006 }
4007
4008 result = vm_sanitize_inherit(inheritance_u, VM_SANITIZE_CALLER_ENTER_MEM_OBJ,
4009 inheritance);
4010 if (__improbable(result != KERN_SUCCESS)) {
4011 return result;
4012 }
4013
4014 result = vm_sanitize_mask(mask_u, VM_SANITIZE_CALLER_ENTER_MEM_OBJ, mask);
4015 if (__improbable(result != KERN_SUCCESS)) {
4016 return result;
4017 }
4018
4019 if (vmk_flags.vmf_fixed) {
4020 vm_map_address_t map_end;
4021
4022 result = vm_sanitize_addr_size(address_u, initial_size_u,
4023 VM_SANITIZE_CALLER_ENTER_MEM_OBJ,
4024 target_map,
4025 VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS | VM_SANITIZE_FLAGS_REALIGN_START,
4026 map_addr, &map_end, map_size);
4027 if (__improbable(result != KERN_SUCCESS)) {
4028 return result;
4029 }
4030 } else {
4031 *map_addr = vm_sanitize_addr(target_map, address_u);
4032 result = vm_sanitize_size(0, initial_size_u,
4033 VM_SANITIZE_CALLER_ENTER_MEM_OBJ, target_map,
4034 VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS, map_size);
4035 if (__improbable(result != KERN_SUCCESS)) {
4036 return result;
4037 }
4038 }
4039
4040 *obj_size = vm_object_round_page(*map_size);
4041 if (__improbable(*obj_size == 0)) {
4042 return KERN_INVALID_ARGUMENT;
4043 }
4044
4045 if (IP_VALID(port)) {
4046 result = vm_sanitize_addr_size(offset_u, *obj_size,
4047 VM_SANITIZE_CALLER_ENTER_MEM_OBJ,
4048 PAGE_MASK,
4049 VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS |
4050 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES,
4051 obj_offs, obj_end, obj_size);
4052 if (__improbable(result != KERN_SUCCESS)) {
4053 return result;
4054 }
4055 } else {
4056 *obj_offs = 0;
4057 *obj_end = *obj_size;
4058 }
4059
4060 return KERN_SUCCESS;
4061}
4062
4063kern_return_t
4064vm_map_enter_mem_object(
4065 vm_map_t target_map,
4066 vm_map_offset_ut *address_u,
4067 vm_map_size_ut initial_size_u,
4068 vm_map_offset_ut mask_u,
4069 vm_map_kernel_flags_t vmk_flags,
4070 ipc_port_t port,
4071 vm_object_offset_ut offset_u,
4072 boolean_t copy,
4073 vm_prot_ut cur_protection_u,
4074 vm_prot_ut max_protection_u,
4075 vm_inherit_ut inheritance_u,
4076 upl_page_list_ptr_t page_list,
4077 unsigned int page_list_count)
4078{
4079 vm_map_offset_t mask;
4080 vm_prot_t cur_protection;
4081 vm_prot_t max_protection;
4082 vm_inherit_t inheritance;
4083 vm_map_address_t map_addr, map_mask;
4084 vm_map_size_t map_size;
4085 vm_object_t object = VM_OBJECT_NULL;
4086 vm_object_offset_t obj_offs, obj_end;
4087 vm_object_size_t obj_size;
4088 kern_return_t result;
4089 boolean_t mask_cur_protection, mask_max_protection;
4090 boolean_t kernel_prefault, try_prefault = (page_list_count != 0);
4091 vm_map_offset_t offset_in_mapping = 0;
4092
4093 vmlp_api_start(VM_MAP_ENTER_MEM_OBJECT);
4094
4095 if (VM_MAP_PAGE_SHIFT(target_map) < PAGE_SHIFT) {
4096 /* XXX TODO4K prefaulting depends on page size... */
4097 try_prefault = FALSE;
4098 }
4099
4100 /*
4101 * Check arguments for validity
4102 */
4103 if ((target_map == VM_MAP_NULL) ||
4104 (try_prefault && (copy || !page_list))) {
4105 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_ARGUMENT);
4106 return KERN_INVALID_ARGUMENT;
4107 }
4108
4109 map_mask = vm_map_page_mask(target_map);
4110
4111 /*
4112 * Sanitize any input parameters that are addr/size/prot/inherit
4113 */
4114 result = vm_map_enter_mem_object_sanitize(
4115 target_map,
4116 *address_u,
4117 initial_size_u,
4118 mask_u,
4119 offset_u,
4120 cur_protection_u,
4121 max_protection_u,
4122 inheritance_u,
4123 vmk_flags,
4124 port,
4125 &map_addr,
4126 &map_size,
4127 &mask,
4128 &obj_offs,
4129 &obj_end,
4130 &obj_size,
4131 &cur_protection,
4132 &max_protection,
4133 &inheritance);
4134 if (__improbable(result != KERN_SUCCESS)) {
4135 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, vm_sanitize_get_kr(result));
4136 return vm_sanitize_get_kr(result);
4137 }
4138
4139 assertf(vmk_flags.__vmkf_unused2 == 0, "vmk_flags unused2=0x%llx\n", vmk_flags.__vmkf_unused2);
4140 vm_map_kernel_flags_update_range_id(&vmk_flags, target_map, map_size);
4141
4142 mask_cur_protection = cur_protection & VM_PROT_IS_MASK;
4143 mask_max_protection = max_protection & VM_PROT_IS_MASK;
4144 cur_protection &= ~VM_PROT_IS_MASK;
4145 max_protection &= ~VM_PROT_IS_MASK;
4146
4147#if __arm64__
4148 if (cur_protection & VM_PROT_EXECUTE) {
4149 cur_protection |= VM_PROT_READ;
4150 }
4151#endif /* __arm64__ */
4152
4153 /*
4154 * Find the vm object (if any) corresponding to this port.
4155 */
4156 if (!IP_VALID(port)) {
4157 object = VM_OBJECT_NULL;
4158 copy = FALSE;
4159 } else if (ip_type(port) == IKOT_NAMED_ENTRY) {
4160 vm_named_entry_t named_entry;
4161 vm_object_size_t initial_size;
4162
4163 named_entry = mach_memory_entry_from_port(port);
4164
4165 if (vmk_flags.vmf_return_data_addr ||
4166 vmk_flags.vmf_return_4k_data_addr) {
4167 result = vm_map_enter_adjust_offset(&obj_offs,
4168 &obj_end, named_entry->data_offset);
4169 if (__improbable(result)) {
4170 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, result);
4171 return result;
4172 }
4173 }
4174
4175 /* a few checks to make sure user is obeying rules */
4176 if (mask_max_protection) {
4177 max_protection &= named_entry->protection;
4178 }
4179 if (mask_cur_protection) {
4180 cur_protection &= named_entry->protection;
4181 }
4182 if ((named_entry->protection & max_protection) !=
4183 max_protection) {
4184 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_RIGHT);
4185 return KERN_INVALID_RIGHT;
4186 }
4187 if ((named_entry->protection & cur_protection) !=
4188 cur_protection) {
4189 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_RIGHT);
4190 return KERN_INVALID_RIGHT;
4191 }
4192
4193 /*
4194 * unwrap is safe because we know obj_size is larger and doesn't
4195 * overflow
4196 */
4197 initial_size = VM_SANITIZE_UNSAFE_UNWRAP(initial_size_u);
4198 if (named_entry->size < obj_offs + initial_size) {
4199 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_ARGUMENT);
4200 return KERN_INVALID_ARGUMENT;
4201 }
4202
4203 /* for a vm_map_copy, we can only map it whole */
4204 if (named_entry->is_copy &&
4205 (obj_size != named_entry->size) &&
4206 (vm_map_round_page(obj_size, map_mask) == named_entry->size)) {
4207 /* XXX FBDP use the rounded size... */
4208 obj_end += named_entry->size - obj_size;
4209 obj_size = named_entry->size;
4210 }
4211
4212 if (named_entry->offset) {
4213 /*
4214 * the callers parameter offset is defined to be the
4215 * offset from beginning of named entry offset in object
4216 *
4217 * Because we checked above that
4218 * obj_offs + obj_size < named_entry_size
4219 * these overflow checks should be redundant...
4220 */
4221 result = vm_map_enter_adjust_offset(&obj_offs,
4222 &obj_end, named_entry->offset);
4223 if (__improbable(result)) {
4224 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, result);
4225 return result;
4226 }
4227 }
4228
4229 if (!VM_MAP_PAGE_ALIGNED(obj_size, map_mask)) {
4230 /*
4231 * Let's not map more than requested;
4232 * vm_map_enter() will handle this "not map-aligned"
4233 * case.
4234 */
4235 map_size = obj_size;
4236 }
4237
4238 named_entry_lock(named_entry);
4239
4240 // rdar://130307561 (Combine copy, object, and submap fields of vm_named_entry into an enum)
4241 assert(named_entry->is_copy || named_entry->is_object || named_entry->is_sub_map);
4242
4243 if (named_entry->is_sub_map) {
4244 vm_map_t submap;
4245
4246 assert(!named_entry->is_copy);
4247 assert(!named_entry->is_object);
4248
4249 if (vmk_flags.vmf_return_data_addr ||
4250 vmk_flags.vmf_return_4k_data_addr) {
4251 panic("VM_FLAGS_RETURN_DATA_ADDR not expected for submap.");
4252 }
4253
4254 submap = named_entry->backing.map;
4255 vm_map_reference(submap);
4256 named_entry_unlock(named_entry);
4257
4258 vmk_flags.vmkf_submap = TRUE;
4259 result = vm_map_enter(target_map,
4260 &map_addr,
4261 map_size,
4262 mask,
4263 vmk_flags,
4264 (vm_object_t)(uintptr_t) submap,
4265 obj_offs,
4266 copy,
4267 cur_protection,
4268 max_protection,
4269 inheritance);
4270 if (result != KERN_SUCCESS) {
4271 vm_map_deallocate(submap);
4272 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, result);
4273 return result;
4274 }
4275 /*
4276 * No need to lock "submap" just to check its
4277 * "mapped" flag: that flag is never reset
4278 * once it's been set and if we race, we'll
4279 * just end up setting it twice, which is OK.
4280 */
4281 if (submap->mapped_in_other_pmaps == FALSE &&
4282 vm_map_pmap(submap) != PMAP_NULL &&
4283 vm_map_pmap(submap) !=
4284 vm_map_pmap(target_map)) {
4285 /*
4286 * This submap is being mapped in a map
4287 * that uses a different pmap.
4288 * Set its "mapped_in_other_pmaps" flag
4289 * to indicate that we now need to
4290 * remove mappings from all pmaps rather
4291 * than just the submap's pmap.
4292 */
4293 vm_map_lock(submap);
4294 submap->mapped_in_other_pmaps = TRUE;
4295 vm_map_unlock(submap);
4296 }
4297 goto out;
4298 }
4299
4300 if (named_entry->is_copy) {
4301 kern_return_t kr;
4302 vm_map_copy_t copy_map;
4303 vm_map_entry_t copy_entry;
4304 vm_map_offset_t copy_addr;
4305 vm_map_copy_t target_copy_map;
4306 vm_map_offset_t overmap_start, overmap_end;
4307 vm_map_offset_t trimmed_start;
4308 vm_map_size_t target_size;
4309
4310 assert(!named_entry->is_object);
4311 assert(!named_entry->is_sub_map);
4312
4313 int allowed_flags = VM_FLAGS_FIXED |
4314 VM_FLAGS_ANYWHERE |
4315 VM_FLAGS_OVERWRITE |
4316 VM_FLAGS_RETURN_4K_DATA_ADDR |
4317 VM_FLAGS_RETURN_DATA_ADDR;
4318
4319 if (!vm_map_kernel_flags_check_vmflags(vmk_flags, allowed_flags)) {
4320 named_entry_unlock(named_entry);
4321 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_ARGUMENT);
4322 return KERN_INVALID_ARGUMENT;
4323 }
4324
4325 copy_map = named_entry->backing.copy;
4326 assert(copy_map->type == VM_MAP_COPY_ENTRY_LIST);
4327 if (copy_map->type != VM_MAP_COPY_ENTRY_LIST) {
4328 /* unsupported type; should not happen */
4329 printf("vm_map_enter_mem_object: "
4330 "memory_entry->backing.copy "
4331 "unsupported type 0x%x\n",
4332 copy_map->type);
4333 named_entry_unlock(named_entry);
4334 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_ARGUMENT);
4335 return KERN_INVALID_ARGUMENT;
4336 }
4337
4338 if (VM_MAP_PAGE_SHIFT(target_map) != copy_map->cpy_hdr.page_shift) {
4339 DEBUG4K_SHARE("copy_map %p offset %llx size 0x%llx pgshift %d -> target_map %p pgshift %d\n", copy_map, obj_offs, (uint64_t)map_size, copy_map->cpy_hdr.page_shift, target_map, VM_MAP_PAGE_SHIFT(target_map));
4340 }
4341
4342 if (vmk_flags.vmf_return_data_addr ||
4343 vmk_flags.vmf_return_4k_data_addr) {
4344 offset_in_mapping = obj_offs & map_mask;
4345 if (vmk_flags.vmf_return_4k_data_addr) {
4346 offset_in_mapping &= ~((signed)(0xFFF));
4347 }
4348 }
4349
4350 target_copy_map = VM_MAP_COPY_NULL;
4351 target_size = copy_map->size;
4352 overmap_start = 0;
4353 overmap_end = 0;
4354 trimmed_start = 0;
4355 if (copy_map->cpy_hdr.page_shift != VM_MAP_PAGE_SHIFT(target_map)) {
4356 DEBUG4K_ADJUST("adjusting...\n");
4357 kr = vm_map_copy_adjust_to_target(
4358 copy_map,
4359 obj_offs,
4360 initial_size,
4361 target_map,
4362 copy,
4363 &target_copy_map,
4364 &overmap_start,
4365 &overmap_end,
4366 &trimmed_start);
4367 if (kr != KERN_SUCCESS) {
4368 named_entry_unlock(named_entry);
4369 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, kr);
4370 return kr;
4371 }
4372 target_size = target_copy_map->size;
4373 } else {
4374 /*
4375 * Assert that the vm_map_copy is coming from the right
4376 * zone and hasn't been forged
4377 */
4378 vm_map_copy_require(copy_map);
4379 target_copy_map = copy_map;
4380 }
4381
4382 vm_map_kernel_flags_t rsv_flags = vmk_flags;
4383
4384 vm_map_kernel_flags_and_vmflags(&rsv_flags,
4385 (VM_FLAGS_FIXED |
4386 VM_FLAGS_ANYWHERE |
4387 VM_FLAGS_OVERWRITE |
4388 VM_FLAGS_RETURN_4K_DATA_ADDR |
4389 VM_FLAGS_RETURN_DATA_ADDR));
4390
4391 /* reserve a contiguous range */
4392 kr = vm_map_enter(target_map,
4393 &map_addr,
4394 vm_map_round_page(target_size, map_mask),
4395 mask,
4396 rsv_flags,
4397 VM_OBJECT_NULL,
4398 0,
4399 FALSE, /* copy */
4400 cur_protection,
4401 max_protection,
4402 inheritance);
4403 if (kr != KERN_SUCCESS) {
4404 DEBUG4K_ERROR("kr 0x%x\n", kr);
4405 if (target_copy_map != copy_map) {
4406 vm_map_copy_discard(target_copy_map);
4407 target_copy_map = VM_MAP_COPY_NULL;
4408 }
4409 named_entry_unlock(named_entry);
4410 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, kr);
4411 return kr;
4412 }
4413
4414 copy_addr = map_addr;
4415
4416 for (copy_entry = vm_map_copy_first_entry(target_copy_map);
4417 copy_entry != vm_map_copy_to_entry(target_copy_map);
4418 copy_entry = copy_entry->vme_next) {
4419 vm_map_t copy_submap = VM_MAP_NULL;
4420 vm_object_t copy_object = VM_OBJECT_NULL;
4421 vm_map_size_t copy_size;
4422 vm_object_offset_t copy_offset;
4423 boolean_t do_copy = false;
4424
4425 if (copy_entry->is_sub_map) {
4426 copy_submap = VME_SUBMAP(copy_entry);
4427 copy_object = (vm_object_t)copy_submap;
4428 } else {
4429 copy_object = VME_OBJECT(copy_entry);
4430 }
4431 copy_offset = VME_OFFSET(copy_entry);
4432 copy_size = (copy_entry->vme_end -
4433 copy_entry->vme_start);
4434
4435 /* sanity check */
4436 if ((copy_addr + copy_size) >
4437 (map_addr +
4438 overmap_start + overmap_end +
4439 named_entry->size /* XXX full size */)) {
4440 /* over-mapping too much !? */
4441 kr = KERN_INVALID_ARGUMENT;
4442 DEBUG4K_ERROR("kr 0x%x\n", kr);
4443 /* abort */
4444 break;
4445 }
4446
4447 /* take a reference on the object */
4448 if (copy_entry->is_sub_map) {
4449 vm_map_reference(copy_submap);
4450 } else {
4451 if (!copy &&
4452 copy_object != VM_OBJECT_NULL &&
4453 copy_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
4454 bool is_writable;
4455
4456 /*
4457 * We need to resolve our side of this
4458 * "symmetric" copy-on-write now; we
4459 * need a new object to map and share,
4460 * instead of the current one which
4461 * might still be shared with the
4462 * original mapping.
4463 *
4464 * Note: A "vm_map_copy_t" does not
4465 * have a lock but we're protected by
4466 * the named entry's lock here.
4467 */
4468 // assert(copy_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC);
4469 VME_OBJECT_SHADOW(copy_entry, copy_size, TRUE);
4470 assert(copy_object != VME_OBJECT(copy_entry));
4471 is_writable = false;
4472 if (copy_entry->protection & VM_PROT_WRITE) {
4473 is_writable = true;
4474#if __arm64e__
4475 } else if (copy_entry->used_for_tpro) {
4476 is_writable = true;
4477#endif /* __arm64e__ */
4478 }
4479 if (!copy_entry->needs_copy && is_writable) {
4480 vm_prot_t prot;
4481
4482 prot = copy_entry->protection & ~VM_PROT_WRITE;
4483 vm_object_pmap_protect(copy_object,
4484 copy_offset,
4485 copy_size,
4486 PMAP_NULL,
4487 PAGE_SIZE,
4488 0,
4489 prot);
4490 }
4491 copy_entry->needs_copy = FALSE;
4492 copy_entry->is_shared = TRUE;
4493 copy_object = VME_OBJECT(copy_entry);
4494 copy_offset = VME_OFFSET(copy_entry);
4495 vm_object_lock(copy_object);
4496 /* we're about to make a shared mapping of this object */
4497 copy_object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
4498 VM_OBJECT_SET_TRUE_SHARE(copy_object, TRUE);
4499 vm_object_unlock(copy_object);
4500 }
4501
4502 if (copy_object != VM_OBJECT_NULL &&
4503 copy_object->named &&
4504 copy_object->pager != MEMORY_OBJECT_NULL &&
4505 copy_object->copy_strategy != MEMORY_OBJECT_COPY_NONE) {
4506 memory_object_t pager;
4507 vm_prot_t pager_prot;
4508
4509 /*
4510 * For "named" VM objects, let the pager know that the
4511 * memory object is being mapped. Some pagers need to keep
4512 * track of this, to know when they can reclaim the memory
4513 * object, for example.
4514 * VM calls memory_object_map() for each mapping (specifying
4515 * the protection of each mapping) and calls
4516 * memory_object_last_unmap() when all the mappings are gone.
4517 */
4518 pager_prot = max_protection;
4519 if (copy) {
4520 /*
4521 * Copy-On-Write mapping: won't modify the
4522 * memory object.
4523 */
4524 pager_prot &= ~VM_PROT_WRITE;
4525 }
4526 vm_object_lock(copy_object);
4527 pager = copy_object->pager;
4528 if (copy_object->named &&
4529 pager != MEMORY_OBJECT_NULL &&
4530 copy_object->copy_strategy != MEMORY_OBJECT_COPY_NONE) {
4531 assert(copy_object->pager_ready);
4532 vm_object_mapping_wait(copy_object, THREAD_UNINT);
4533 /*
4534 * Object might have lost its pager
4535 * while waiting.
4536 */
4537 pager = copy_object->pager;
4538 if (copy_object->named &&
4539 pager != MEMORY_OBJECT_NULL) {
4540 vm_object_mapping_begin(copy_object);
4541 vm_object_unlock(copy_object);
4542
4543 kr = memory_object_map(pager, pager_prot);
4544 assert(kr == KERN_SUCCESS);
4545
4546 vm_object_lock(copy_object);
4547 vm_object_mapping_end(copy_object);
4548 }
4549 }
4550 vm_object_unlock(copy_object);
4551 }
4552
4553 /*
4554 * Perform the copy if requested
4555 */
4556
4557 if (copy && copy_object != VM_OBJECT_NULL) {
4558 vm_object_t new_object;
4559 vm_object_offset_t new_offset;
4560
4561 result = vm_object_copy_strategically(copy_object, copy_offset,
4562 copy_size,
4563 false, /* forking */
4564 &new_object, &new_offset,
4565 &do_copy);
4566
4567
4568 if (result == KERN_MEMORY_RESTART_COPY) {
4569 boolean_t success;
4570 boolean_t src_needs_copy;
4571
4572 /*
4573 * XXX
4574 * We currently ignore src_needs_copy.
4575 * This really is the issue of how to make
4576 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
4577 * non-kernel users to use. Solution forthcoming.
4578 * In the meantime, since we don't allow non-kernel
4579 * memory managers to specify symmetric copy,
4580 * we won't run into problems here.
4581 */
4582 new_object = copy_object;
4583 new_offset = copy_offset;
4584 success = vm_object_copy_quickly(new_object,
4585 new_offset,
4586 copy_size,
4587 &src_needs_copy,
4588 &do_copy);
4589 assert(success);
4590 result = KERN_SUCCESS;
4591 }
4592 if (result != KERN_SUCCESS) {
4593 kr = result;
4594 break;
4595 }
4596
4597 copy_object = new_object;
4598 copy_offset = new_offset;
4599 /*
4600 * No extra object reference for the mapping:
4601 * the mapping should be the only thing keeping
4602 * this new object alive.
4603 */
4604 } else {
4605 /*
4606 * We already have the right object
4607 * to map.
4608 */
4609 copy_object = VME_OBJECT(copy_entry);
4610 /* take an extra ref for the mapping below */
4611 vm_object_reference(copy_object);
4612 }
4613 }
4614
4615 /*
4616 * If the caller does not want a specific
4617 * tag for this new mapping: use
4618 * the tag of the original mapping.
4619 */
4620 vm_map_kernel_flags_t vmk_remap_flags = {
4621 .vmkf_submap = copy_entry->is_sub_map,
4622 };
4623
4624 vm_map_kernel_flags_set_vmflags(&vmk_remap_flags,
4625 vm_map_kernel_flags_vmflags(vmk_flags),
4626 vmk_flags.vm_tag ?: VME_ALIAS(copy_entry));
4627
4628 /* over-map the object into destination */
4629 vmk_remap_flags.vmf_fixed = true;
4630 vmk_remap_flags.vmf_overwrite = true;
4631
4632 if (!copy && !copy_entry->is_sub_map) {
4633 /*
4634 * copy-on-write should have been
4635 * resolved at this point, or we would
4636 * end up sharing instead of copying.
4637 */
4638 assert(!copy_entry->needs_copy);
4639 }
4640#if XNU_TARGET_OS_OSX
4641 if (copy_entry->used_for_jit) {
4642 vmk_remap_flags.vmkf_map_jit = TRUE;
4643 }
4644#endif /* XNU_TARGET_OS_OSX */
4645
4646 kr = vm_map_enter(target_map,
4647 ©_addr,
4648 copy_size,
4649 (vm_map_offset_t) 0,
4650 vmk_remap_flags,
4651 copy_object,
4652 copy_offset,
4653 ((copy_object == NULL)
4654 ? FALSE
4655 : (copy || copy_entry->needs_copy)),
4656 cur_protection,
4657 max_protection,
4658 inheritance);
4659 if (kr != KERN_SUCCESS) {
4660 DEBUG4K_SHARE("failed kr 0x%x\n", kr);
4661 if (copy_entry->is_sub_map) {
4662 vm_map_deallocate(copy_submap);
4663 } else {
4664 vm_object_deallocate(copy_object);
4665 }
4666 /* abort */
4667 break;
4668 }
4669
4670 /* next mapping */
4671 copy_addr += copy_size;
4672 }
4673
4674 named_entry_unlock(named_entry);
4675 if (target_copy_map != copy_map) {
4676 vm_map_copy_discard(target_copy_map);
4677 target_copy_map = VM_MAP_COPY_NULL;
4678 }
4679
4680 if (kr == KERN_SUCCESS) {
4681 if (overmap_start) {
4682 DEBUG4K_SHARE("map %p map_addr 0x%llx offset_in_mapping 0x%llx overmap_start 0x%llx -> *address 0x%llx\n", target_map, (uint64_t)map_addr, (uint64_t)offset_in_mapping, (uint64_t)overmap_start, (uint64_t)(map_addr + offset_in_mapping + overmap_start));
4683 }
4684 offset_in_mapping += overmap_start;
4685 } else if (!vmk_flags.vmf_overwrite) {
4686 /* deallocate the contiguous range */
4687 vm_map_remove(target_map, map_addr,
4688 map_addr + map_size);
4689 }
4690 result = kr;
4691 goto out;
4692 }
4693
4694 if (named_entry->is_object) {
4695 unsigned int access;
4696 unsigned int wimg_mode;
4697
4698 assert(!named_entry->is_copy);
4699 assert(!named_entry->is_sub_map);
4700
4701 /* we are mapping a VM object */
4702
4703 access = named_entry->access;
4704
4705 if (vmk_flags.vmf_return_data_addr ||
4706 vmk_flags.vmf_return_4k_data_addr) {
4707 offset_in_mapping = obj_offs & map_mask;
4708 if (vmk_flags.vmf_return_4k_data_addr) {
4709 offset_in_mapping &= ~((signed)(0xFFF));
4710 }
4711 obj_offs -= offset_in_mapping;
4712 map_size = vm_map_round_page(initial_size +
4713 offset_in_mapping, map_mask);
4714 }
4715
4716 object = vm_named_entry_to_vm_object(named_entry);
4717 assert(object != VM_OBJECT_NULL);
4718 vm_object_lock(object);
4719 named_entry_unlock(named_entry);
4720
4721 wimg_mode = object->wimg_bits;
4722 vm_prot_to_wimg(access, &wimg_mode);
4723 if (object->wimg_bits != wimg_mode) {
4724 vm_object_change_wimg_mode(object, wimg_mode);
4725 }
4726
4727 vm_object_reference_locked(object);
4728 vm_object_unlock(object);
4729 } else {
4730 panic("invalid VM named entry %p", named_entry);
4731 }
4732 } else if (ip_type(port) == IKOT_MEMORY_OBJECT) {
4733 /*
4734 * JMM - This is temporary until we unify named entries
4735 * and raw memory objects.
4736 *
4737 * Detected fake object type for a memory object. In
4738 * this case, the port isn't really a port at all, but
4739 * instead is just a raw memory object.
4740 */
4741 if (vmk_flags.vmf_return_data_addr ||
4742 vmk_flags.vmf_return_4k_data_addr) {
4743 panic("VM_FLAGS_RETURN_DATA_ADDR not expected for raw memory object.");
4744 }
4745
4746 object = memory_object_to_vm_object((memory_object_t)port);
4747 if (object == VM_OBJECT_NULL) {
4748 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_OBJECT);
4749 return KERN_INVALID_OBJECT;
4750 }
4751 vm_object_reference(object);
4752
4753 /* wait for object (if any) to be ready */
4754 if (object != VM_OBJECT_NULL) {
4755 if (is_kernel_object(object)) {
4756 printf("Warning: Attempt to map kernel object"
4757 " by a non-private kernel entity\n");
4758 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_OBJECT);
4759 return KERN_INVALID_OBJECT;
4760 }
4761 if (!object->pager_ready) {
4762 vm_object_lock(object);
4763
4764 while (!object->pager_ready) {
4765 vm_object_sleep(object,
4766 VM_OBJECT_EVENT_PAGER_READY,
4767 THREAD_UNINT,
4768 LCK_SLEEP_EXCLUSIVE);
4769 }
4770 vm_object_unlock(object);
4771 }
4772 }
4773 } else {
4774 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, KERN_INVALID_OBJECT);
4775 return KERN_INVALID_OBJECT;
4776 }
4777
4778 if (object != VM_OBJECT_NULL &&
4779 object->named &&
4780 object->pager != MEMORY_OBJECT_NULL &&
4781 object->copy_strategy != MEMORY_OBJECT_COPY_NONE) {
4782 memory_object_t pager;
4783 vm_prot_t pager_prot;
4784 kern_return_t kr;
4785
4786 /*
4787 * For "named" VM objects, let the pager know that the
4788 * memory object is being mapped. Some pagers need to keep
4789 * track of this, to know when they can reclaim the memory
4790 * object, for example.
4791 * VM calls memory_object_map() for each mapping (specifying
4792 * the protection of each mapping) and calls
4793 * memory_object_last_unmap() when all the mappings are gone.
4794 */
4795 pager_prot = max_protection;
4796 if (copy) {
4797 /*
4798 * Copy-On-Write mapping: won't modify the
4799 * memory object.
4800 */
4801 pager_prot &= ~VM_PROT_WRITE;
4802 }
4803 vm_object_lock(object);
4804 pager = object->pager;
4805 if (object->named &&
4806 pager != MEMORY_OBJECT_NULL &&
4807 object->copy_strategy != MEMORY_OBJECT_COPY_NONE) {
4808 assert(object->pager_ready);
4809 vm_object_mapping_wait(object, THREAD_UNINT);
4810 /* object might have lost its pager while waiting */
4811 pager = object->pager;
4812 if (object->named && pager != MEMORY_OBJECT_NULL) {
4813 vm_object_mapping_begin(object);
4814 vm_object_unlock(object);
4815
4816 kr = memory_object_map(pager, pager_prot);
4817 assert(kr == KERN_SUCCESS);
4818
4819 vm_object_lock(object);
4820 vm_object_mapping_end(object);
4821 }
4822 }
4823 vm_object_unlock(object);
4824 }
4825
4826 /*
4827 * Perform the copy if requested
4828 */
4829
4830 if (copy) {
4831 vm_object_t new_object;
4832 vm_object_offset_t new_offset;
4833
4834 result = vm_object_copy_strategically(object,
4835 obj_offs,
4836 map_size,
4837 false, /* forking */
4838 &new_object, &new_offset,
4839 ©);
4840
4841
4842 if (result == KERN_MEMORY_RESTART_COPY) {
4843 boolean_t success;
4844 boolean_t src_needs_copy;
4845
4846 /*
4847 * XXX
4848 * We currently ignore src_needs_copy.
4849 * This really is the issue of how to make
4850 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
4851 * non-kernel users to use. Solution forthcoming.
4852 * In the meantime, since we don't allow non-kernel
4853 * memory managers to specify symmetric copy,
4854 * we won't run into problems here.
4855 */
4856 new_object = object;
4857 new_offset = obj_offs;
4858 success = vm_object_copy_quickly(new_object,
4859 new_offset,
4860 map_size,
4861 &src_needs_copy,
4862 ©);
4863 assert(success);
4864 result = KERN_SUCCESS;
4865 }
4866 /*
4867 * Throw away the reference to the
4868 * original object, as it won't be mapped.
4869 */
4870
4871 vm_object_deallocate(object);
4872
4873 if (result != KERN_SUCCESS) {
4874 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, result);
4875 return result;
4876 }
4877
4878 object = new_object;
4879 obj_offs = new_offset;
4880 }
4881
4882 /*
4883 * If non-kernel users want to try to prefault pages, the mapping and prefault
4884 * needs to be atomic.
4885 */
4886 kernel_prefault = (try_prefault && vm_kernel_map_is_kernel(target_map));
4887 vmk_flags.vmkf_keep_map_locked = (try_prefault && !kernel_prefault);
4888
4889 if (try_prefault) {
4890 /* take an extra reference to keep object alive during "prefault" */
4891 vm_object_reference(object);
4892 }
4893
4894 result = vm_map_enter(target_map,
4895 &map_addr, map_size,
4896 (vm_map_offset_t)mask,
4897 vmk_flags,
4898 object, obj_offs,
4899 copy,
4900 cur_protection, max_protection,
4901 inheritance);
4902 if (result != KERN_SUCCESS) {
4903 vm_object_deallocate(object);
4904 }
4905
4906 /*
4907 * Try to prefault, and do not forget to release the vm map lock.
4908 */
4909 if (result == KERN_SUCCESS && try_prefault) {
4910 mach_vm_address_t va = map_addr;
4911 vm_object_offset_t page_offset;
4912 kern_return_t kr = KERN_SUCCESS;
4913 unsigned int i = 0;
4914 int pmap_options;
4915
4916 pmap_options = kernel_prefault ? 0 : PMAP_OPTIONS_NOWAIT;
4917
4918 vm_object_lock(object);
4919 page_offset = obj_offs;
4920 for (i = 0; i < page_list_count; ++i) {
4921 if (!UPL_VALID_PAGE(page_list, i)) {
4922 if (kernel_prefault) {
4923 assertf(FALSE, "kernel_prefault && !UPL_VALID_PAGE");
4924 result = KERN_MEMORY_ERROR;
4925 break;
4926 }
4927 } else {
4928 if (object->phys_contiguous) {
4929 /* no VM page to look up... */
4930 } else {
4931 vm_page_t p;
4932
4933 p = vm_page_lookup(object, page_offset);
4934 assertf(p, "offset 0x%llx: no VM page", page_offset);
4935 if (p == VM_PAGE_NULL) {
4936 /*
4937 * No VM page , so nothing to prefault.
4938 * Note that this should not happen if
4939 * we really had the page in the UPL,
4940 * so let's give up on prefaulting...
4941 */
4942 vm_prefault_nb_no_page++;
4943 break;
4944 } else if (VM_PAGE_GET_PHYS_PAGE(p) !=
4945 UPL_PHYS_PAGE(page_list, i)) {
4946 /*
4947 * Different physical page; that should
4948 * also not happen, so let's give up...
4949 */
4950 assertf(VM_PAGE_GET_PHYS_PAGE(p) == UPL_PHYS_PAGE(page_list, i),
4951 "offset 0x%llx: page %p phys 0x%x != 0x%x\n",
4952 page_offset, p,
4953 VM_PAGE_GET_PHYS_PAGE(p),
4954 UPL_PHYS_PAGE(page_list, i));
4955 vm_prefault_nb_wrong_page++;
4956 break;
4957 } else {
4958 /*
4959 * Register that this VM page was pmapped,
4960 * so that we know to clean up its pmap
4961 * mappings if we end up reclaiming it
4962 * before this mapping goes away...
4963 */
4964 if (!p->vmp_pmapped) {
4965 p->vmp_pmapped = true;
4966 }
4967 }
4968 }
4969 /*
4970 * If this function call failed, we should stop
4971 * trying to optimize, other calls are likely
4972 * going to fail too.
4973 *
4974 * We are not gonna report an error for such
4975 * failure though. That's an optimization, not
4976 * something critical.
4977 */
4978 kr = pmap_enter_object_options_check(target_map->pmap,
4979 va, 0, object, UPL_PHYS_PAGE(page_list, i),
4980 cur_protection, VM_PROT_NONE,
4981 TRUE, pmap_options);
4982 if (kr != KERN_SUCCESS) {
4983 OSIncrementAtomic64(&vm_prefault_nb_bailout);
4984 if (kernel_prefault) {
4985 result = kr;
4986 }
4987 break;
4988 }
4989 OSIncrementAtomic64(&vm_prefault_nb_pages);
4990 }
4991
4992 /* Next virtual address */
4993 va += PAGE_SIZE;
4994 page_offset += PAGE_SIZE;
4995 }
4996 vm_object_unlock(object);
4997 if (vmk_flags.vmkf_keep_map_locked) {
4998 vm_map_unlock(target_map);
4999 }
5000 }
5001
5002 if (try_prefault) {
5003 /* release our extra "prefault" reference */
5004 vm_object_deallocate(object);
5005 }
5006
5007out:
5008 if (result == KERN_SUCCESS) {
5009#if KASAN
5010 if (target_map->pmap == kernel_pmap) {
5011 kasan_notify_address(map_addr, map_size);
5012 }
5013#endif
5014 *address_u = vm_sanitize_wrap_addr(map_addr + offset_in_mapping);
5015 vmlp_range_event(target_map, map_addr, map_size);
5016 }
5017 vmlp_api_end(VM_MAP_ENTER_MEM_OBJECT, result);
5018 return result;
5019}
5020
5021kern_return_t
5022vm_map_enter_mem_object_prefault(
5023 vm_map_t target_map,
5024 vm_map_offset_ut *address,
5025 vm_map_size_ut initial_size,
5026 vm_map_offset_ut mask,
5027 vm_map_kernel_flags_t vmk_flags,
5028 ipc_port_t port,
5029 vm_object_offset_ut offset,
5030 vm_prot_ut cur_protection,
5031 vm_prot_ut max_protection,
5032 upl_page_list_ptr_t page_list,
5033 unsigned int page_list_count)
5034{
5035 /* range_id is set by vm_map_enter_mem_object */
5036 return vm_map_enter_mem_object(target_map,
5037 address,
5038 initial_size,
5039 mask,
5040 vmk_flags,
5041 port,
5042 offset,
5043 FALSE,
5044 cur_protection,
5045 max_protection,
5046 VM_INHERIT_DEFAULT,
5047 page_list,
5048 page_list_count);
5049}
5050
5051static __attribute__((always_inline, warn_unused_result))
5052kern_return_t
5053vm_map_enter_mem_object_control_sanitize(
5054 vm_map_t target_map,
5055 vm_map_offset_ut address_u,
5056 vm_map_size_ut initial_size_u,
5057 vm_map_offset_ut mask_u,
5058 vm_object_offset_ut offset_u,
5059 vm_prot_ut cur_protection_u,
5060 vm_prot_ut max_protection_u,
5061 vm_inherit_ut inheritance_u,
5062 vm_map_kernel_flags_t vmk_flags,
5063 vm_map_address_t *map_addr,
5064 vm_map_size_t *map_size,
5065 vm_map_offset_t *mask,
5066 vm_object_offset_t *obj_offs,
5067 vm_object_offset_t *obj_end,
5068 vm_object_size_t *obj_size,
5069 vm_prot_t *cur_protection,
5070 vm_prot_t *max_protection,
5071 vm_inherit_t *inheritance)
5072{
5073 kern_return_t kr;
5074
5075 kr = vm_sanitize_cur_and_max_prots(cur_protection_u, max_protection_u,
5076 VM_SANITIZE_CALLER_ENTER_MEM_OBJ_CTL, target_map,
5077 cur_protection, max_protection);
5078 if (__improbable(kr != KERN_SUCCESS)) {
5079 return kr;
5080 }
5081
5082 kr = vm_sanitize_inherit(inheritance_u, VM_SANITIZE_CALLER_ENTER_MEM_OBJ_CTL,
5083 inheritance);
5084 if (__improbable(kr != KERN_SUCCESS)) {
5085 return kr;
5086 }
5087
5088 kr = vm_sanitize_mask(mask_u, VM_SANITIZE_CALLER_ENTER_MEM_OBJ_CTL, mask);
5089 if (__improbable(kr != KERN_SUCCESS)) {
5090 return kr;
5091 }
5092 /*
5093 * Ensure arithmetic doesn't overflow in vm_object space (kernel
5094 * pages).
5095 * We keep unaligned values for now. The call we eventually make to
5096 * vm_map_enter does guarantee that offset_u is page aligned for EITHER
5097 * target_map pages or kernel pages. But this isn't enough to guarantee
5098 * kernel space alignment.
5099 */
5100 kr = vm_sanitize_addr_size(offset_u, initial_size_u,
5101 VM_SANITIZE_CALLER_ENTER_MEM_OBJ_CTL, PAGE_MASK,
5102 VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS |
5103 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES,
5104 obj_offs, obj_end, obj_size);
5105 if (__improbable(kr != KERN_SUCCESS)) {
5106 return kr;
5107 }
5108
5109 /*
5110 * There is no vm_sanitize_addr_size variant that also adjusts for
5111 * a separate offset. Rather than create one for this one-off issue,
5112 * we sanitize map_addr and map_size individually, relying on
5113 * vm_sanitize_size to incorporate the offset. Then, we perform the
5114 * overflow check manually below.
5115 */
5116 *map_addr = vm_sanitize_addr(target_map, address_u);
5117 kr = vm_sanitize_size(offset_u, initial_size_u,
5118 VM_SANITIZE_CALLER_ENTER_MEM_OBJ_CTL, target_map,
5119 VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS, map_size);
5120 if (__improbable(kr != KERN_SUCCESS)) {
5121 return kr;
5122 }
5123
5124 /*
5125 * Ensure arithmetic doesn't overflow in target_map space.
5126 * The computation of map_size above accounts for the possibility that
5127 * offset_u might be unaligned in target_map space.
5128 */
5129 if (vmk_flags.vmf_fixed) {
5130 vm_map_address_t map_end;
5131
5132 if (__improbable(os_add_overflow(*map_addr, *map_size, &map_end))) {
5133 return KERN_INVALID_ARGUMENT;
5134 }
5135 }
5136
5137 return KERN_SUCCESS;
5138}
5139
5140kern_return_t
5141vm_map_enter_mem_object_control(
5142 vm_map_t target_map,
5143 vm_map_offset_ut *address_u,
5144 vm_map_size_ut initial_size_u,
5145 vm_map_offset_ut mask_u,
5146 vm_map_kernel_flags_t vmk_flags,
5147 memory_object_control_t control,
5148 vm_object_offset_ut offset_u,
5149 boolean_t needs_copy,
5150 vm_prot_ut cur_protection_u,
5151 vm_prot_ut max_protection_u,
5152 vm_inherit_ut inheritance_u)
5153{
5154 vm_map_offset_t mask;
5155 vm_prot_t cur_protection;
5156 vm_prot_t max_protection;
5157 vm_inherit_t inheritance;
5158 vm_map_address_t map_addr;
5159 vm_map_size_t map_size;
5160 vm_object_t object;
5161 vm_object_offset_t obj_offs, obj_end;
5162 vm_object_size_t obj_size;
5163 kern_return_t result;
5164 memory_object_t pager;
5165 vm_prot_t pager_prot;
5166 kern_return_t kr;
5167
5168 /*
5169 * Check arguments for validity
5170 */
5171 if (target_map == VM_MAP_NULL) {
5172 return KERN_INVALID_ARGUMENT;
5173 }
5174
5175 /*
5176 * We only support vmf_return_data_addr-like behavior.
5177 */
5178 vmk_flags.vmf_return_data_addr = true;
5179
5180 /*
5181 * Sanitize any input parameters that are addr/size/prot/inherit
5182 */
5183 kr = vm_map_enter_mem_object_control_sanitize(target_map,
5184 *address_u,
5185 initial_size_u,
5186 mask_u,
5187 offset_u,
5188 cur_protection_u,
5189 max_protection_u,
5190 inheritance_u,
5191 vmk_flags,
5192 &map_addr,
5193 &map_size,
5194 &mask,
5195 &obj_offs,
5196 &obj_end,
5197 &obj_size,
5198 &cur_protection,
5199 &max_protection,
5200 &inheritance);
5201 if (__improbable(kr != KERN_SUCCESS)) {
5202 return vm_sanitize_get_kr(kr);
5203 }
5204
5205 object = memory_object_control_to_vm_object(control);
5206
5207 if (object == VM_OBJECT_NULL) {
5208 return KERN_INVALID_OBJECT;
5209 }
5210
5211 if (is_kernel_object(object)) {
5212 printf("Warning: Attempt to map kernel object"
5213 " by a non-private kernel entity\n");
5214 return KERN_INVALID_OBJECT;
5215 }
5216
5217 vm_object_lock(object);
5218 os_ref_retain_locked_raw(&object->ref_count, &vm_object_refgrp);
5219
5220
5221 /*
5222 * For "named" VM objects, let the pager know that the
5223 * memory object is being mapped. Some pagers need to keep
5224 * track of this, to know when they can reclaim the memory
5225 * object, for example.
5226 * VM calls memory_object_map() for each mapping (specifying
5227 * the protection of each mapping) and calls
5228 * memory_object_last_unmap() when all the mappings are gone.
5229 */
5230 pager_prot = max_protection;
5231 if (needs_copy) {
5232 pager_prot &= ~VM_PROT_WRITE;
5233 }
5234 pager = object->pager;
5235 if (object->named &&
5236 pager != MEMORY_OBJECT_NULL &&
5237 object->copy_strategy != MEMORY_OBJECT_COPY_NONE) {
5238 assert(object->pager_ready);
5239 vm_object_mapping_wait(object, THREAD_UNINT);
5240 /* object might have lost its pager while waiting */
5241 pager = object->pager;
5242 if (object->named && pager != MEMORY_OBJECT_NULL) {
5243 vm_object_mapping_begin(object);
5244 vm_object_unlock(object);
5245
5246 kr = memory_object_map(pager, pager_prot);
5247 assert(kr == KERN_SUCCESS);
5248
5249 vm_object_lock(object);
5250 vm_object_mapping_end(object);
5251 }
5252 }
5253 vm_object_unlock(object);
5254
5255 /*
5256 * Perform the copy if requested
5257 */
5258
5259 if (needs_copy) {
5260 vm_object_t new_object;
5261 vm_object_offset_t new_offset;
5262
5263 result = vm_object_copy_strategically(object, obj_offs, obj_size,
5264 false, /* forking */
5265 &new_object, &new_offset,
5266 &needs_copy);
5267
5268
5269 if (result == KERN_MEMORY_RESTART_COPY) {
5270 boolean_t success;
5271 boolean_t src_needs_copy;
5272
5273 /*
5274 * XXX
5275 * We currently ignore src_needs_copy.
5276 * This really is the issue of how to make
5277 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
5278 * non-kernel users to use. Solution forthcoming.
5279 * In the meantime, since we don't allow non-kernel
5280 * memory managers to specify symmetric copy,
5281 * we won't run into problems here.
5282 */
5283 new_object = object;
5284 new_offset = obj_offs;
5285 success = vm_object_copy_quickly(new_object,
5286 new_offset, obj_size,
5287 &src_needs_copy,
5288 &needs_copy);
5289 assert(success);
5290 result = KERN_SUCCESS;
5291 }
5292 /*
5293 * Throw away the reference to the
5294 * original object, as it won't be mapped.
5295 */
5296
5297 vm_object_deallocate(object);
5298
5299 if (result != KERN_SUCCESS) {
5300 return result;
5301 }
5302
5303 object = new_object;
5304 obj_offs = new_offset;
5305 }
5306
5307 result = vm_map_enter(target_map,
5308 &map_addr, map_size,
5309 (vm_map_offset_t)mask,
5310 vmk_flags,
5311 object,
5312 obj_offs,
5313 needs_copy,
5314 cur_protection, max_protection,
5315 inheritance);
5316
5317 if (result == KERN_SUCCESS) {
5318 *address_u = vm_sanitize_wrap_addr(
5319 map_addr + (obj_offs & vm_map_page_mask(target_map)));
5320 } else {
5321 vm_object_deallocate(object);
5322 }
5323
5324 return result;
5325}
5326
5327
5328/* Not used without nested pmaps */
5329#ifndef NO_NESTED_PMAP
5330/*
5331 * Clip and unnest a portion of a nested submap mapping.
5332 */
5333
5334
5335static void
5336vm_map_clip_unnest(
5337 vm_map_t map,
5338 vm_map_entry_t entry,
5339 vm_map_offset_t start_unnest,
5340 vm_map_offset_t end_unnest)
5341{
5342 vm_map_offset_t old_start_unnest = start_unnest;
5343 vm_map_offset_t old_end_unnest = end_unnest;
5344
5345 assert(entry->is_sub_map);
5346 assert(VME_SUBMAP(entry) != NULL);
5347 assert(entry->use_pmap);
5348
5349 /*
5350 * Query the platform for the optimal unnest range.
5351 * DRK: There's some duplication of effort here, since
5352 * callers may have adjusted the range to some extent. This
5353 * routine was introduced to support 1GiB subtree nesting
5354 * for x86 platforms, which can also nest on 2MiB boundaries
5355 * depending on size/alignment.
5356 */
5357 if (pmap_adjust_unnest_parameters(map->pmap, &start_unnest, &end_unnest)) {
5358 assert(VME_SUBMAP(entry)->is_nested_map);
5359 assert(!VME_SUBMAP(entry)->disable_vmentry_reuse);
5360 log_unnest_badness(map,
5361 old_start_unnest,
5362 old_end_unnest,
5363 VME_SUBMAP(entry)->is_nested_map,
5364 (entry->vme_start +
5365 VME_SUBMAP(entry)->lowest_unnestable_start -
5366 VME_OFFSET(entry)));
5367 }
5368
5369 if (entry->vme_start > start_unnest ||
5370 entry->vme_end < end_unnest) {
5371 panic("vm_map_clip_unnest(0x%llx,0x%llx): "
5372 "bad nested entry: start=0x%llx end=0x%llx\n",
5373 (long long)start_unnest, (long long)end_unnest,
5374 (long long)entry->vme_start, (long long)entry->vme_end);
5375 }
5376
5377 if (start_unnest > entry->vme_start) {
5378 _vm_map_clip_start(&map->hdr,
5379 entry,
5380 start_unnest);
5381 if (map->holelistenabled) {
5382 vm_map_store_update_first_free(map, NULL, FALSE);
5383 } else {
5384 vm_map_store_update_first_free(map, map->first_free, FALSE);
5385 }
5386 }
5387 if (entry->vme_end > end_unnest) {
5388 _vm_map_clip_end(&map->hdr,
5389 entry,
5390 end_unnest);
5391 if (map->holelistenabled) {
5392 vm_map_store_update_first_free(map, NULL, FALSE);
5393 } else {
5394 vm_map_store_update_first_free(map, map->first_free, FALSE);
5395 }
5396 }
5397
5398 pmap_unnest(map->pmap,
5399 entry->vme_start,
5400 entry->vme_end - entry->vme_start);
5401 if ((map->mapped_in_other_pmaps) && os_ref_get_count_raw(&map->map_refcnt) != 0) {
5402 /* clean up parent map/maps */
5403 vm_map_submap_pmap_clean(
5404 map, entry->vme_start,
5405 entry->vme_end,
5406 VME_SUBMAP(entry),
5407 VME_OFFSET(entry));
5408 }
5409 entry->use_pmap = FALSE;
5410 if ((map->pmap != kernel_pmap) &&
5411 (VME_ALIAS(entry) == VM_MEMORY_SHARED_PMAP)) {
5412 VME_ALIAS_SET(entry, VM_MEMORY_UNSHARED_PMAP);
5413 }
5414}
5415#endif /* NO_NESTED_PMAP */
5416
5417__abortlike
5418static void
5419__vm_map_clip_atomic_entry_panic(
5420 vm_map_t map,
5421 vm_map_entry_t entry,
5422 vm_map_offset_t where)
5423{
5424 panic("vm_map_clip(%p): Attempting to clip an atomic VM map entry "
5425 "%p [0x%llx:0x%llx] at 0x%llx", map, entry,
5426 (uint64_t)entry->vme_start,
5427 (uint64_t)entry->vme_end,
5428 (uint64_t)where);
5429}
5430
5431__abortlike
5432static void
5433__vm_map_clip_sealed_panic(
5434 vm_map_t map,
5435 vm_map_entry_t entry,
5436 vm_map_offset_t where)
5437{
5438 panic("vm_map_clip(%p): Attempting to clip in a sealed VM map "
5439 "%p [0x%llx:0x%llx] at 0x%llx", map, entry,
5440 (uint64_t)entry->vme_start,
5441 (uint64_t)entry->vme_end,
5442 (uint64_t)where);
5443}
5444
5445/*
5446 * vm_map_clip_start: [ internal use only ]
5447 *
5448 * Asserts that the given entry begins at or after
5449 * the specified address; if necessary,
5450 * it splits the entry into two.
5451 */
5452void
5453vm_map_clip_start(
5454 vm_map_t map,
5455 vm_map_entry_t entry,
5456 vm_map_offset_t startaddr)
5457{
5458 if (__improbable(vm_map_is_sealed(map))) {
5459 __vm_map_clip_sealed_panic(map, entry, startaddr);
5460 }
5461
5462#ifndef NO_NESTED_PMAP
5463 if (entry->is_sub_map &&
5464 entry->use_pmap &&
5465 startaddr >= entry->vme_start) {
5466 vm_map_offset_t start_unnest, end_unnest;
5467
5468 /*
5469 * Make sure "startaddr" is no longer in a nested range
5470 * before we clip. Unnest only the minimum range the platform
5471 * can handle.
5472 * vm_map_clip_unnest may perform additional adjustments to
5473 * the unnest range.
5474 */
5475 start_unnest = startaddr & ~(pmap_shared_region_size_min(map->pmap) - 1);
5476 end_unnest = start_unnest + pmap_shared_region_size_min(map->pmap);
5477 vm_map_clip_unnest(map, entry, start_unnest, end_unnest);
5478 }
5479#endif /* NO_NESTED_PMAP */
5480 if (startaddr > entry->vme_start) {
5481 if (!entry->is_sub_map &&
5482 VME_OBJECT(entry) &&
5483 VME_OBJECT(entry)->phys_contiguous) {
5484 pmap_remove(map->pmap,
5485 (addr64_t)(entry->vme_start),
5486 (addr64_t)(entry->vme_end));
5487 }
5488 if (entry->vme_atomic) {
5489 __vm_map_clip_atomic_entry_panic(map, entry, startaddr);
5490 }
5491
5492 DTRACE_VM5(
5493 vm_map_clip_start,
5494 vm_map_t, map,
5495 vm_map_offset_t, entry->vme_start,
5496 vm_map_offset_t, entry->vme_end,
5497 vm_map_offset_t, startaddr,
5498 int, VME_ALIAS(entry));
5499
5500 _vm_map_clip_start(&map->hdr, entry, startaddr);
5501 if (map->holelistenabled) {
5502 vm_map_store_update_first_free(map, NULL, FALSE);
5503 } else {
5504 vm_map_store_update_first_free(map, map->first_free, FALSE);
5505 }
5506 }
5507}
5508
5509
5510#define vm_map_copy_clip_start(copy, entry, startaddr) \
5511 MACRO_BEGIN \
5512 if ((startaddr) > (entry)->vme_start) \
5513 _vm_map_clip_start(&(copy)->cpy_hdr,(entry),(startaddr)); \
5514 MACRO_END
5515
5516/*
5517 * This routine is called only when it is known that
5518 * the entry must be split.
5519 */
5520static void
5521_vm_map_clip_start(
5522 struct vm_map_header *map_header,
5523 vm_map_entry_t entry,
5524 vm_map_offset_t start)
5525{
5526 vm_map_entry_t new_entry;
5527
5528 /*
5529 * Split off the front portion --
5530 * note that we must insert the new
5531 * entry BEFORE this one, so that
5532 * this entry has the specified starting
5533 * address.
5534 */
5535 assert(VM_MAP_PAGE_ALIGNED(start, VM_MAP_HDR_PAGE_MASK(map_header)));
5536
5537 new_entry = _vm_map_entry_create(map_header);
5538 vm_map_entry_copy_full(new_entry, entry);
5539
5540 new_entry->vme_end = start;
5541 assert(new_entry->vme_start < new_entry->vme_end);
5542 VME_OFFSET_SET(entry, VME_OFFSET(entry) + (start - entry->vme_start));
5543 if (__improbable(start >= entry->vme_end)) {
5544 panic("mapHdr %p entry %p start 0x%llx end 0x%llx new start 0x%llx", map_header, entry, entry->vme_start, entry->vme_end, start);
5545 }
5546 assert(start < entry->vme_end);
5547 entry->vme_start = start;
5548
5549 _vm_map_store_entry_link(map_header, VME_PREV(entry), new_entry);
5550
5551 if (entry->is_sub_map) {
5552 vm_map_reference(VME_SUBMAP(new_entry));
5553 } else {
5554 vm_object_reference(VME_OBJECT(new_entry));
5555 }
5556}
5557
5558
5559/*
5560 * vm_map_clip_end: [ internal use only ]
5561 *
5562 * Asserts that the given entry ends at or before
5563 * the specified address; if necessary,
5564 * it splits the entry into two.
5565 */
5566void
5567vm_map_clip_end(
5568 vm_map_t map,
5569 vm_map_entry_t entry,
5570 vm_map_offset_t endaddr)
5571{
5572 if (__improbable(vm_map_is_sealed(map))) {
5573 __vm_map_clip_sealed_panic(map, entry, endaddr);
5574 }
5575
5576 if (endaddr > entry->vme_end) {
5577 /*
5578 * Within the scope of this clipping, limit "endaddr" to
5579 * the end of this map entry...
5580 */
5581 endaddr = entry->vme_end;
5582 }
5583#ifndef NO_NESTED_PMAP
5584 if (entry->is_sub_map && entry->use_pmap) {
5585 vm_map_offset_t start_unnest, end_unnest;
5586
5587 /*
5588 * Make sure the range between the start of this entry and
5589 * the new "endaddr" is no longer nested before we clip.
5590 * Unnest only the minimum range the platform can handle.
5591 * vm_map_clip_unnest may perform additional adjustments to
5592 * the unnest range.
5593 */
5594 start_unnest = entry->vme_start;
5595 end_unnest =
5596 (endaddr + pmap_shared_region_size_min(map->pmap) - 1) &
5597 ~(pmap_shared_region_size_min(map->pmap) - 1);
5598 vm_map_clip_unnest(map, entry, start_unnest, end_unnest);
5599 }
5600#endif /* NO_NESTED_PMAP */
5601 if (endaddr < entry->vme_end) {
5602 if (!entry->is_sub_map &&
5603 VME_OBJECT(entry) &&
5604 VME_OBJECT(entry)->phys_contiguous) {
5605 pmap_remove(map->pmap,
5606 (addr64_t)(entry->vme_start),
5607 (addr64_t)(entry->vme_end));
5608 }
5609 if (entry->vme_atomic) {
5610 __vm_map_clip_atomic_entry_panic(map, entry, endaddr);
5611 }
5612 DTRACE_VM5(
5613 vm_map_clip_end,
5614 vm_map_t, map,
5615 vm_map_offset_t, entry->vme_start,
5616 vm_map_offset_t, entry->vme_end,
5617 vm_map_offset_t, endaddr,
5618 int, VME_ALIAS(entry));
5619
5620 _vm_map_clip_end(&map->hdr, entry, endaddr);
5621 if (map->holelistenabled) {
5622 vm_map_store_update_first_free(map, NULL, FALSE);
5623 } else {
5624 vm_map_store_update_first_free(map, map->first_free, FALSE);
5625 }
5626 }
5627}
5628
5629
5630#define vm_map_copy_clip_end(copy, entry, endaddr) \
5631 MACRO_BEGIN \
5632 if ((endaddr) < (entry)->vme_end) \
5633 _vm_map_clip_end(&(copy)->cpy_hdr,(entry),(endaddr)); \
5634 MACRO_END
5635
5636/*
5637 * This routine is called only when it is known that
5638 * the entry must be split.
5639 */
5640static void
5641_vm_map_clip_end(
5642 struct vm_map_header *map_header,
5643 vm_map_entry_t entry,
5644 vm_map_offset_t end)
5645{
5646 vm_map_entry_t new_entry;
5647
5648 /*
5649 * Create a new entry and insert it
5650 * AFTER the specified entry
5651 */
5652
5653 assert(VM_MAP_PAGE_ALIGNED(end, VM_MAP_HDR_PAGE_MASK(map_header)));
5654
5655 new_entry = _vm_map_entry_create(map_header);
5656 vm_map_entry_copy_full(new_entry, entry);
5657
5658 if (__improbable(end <= entry->vme_start)) {
5659 panic("mapHdr %p entry %p start 0x%llx end 0x%llx new end 0x%llx", map_header, entry, entry->vme_start, entry->vme_end, end);
5660 }
5661 assert(entry->vme_start < end);
5662 new_entry->vme_start = entry->vme_end = end;
5663 VME_OFFSET_SET(new_entry,
5664 VME_OFFSET(new_entry) + (end - entry->vme_start));
5665 assert(new_entry->vme_start < new_entry->vme_end);
5666
5667 _vm_map_store_entry_link(map_header, entry, new_entry);
5668
5669 if (entry->is_sub_map) {
5670 vm_map_reference(VME_SUBMAP(new_entry));
5671 } else {
5672 vm_object_reference(VME_OBJECT(new_entry));
5673 }
5674}
5675
5676
5677/*
5678 * VM_MAP_RANGE_CHECK: [ internal use only ]
5679 *
5680 * Asserts that the starting and ending region
5681 * addresses fall within the valid range of the map.
5682 */
5683#define VM_MAP_RANGE_CHECK(map, start, end) \
5684 MACRO_BEGIN \
5685 if (start < vm_map_min(map)) \
5686 start = vm_map_min(map); \
5687 if (end > vm_map_max(map)) \
5688 end = vm_map_max(map); \
5689 if (start > end) \
5690 start = end; \
5691 MACRO_END
5692
5693/*
5694 * vm_map_range_check: [ internal use only ]
5695 *
5696 * Check that the region defined by the specified start and
5697 * end addresses are wholly contained within a single map
5698 * entry or set of adjacent map entries of the spacified map,
5699 * i.e. the specified region contains no unmapped space.
5700 * If any or all of the region is unmapped, FALSE is returned.
5701 * Otherwise, TRUE is returned and if the output argument 'entry'
5702 * is not NULL it points to the map entry containing the start
5703 * of the region.
5704 *
5705 * The map is locked for reading on entry and is left locked.
5706 */
5707static boolean_t
5708vm_map_range_check(
5709 vm_map_t map,
5710 vm_map_offset_t start,
5711 vm_map_offset_t end,
5712 vm_map_entry_t *entry)
5713{
5714 vm_map_entry_t cur;
5715 vm_map_offset_t prev;
5716
5717 /*
5718 * Basic sanity checks first
5719 */
5720 if (start < vm_map_min(map) || end > vm_map_max(map) || start > end) {
5721 return FALSE;
5722 }
5723
5724 /*
5725 * Check first if the region starts within a valid
5726 * mapping for the map.
5727 */
5728 if (!vm_map_lookup_entry(map, start, &cur)) {
5729 return FALSE;
5730 }
5731
5732 /*
5733 * Optimize for the case that the region is contained
5734 * in a single map entry.
5735 */
5736 if (entry != (vm_map_entry_t *) NULL) {
5737 *entry = cur;
5738 }
5739 if (end <= cur->vme_end) {
5740 return TRUE;
5741 }
5742
5743 /*
5744 * If the region is not wholly contained within a
5745 * single entry, walk the entries looking for holes.
5746 */
5747 prev = cur->vme_end;
5748 cur = cur->vme_next;
5749 while ((cur != vm_map_to_entry(map)) && (prev == cur->vme_start)) {
5750 if (end <= cur->vme_end) {
5751 return TRUE;
5752 }
5753 prev = cur->vme_end;
5754 cur = cur->vme_next;
5755 }
5756 return FALSE;
5757}
5758
5759static __attribute__((always_inline, warn_unused_result))
5760kern_return_t
5761vm_map_protect_sanitize(
5762 vm_map_t map,
5763 vm_map_offset_ut start_u,
5764 vm_map_offset_ut end_u,
5765 vm_prot_ut new_prot_u,
5766 vm_map_offset_t *start,
5767 vm_map_offset_t *end,
5768 vm_prot_t *new_prot)
5769{
5770 kern_return_t kr;
5771 vm_map_size_t size;
5772 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
5773
5774
5775 kr = vm_sanitize_prot(new_prot_u, VM_SANITIZE_CALLER_VM_MAP_PROTECT,
5776 map, VM_PROT_COPY, new_prot);
5777 if (__improbable(kr != KERN_SUCCESS)) {
5778 return kr;
5779 }
5780
5781 kr = vm_sanitize_addr_end(start_u, end_u, VM_SANITIZE_CALLER_VM_MAP_PROTECT,
5782 map, flags, start, end, &size);
5783 if (__improbable(kr != KERN_SUCCESS)) {
5784 return kr;
5785 }
5786
5787 return KERN_SUCCESS;
5788}
5789
5790/*
5791 * vm_map_protect:
5792 *
5793 * Sets the protection of the specified address
5794 * region in the target map. If "set_max" is
5795 * specified, the maximum protection is to be set;
5796 * otherwise, only the current protection is affected.
5797 */
5798kern_return_t
5799vm_map_protect(
5800 vm_map_t map,
5801 vm_map_offset_ut start_u,
5802 vm_map_offset_ut end_u,
5803 boolean_t set_max,
5804 vm_prot_ut new_prot_u)
5805{
5806 vm_map_entry_t current;
5807 vm_map_offset_t prev;
5808 vm_map_entry_t entry;
5809 vm_prot_t new_prot;
5810 vm_prot_t new_max;
5811 int pmap_options = 0;
5812 kern_return_t kr;
5813 vm_map_offset_t start, original_start;
5814 vm_map_offset_t end;
5815
5816 vmlp_api_start(VM_MAP_PROTECT);
5817
5818 kr = vm_map_protect_sanitize(map,
5819 start_u,
5820 end_u,
5821 new_prot_u,
5822 &start,
5823 &end,
5824 &new_prot);
5825 if (__improbable(kr != KERN_SUCCESS)) {
5826 kr = vm_sanitize_get_kr(kr);
5827 vmlp_api_end(VM_MAP_PROTECT, kr);
5828 return kr;
5829 }
5830 original_start = start;
5831
5832 if (new_prot & VM_PROT_COPY) {
5833 vm_map_offset_t new_start;
5834 vm_prot_t cur_prot, max_prot;
5835 vm_map_kernel_flags_t kflags;
5836
5837 /* LP64todo - see below */
5838 if (start >= map->max_offset) {
5839 vmlp_api_end(VM_MAP_PROTECT, KERN_INVALID_ADDRESS);
5840 return KERN_INVALID_ADDRESS;
5841 }
5842
5843 if ((new_prot & VM_PROT_ALLEXEC) &&
5844 map->pmap != kernel_pmap &&
5845 (vm_map_cs_enforcement(map)
5846#if XNU_TARGET_OS_OSX && __arm64__
5847 || !VM_MAP_IS_EXOTIC(map)
5848#endif /* XNU_TARGET_OS_OSX && __arm64__ */
5849 ) &&
5850 VM_MAP_POLICY_WX_FAIL(map)) {
5851 DTRACE_VM3(cs_wx,
5852 uint64_t, (uint64_t) start,
5853 uint64_t, (uint64_t) end,
5854 vm_prot_t, new_prot);
5855 printf("CODE SIGNING: %d[%s] %s:%d(0x%llx,0x%llx,0x%x) can't have both write and exec at the same time\n",
5856 proc_selfpid(),
5857 (get_bsdtask_info(current_task())
5858 ? proc_name_address(get_bsdtask_info(current_task()))
5859 : "?"),
5860 __FUNCTION__, __LINE__,
5861#if DEVELOPMENT || DEBUG
5862 (uint64_t)start,
5863 (uint64_t)end,
5864#else /* DEVELOPMENT || DEBUG */
5865 (uint64_t)0,
5866 (uint64_t)0,
5867#endif /* DEVELOPMENT || DEBUG */
5868 new_prot);
5869 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
5870 return KERN_PROTECTION_FAILURE;
5871 }
5872
5873 /*
5874 * Let vm_map_remap_extract() know that it will need to:
5875 * + make a copy of the mapping
5876 * + add VM_PROT_WRITE to the max protections
5877 * + remove any protections that are no longer allowed from the
5878 * max protections (to avoid any WRITE/EXECUTE conflict, for
5879 * example).
5880 * Note that "max_prot" is an IN/OUT parameter only for this
5881 * specific (VM_PROT_COPY) case. It's usually an OUT parameter
5882 * only.
5883 */
5884 max_prot = new_prot & (VM_PROT_ALL | VM_PROT_ALLEXEC);
5885 cur_prot = VM_PROT_NONE;
5886 kflags = VM_MAP_KERNEL_FLAGS_FIXED(.vmf_overwrite = true);
5887 kflags.vmkf_remap_prot_copy = true;
5888 kflags.vmkf_tpro_enforcement_override = !vm_map_tpro_enforcement(map);
5889 new_start = start;
5890 kr = vm_map_remap(map,
5891 vm_sanitize_wrap_addr_ref(&new_start),
5892 end - start,
5893 0, /* mask */
5894 kflags,
5895 map,
5896 start,
5897 TRUE, /* copy-on-write remapping! */
5898 vm_sanitize_wrap_prot_ref(&cur_prot), /* IN/OUT */
5899 vm_sanitize_wrap_prot_ref(&max_prot), /* IN/OUT */
5900 VM_INHERIT_DEFAULT);
5901 if (kr != KERN_SUCCESS) {
5902 vmlp_api_end(VM_MAP_PROTECT, kr);
5903 return kr;
5904 }
5905 new_prot &= ~VM_PROT_COPY;
5906 }
5907
5908 vm_map_lock(map);
5909 vmlp_range_event(map, start, end - start);
5910
5911restart_after_unlock:
5912
5913 /* LP64todo - remove this check when vm_map_commpage64()
5914 * no longer has to stuff in a map_entry for the commpage
5915 * above the map's max_offset.
5916 */
5917 if (start >= map->max_offset) {
5918 vm_map_unlock(map);
5919 vmlp_api_end(VM_MAP_PROTECT, KERN_INVALID_ADDRESS);
5920 return KERN_INVALID_ADDRESS;
5921 }
5922
5923 while (1) {
5924 /*
5925 * Lookup the entry. If it doesn't start in a valid
5926 * entry, return an error.
5927 */
5928 if (!vm_map_lookup_entry(map, start, &entry)) {
5929 vm_map_unlock(map);
5930 vmlp_api_end(VM_MAP_PROTECT, KERN_INVALID_ADDRESS);
5931 return KERN_INVALID_ADDRESS;
5932 }
5933
5934 if (entry->superpage_size && (start & (SUPERPAGE_SIZE - 1))) { /* extend request to whole entry */
5935 start = SUPERPAGE_ROUND_DOWN(start);
5936 continue;
5937 }
5938 break;
5939 }
5940 if (entry->superpage_size) {
5941 end = SUPERPAGE_ROUND_UP(end);
5942 }
5943
5944 /*
5945 * Make a first pass to check for protection and address
5946 * violations.
5947 */
5948
5949 current = entry;
5950 prev = current->vme_start;
5951 while ((current != vm_map_to_entry(map)) &&
5952 (current->vme_start < end)) {
5953 /*
5954 * If there is a hole, return an error.
5955 */
5956 if (current->vme_start != prev) {
5957 vm_map_unlock(map);
5958 vmlp_api_end(VM_MAP_PROTECT, KERN_INVALID_ADDRESS);
5959 return KERN_INVALID_ADDRESS;
5960 }
5961
5962 new_max = current->max_protection;
5963
5964#if defined(__x86_64__)
5965 /* Allow max mask to include execute prot bits if this map doesn't enforce CS */
5966 if (set_max && (new_prot & VM_PROT_ALLEXEC) && !vm_map_cs_enforcement(map)) {
5967 new_max = (new_max & ~VM_PROT_ALLEXEC) | (new_prot & VM_PROT_ALLEXEC);
5968 }
5969#elif CODE_SIGNING_MONITOR
5970 if (set_max && (new_prot & VM_PROT_EXECUTE) && (csm_address_space_exempt(map->pmap) == KERN_SUCCESS)) {
5971 new_max |= VM_PROT_EXECUTE;
5972 }
5973#endif
5974 if ((new_prot & new_max) != new_prot) {
5975 vm_map_unlock(map);
5976 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
5977 return KERN_PROTECTION_FAILURE;
5978 }
5979
5980 if (current->used_for_jit &&
5981 pmap_has_prot_policy(map->pmap, current->translated_allow_execute, current->protection)) {
5982 vm_map_unlock(map);
5983 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
5984 return KERN_PROTECTION_FAILURE;
5985 }
5986
5987#if __arm64e__
5988 /* Disallow protecting hw assisted TPRO mappings */
5989 if (current->used_for_tpro) {
5990 vm_map_unlock(map);
5991 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
5992 return KERN_PROTECTION_FAILURE;
5993 }
5994#endif /* __arm64e__ */
5995
5996
5997 if ((new_prot & VM_PROT_WRITE) &&
5998 (new_prot & VM_PROT_ALLEXEC) &&
5999#if XNU_TARGET_OS_OSX
6000 map->pmap != kernel_pmap &&
6001 (vm_map_cs_enforcement(map)
6002#if __arm64__
6003 || !VM_MAP_IS_EXOTIC(map)
6004#endif /* __arm64__ */
6005 ) &&
6006#endif /* XNU_TARGET_OS_OSX */
6007#if CODE_SIGNING_MONITOR
6008 (csm_address_space_exempt(map->pmap) != KERN_SUCCESS) &&
6009#endif
6010 !(current->used_for_jit)) {
6011 DTRACE_VM3(cs_wx,
6012 uint64_t, (uint64_t) current->vme_start,
6013 uint64_t, (uint64_t) current->vme_end,
6014 vm_prot_t, new_prot);
6015 printf("CODE SIGNING: %d[%s] %s:%d(0x%llx,0x%llx,0x%x) can't have both write and exec at the same time\n",
6016 proc_selfpid(),
6017 (get_bsdtask_info(current_task())
6018 ? proc_name_address(get_bsdtask_info(current_task()))
6019 : "?"),
6020 __FUNCTION__, __LINE__,
6021#if DEVELOPMENT || DEBUG
6022 (uint64_t)current->vme_start,
6023 (uint64_t)current->vme_end,
6024#else /* DEVELOPMENT || DEBUG */
6025 (uint64_t)0,
6026 (uint64_t)0,
6027#endif /* DEVELOPMENT || DEBUG */
6028 new_prot);
6029 new_prot &= ~VM_PROT_ALLEXEC;
6030 if (VM_MAP_POLICY_WX_FAIL(map)) {
6031 vm_map_unlock(map);
6032 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
6033 return KERN_PROTECTION_FAILURE;
6034 }
6035 }
6036
6037 /*
6038 * If the task has requested executable lockdown,
6039 * deny both:
6040 * - adding executable protections OR
6041 * - adding write protections to an existing executable mapping.
6042 */
6043 if (map->map_disallow_new_exec == TRUE) {
6044 if ((new_prot & VM_PROT_ALLEXEC) ||
6045 ((current->protection & VM_PROT_EXECUTE) && (new_prot & VM_PROT_WRITE))) {
6046 vm_map_unlock(map);
6047 vmlp_api_end(VM_MAP_PROTECT, KERN_PROTECTION_FAILURE);
6048 return KERN_PROTECTION_FAILURE;
6049 }
6050 }
6051
6052 prev = current->vme_end;
6053 current = current->vme_next;
6054 }
6055
6056 if (end > prev) {
6057 vm_map_unlock(map);
6058 vmlp_api_end(VM_MAP_PROTECT, KERN_INVALID_ADDRESS);
6059 return KERN_INVALID_ADDRESS;
6060 }
6061
6062 /*
6063 * Go back and fix up protections.
6064 * Clip to start here if the range starts within
6065 * the entry.
6066 */
6067
6068 current = entry;
6069 if (current != vm_map_to_entry(map)) {
6070 /* clip and unnest if necessary */
6071 vm_map_clip_start(map, current, start);
6072 }
6073
6074 while ((current != vm_map_to_entry(map)) &&
6075 (current->vme_start < end)) {
6076 vm_prot_t old_prot;
6077
6078 if (current->in_transition) {
6079 wait_result_t wait_result;
6080 vm_map_offset_t current_start;
6081
6082 /*
6083 * Another thread is wiring/unwiring this entry.
6084 * Let the other thread know we are waiting.
6085 */
6086 current_start = current->vme_start;
6087 current->needs_wakeup = true;
6088 /* wait for the other thread to be done */
6089 wait_result = vm_map_entry_wait(map, TH_UNINT);
6090 /*
6091 * We unlocked the map, so anything could have changed in the
6092 * range and we need to re-check from "current_start" to "end".
6093 * Our entries might no longer be valid.
6094 */
6095 current = NULL;
6096 entry = NULL;
6097 /*
6098 * Re-lookup and re-clip "current_start".
6099 * If it's no longer mapped,
6100 */
6101 vm_map_lookup_entry_or_next(map, current_start, ¤t);
6102 if (current != vm_map_to_entry(map)) {
6103 vm_map_clip_start(map, current, current_start);
6104 }
6105 /* restart from this point */
6106 start = current_start;
6107 goto restart_after_unlock;
6108 }
6109
6110 vm_map_clip_end(map, current, end);
6111
6112#if DEVELOPMENT || DEBUG
6113 if (current->csm_associated && vm_log_xnu_user_debug) {
6114 printf("FBDP %d[%s] %s(0x%llx,0x%llx,0x%x) on map %p entry %p [0x%llx:0x%llx 0x%x/0x%x] csm_associated\n",
6115 proc_selfpid(),
6116 (get_bsdtask_info(current_task())
6117 ? proc_name_address(get_bsdtask_info(current_task()))
6118 : "?"),
6119 __FUNCTION__,
6120 (uint64_t)start,
6121 (uint64_t)end,
6122 new_prot,
6123 map, current,
6124 current->vme_start,
6125 current->vme_end,
6126 current->protection,
6127 current->max_protection);
6128 }
6129#endif /* DEVELOPMENT || DEBUG */
6130
6131 if (current->is_sub_map) {
6132 /* clipping did unnest if needed */
6133 assert(!current->use_pmap);
6134 }
6135
6136 old_prot = current->protection;
6137
6138 if (set_max) {
6139 current->max_protection = new_prot;
6140 /* Consider either EXECUTE or UEXEC as EXECUTE for this masking */
6141 current->protection = (new_prot & old_prot);
6142 } else {
6143 current->protection = new_prot;
6144 }
6145
6146#if CODE_SIGNING_MONITOR
6147 if (/* a !csm_associated mapping becoming executable */
6148 ((!current->csm_associated &&
6149 !(old_prot & VM_PROT_EXECUTE) &&
6150 (current->protection & VM_PROT_EXECUTE))
6151 ||
6152 /* a csm_associated mapping becoming writable */
6153 (current->csm_associated &&
6154 !(old_prot & VM_PROT_WRITE) &&
6155 (current->protection & VM_PROT_WRITE)))) {
6156 /*
6157 * This mapping has not already been marked as
6158 * "user_debug" and it is either:
6159 * 1. not code-signing-monitored and becoming executable
6160 * 2. code-signing-monitored and becoming writable,
6161 * so inform the CodeSigningMonitor and mark the
6162 * mapping as "user_debug" if appropriate.
6163 */
6164 vm_map_kernel_flags_t vmk_flags;
6165 vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
6166 /* pretend it's a vm_protect(VM_PROT_COPY)... */
6167 vmk_flags.vmkf_remap_prot_copy = true;
6168 kr = vm_map_entry_cs_associate(map, current, vmk_flags);
6169#if DEVELOPMENT || DEBUG
6170 if (vm_log_xnu_user_debug) {
6171 printf("FBDP %d[%s] %s:%d map %p entry %p [ 0x%llx 0x%llx ] prot 0x%x -> 0x%x cs_associate -> %d user_debug=%d\n",
6172 proc_selfpid(),
6173 (get_bsdtask_info(current_task()) ? proc_name_address(get_bsdtask_info(current_task())) : "?"),
6174 __FUNCTION__, __LINE__,
6175 map, current,
6176 current->vme_start, current->vme_end,
6177 old_prot, current->protection,
6178 kr, current->vme_xnu_user_debug);
6179 }
6180#endif /* DEVELOPMENT || DEBUG */
6181 }
6182#endif /* CODE_SIGNING_MONITOR */
6183
6184 /*
6185 * Update physical map if necessary.
6186 * If the request is to turn off write protection,
6187 * we won't do it for real (in pmap). This is because
6188 * it would cause copy-on-write to fail. We've already
6189 * set, the new protection in the map, so if a
6190 * write-protect fault occurred, it will be fixed up
6191 * properly, COW or not.
6192 */
6193 if (current->protection != old_prot) {
6194 /* Look one level in we support nested pmaps */
6195 /* from mapped submaps which are direct entries */
6196 /* in our map */
6197
6198 vm_prot_t prot;
6199
6200 prot = current->protection;
6201 if (current->is_sub_map || (VME_OBJECT(current) == NULL) || (VME_OBJECT(current) != compressor_object)) {
6202 prot &= ~VM_PROT_WRITE;
6203 } else {
6204 assert(!VME_OBJECT(current)->code_signed);
6205 assert(VME_OBJECT(current)->copy_strategy == MEMORY_OBJECT_COPY_NONE);
6206 if (prot & VM_PROT_WRITE) {
6207 /*
6208 * For write requests on the
6209 * compressor, we wil ask the
6210 * pmap layer to prevent us from
6211 * taking a write fault when we
6212 * attempt to access the mapping
6213 * next.
6214 */
6215 pmap_options |= PMAP_OPTIONS_PROTECT_IMMEDIATE;
6216 }
6217 }
6218
6219 if (override_nx(map, VME_ALIAS(current)) && prot) {
6220 prot |= VM_PROT_EXECUTE;
6221 }
6222
6223#if DEVELOPMENT || DEBUG
6224 if (!(old_prot & VM_PROT_EXECUTE) &&
6225 (prot & VM_PROT_EXECUTE) &&
6226 panic_on_unsigned_execute &&
6227 (proc_selfcsflags() & CS_KILL)) {
6228 panic("vm_map_protect(%p,0x%llx,0x%llx) old=0x%x new=0x%x - <rdar://23770418> code-signing bypass?", map, (uint64_t)current->vme_start, (uint64_t)current->vme_end, old_prot, prot);
6229 }
6230#endif /* DEVELOPMENT || DEBUG */
6231
6232 if (pmap_has_prot_policy(map->pmap, current->translated_allow_execute, prot)) {
6233 if (current->wired_count) {
6234 panic("vm_map_protect(%p,0x%llx,0x%llx) new=0x%x wired=%x",
6235 map, (uint64_t)current->vme_start, (uint64_t)current->vme_end, prot, current->wired_count);
6236 }
6237
6238 /* If the pmap layer cares about this
6239 * protection type, force a fault for
6240 * each page so that vm_fault will
6241 * repopulate the page with the full
6242 * set of protections.
6243 */
6244 /*
6245 * TODO: We don't seem to need this,
6246 * but this is due to an internal
6247 * implementation detail of
6248 * pmap_protect. Do we want to rely
6249 * on this?
6250 */
6251 prot = VM_PROT_NONE;
6252 }
6253
6254 if (current->is_sub_map && current->use_pmap) {
6255 pmap_protect(VME_SUBMAP(current)->pmap,
6256 current->vme_start,
6257 current->vme_end,
6258 prot);
6259 } else {
6260 pmap_protect_options(map->pmap,
6261 current->vme_start,
6262 current->vme_end,
6263 prot,
6264 pmap_options,
6265 NULL);
6266 }
6267 }
6268 current = current->vme_next;
6269 }
6270
6271 if (entry == VM_MAP_ENTRY_NULL) {
6272 /*
6273 * Re-lookup the original start of our range.
6274 * If it's no longer mapped, start with the next mapping.
6275 */
6276 vm_map_lookup_entry_or_next(map, original_start, &entry);
6277 }
6278 current = entry;
6279 while ((current != vm_map_to_entry(map)) &&
6280 (current->vme_start <= end)) {
6281 vm_map_simplify_entry(map, current);
6282 current = current->vme_next;
6283 }
6284
6285 vm_map_unlock(map);
6286 vmlp_api_end(VM_MAP_PROTECT, KERN_SUCCESS);
6287 return KERN_SUCCESS;
6288}
6289
6290static __attribute__((always_inline, warn_unused_result))
6291kern_return_t
6292vm_map_inherit_sanitize(
6293 vm_map_t map,
6294 vm_map_offset_ut start_u,
6295 vm_map_offset_ut end_u,
6296 vm_inherit_ut new_inheritance_u,
6297 vm_map_offset_t *start,
6298 vm_map_offset_t *end,
6299 vm_inherit_t *new_inheritance)
6300{
6301 kern_return_t kr;
6302 vm_map_size_t size;
6303
6304 kr = vm_sanitize_inherit(new_inheritance_u,
6305 VM_SANITIZE_CALLER_VM_MAP_INHERIT, new_inheritance);
6306 if (__improbable(kr != KERN_SUCCESS)) {
6307 return kr;
6308 }
6309
6310 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
6311
6312
6313 kr = vm_sanitize_addr_end(start_u, end_u, VM_SANITIZE_CALLER_VM_MAP_INHERIT,
6314 map, flags, start, end, &size);
6315 if (__improbable(kr != KERN_SUCCESS)) {
6316 return kr;
6317 }
6318
6319 return KERN_SUCCESS;
6320}
6321
6322/*
6323 * vm_map_inherit:
6324 *
6325 * Sets the inheritance of the specified address
6326 * range in the target map. Inheritance
6327 * affects how the map will be shared with
6328 * child maps at the time of vm_map_fork.
6329 */
6330kern_return_t
6331vm_map_inherit(
6332 vm_map_t map,
6333 vm_map_offset_ut start_u,
6334 vm_map_offset_ut end_u,
6335 vm_inherit_ut new_inheritance_u)
6336{
6337 vm_map_entry_t entry;
6338 vm_map_entry_t temp_entry;
6339 kern_return_t kr;
6340 vm_map_offset_t start;
6341 vm_map_offset_t end;
6342 vm_inherit_t new_inheritance;
6343
6344 vmlp_api_start(VM_MAP_INHERIT);
6345
6346 kr = vm_map_inherit_sanitize(map,
6347 start_u,
6348 end_u,
6349 new_inheritance_u,
6350 &start,
6351 &end,
6352 &new_inheritance);
6353 if (__improbable(kr != KERN_SUCCESS)) {
6354 kr = vm_sanitize_get_kr(kr);
6355 vmlp_api_end(VM_MAP_INHERIT, kr);
6356 return kr;
6357 }
6358
6359 vm_map_lock(map);
6360
6361 VM_MAP_RANGE_CHECK(map, start, end);
6362 vmlp_range_event(map, start, end - start);
6363
6364 if (vm_map_lookup_entry(map, start, &temp_entry)) {
6365 entry = temp_entry;
6366 } else {
6367 temp_entry = temp_entry->vme_next;
6368 entry = temp_entry;
6369 }
6370
6371 /* first check entire range for entries which can't support the */
6372 /* given inheritance. */
6373 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
6374 if (entry->is_sub_map) {
6375 if (new_inheritance == VM_INHERIT_COPY) {
6376 vm_map_unlock(map);
6377 vmlp_api_end(VM_MAP_INHERIT, KERN_INVALID_ADDRESS);
6378 return KERN_INVALID_ARGUMENT;
6379 }
6380 }
6381
6382 entry = entry->vme_next;
6383 }
6384
6385 entry = temp_entry;
6386 if (entry != vm_map_to_entry(map)) {
6387 /* clip and unnest if necessary */
6388 vm_map_clip_start(map, entry, start);
6389 }
6390
6391 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
6392 vm_map_clip_end(map, entry, end);
6393 if (entry->is_sub_map) {
6394 /* clip did unnest if needed */
6395 assert(!entry->use_pmap);
6396 }
6397
6398 entry->inheritance = new_inheritance;
6399
6400 entry = entry->vme_next;
6401 }
6402
6403 vm_map_unlock(map);
6404 vmlp_api_end(VM_MAP_INHERIT, KERN_SUCCESS);
6405 return KERN_SUCCESS;
6406}
6407
6408/*
6409 * Update the accounting for the amount of wired memory in this map. If the user has
6410 * exceeded the defined limits, then we fail. Wiring on behalf of the kernel never fails.
6411 */
6412
6413static kern_return_t
6414add_wire_counts(
6415 vm_map_t map,
6416 vm_map_entry_t entry,
6417 boolean_t user_wire)
6418{
6419 vm_map_size_t size;
6420
6421 bool first_wire = entry->wired_count == 0 && entry->user_wired_count == 0;
6422
6423 if (user_wire) {
6424 unsigned int total_wire_count = vm_page_wire_count + vm_lopage_free_count;
6425
6426 /*
6427 * We're wiring memory at the request of the user. Check if this is the first time the user is wiring
6428 * this map entry.
6429 */
6430
6431 if (entry->user_wired_count == 0) {
6432 size = entry->vme_end - entry->vme_start;
6433
6434 /*
6435 * Since this is the first time the user is wiring this map entry, check to see if we're
6436 * exceeding the user wire limits. There is a per map limit which is the smaller of either
6437 * the process's rlimit or the global vm_per_task_user_wire_limit which caps this value. There is also
6438 * a system-wide limit on the amount of memory all users can wire. If the user is over either
6439 * limit, then we fail.
6440 */
6441
6442 if (size + map->user_wire_size > MIN(map->user_wire_limit, vm_per_task_user_wire_limit) ||
6443 size + ptoa_64(total_wire_count) > vm_global_user_wire_limit) {
6444 if (size + ptoa_64(total_wire_count) > vm_global_user_wire_limit) {
6445#if DEVELOPMENT || DEBUG
6446 if (panic_on_mlock_failure) {
6447 panic("mlock: Over global wire limit. %llu bytes wired and requested to wire %llu bytes more", ptoa_64(total_wire_count), (uint64_t) size);
6448 }
6449#endif /* DEVELOPMENT || DEBUG */
6450 os_atomic_inc(&vm_add_wire_count_over_global_limit, relaxed);
6451 } else {
6452 os_atomic_inc(&vm_add_wire_count_over_user_limit, relaxed);
6453#if DEVELOPMENT || DEBUG
6454 if (panic_on_mlock_failure) {
6455 panic("mlock: Over process wire limit. %llu bytes wired and requested to wire %llu bytes more", (uint64_t) map->user_wire_size, (uint64_t) size);
6456 }
6457#endif /* DEVELOPMENT || DEBUG */
6458 }
6459 return KERN_RESOURCE_SHORTAGE;
6460 }
6461
6462 /*
6463 * The first time the user wires an entry, we also increment the wired_count and add this to
6464 * the total that has been wired in the map.
6465 */
6466
6467 if (entry->wired_count >= MAX_WIRE_COUNT) {
6468 return KERN_FAILURE;
6469 }
6470
6471 entry->wired_count++;
6472 map->user_wire_size += size;
6473 }
6474
6475 if (entry->user_wired_count >= MAX_WIRE_COUNT) {
6476 return KERN_FAILURE;
6477 }
6478
6479 entry->user_wired_count++;
6480 } else {
6481 /*
6482 * The kernel's wiring the memory. Just bump the count and continue.
6483 */
6484
6485 if (entry->wired_count >= MAX_WIRE_COUNT) {
6486 panic("vm_map_wire: too many wirings");
6487 }
6488
6489 entry->wired_count++;
6490 }
6491
6492 if (first_wire) {
6493 vme_btref_consider_and_set(entry, __builtin_frame_address(0));
6494 }
6495
6496 return KERN_SUCCESS;
6497}
6498
6499/*
6500 * Update the memory wiring accounting now that the given map entry is being unwired.
6501 */
6502
6503static void
6504subtract_wire_counts(
6505 vm_map_t map,
6506 vm_map_entry_t entry,
6507 boolean_t user_wire)
6508{
6509 if (user_wire) {
6510 /*
6511 * We're unwiring memory at the request of the user. See if we're removing the last user wire reference.
6512 */
6513
6514 if (entry->user_wired_count == 1) {
6515 /*
6516 * We're removing the last user wire reference. Decrement the wired_count and the total
6517 * user wired memory for this map.
6518 */
6519
6520 assert(entry->wired_count >= 1);
6521 entry->wired_count--;
6522 map->user_wire_size -= entry->vme_end - entry->vme_start;
6523 }
6524
6525 assert(entry->user_wired_count >= 1);
6526 entry->user_wired_count--;
6527 } else {
6528 /*
6529 * The kernel is unwiring the memory. Just update the count.
6530 */
6531
6532 assert(entry->wired_count >= 1);
6533 entry->wired_count--;
6534 }
6535
6536 vme_btref_consider_and_put(entry);
6537}
6538
6539int cs_executable_wire = 0;
6540
6541static kern_return_t
6542vm_map_wire_nested(
6543 vm_map_t map,
6544 vm_map_offset_t start,
6545 vm_map_offset_t end,
6546 vm_prot_t caller_prot,
6547 vm_tag_t tag,
6548 boolean_t user_wire,
6549 pmap_t map_pmap,
6550 vm_map_offset_t pmap_addr,
6551 ppnum_t *physpage_p)
6552{
6553 vm_map_entry_t entry;
6554 vm_prot_t access_type;
6555 struct vm_map_entry *first_entry, tmp_entry;
6556 vm_map_t real_map;
6557 vm_map_offset_t s, e;
6558 kern_return_t rc;
6559 boolean_t need_wakeup;
6560 boolean_t main_map = FALSE;
6561 wait_interrupt_t interruptible_state;
6562 thread_t cur_thread;
6563 unsigned int last_timestamp;
6564 vm_map_size_t size;
6565 boolean_t wire_and_extract;
6566 vm_prot_t extra_prots;
6567
6568 vmlp_api_start(VM_MAP_WIRE_NESTED);
6569 vmlp_range_event(map, start, end - start);
6570
6571 extra_prots = VM_PROT_COPY;
6572 extra_prots |= VM_PROT_COPY_FAIL_IF_EXECUTABLE;
6573#if XNU_TARGET_OS_OSX
6574 if (map->pmap == kernel_pmap ||
6575 !vm_map_cs_enforcement(map)) {
6576 extra_prots &= ~VM_PROT_COPY_FAIL_IF_EXECUTABLE;
6577 }
6578#endif /* XNU_TARGET_OS_OSX */
6579#if CODE_SIGNING_MONITOR
6580 if (csm_address_space_exempt(map->pmap) == KERN_SUCCESS) {
6581 extra_prots &= ~VM_PROT_COPY_FAIL_IF_EXECUTABLE;
6582 }
6583#endif /* CODE_SIGNING_MONITOR */
6584
6585 access_type = (caller_prot & (VM_PROT_ALL | VM_PROT_ALLEXEC));
6586
6587 wire_and_extract = FALSE;
6588 if (physpage_p != NULL) {
6589 /*
6590 * The caller wants the physical page number of the
6591 * wired page. We return only one physical page number
6592 * so this works for only one page at a time.
6593 *
6594 * The only caller (vm_map_wire_and_extract)
6595 * guarantees it.
6596 */
6597 assert(end - start == VM_MAP_PAGE_SIZE(map));
6598 wire_and_extract = TRUE;
6599 *physpage_p = 0;
6600 }
6601
6602 VM_MAP_RANGE_CHECK(map, start, end);
6603 assert(VM_MAP_PAGE_ALIGNED(start, VM_MAP_PAGE_MASK(map)));
6604 assert(VM_MAP_PAGE_ALIGNED(end, VM_MAP_PAGE_MASK(map)));
6605 if (start == end) {
6606 /* We wired what the caller asked for, zero pages */
6607 vmlp_api_end(VM_MAP_WIRE_NESTED, KERN_SUCCESS);
6608 return KERN_SUCCESS;
6609 }
6610
6611 vm_map_lock(map);
6612 if (map_pmap == NULL) {
6613 main_map = TRUE;
6614 }
6615 last_timestamp = map->timestamp;
6616
6617 need_wakeup = FALSE;
6618 cur_thread = current_thread();
6619
6620 s = start;
6621 rc = KERN_SUCCESS;
6622
6623 if (vm_map_lookup_entry(map, s, &first_entry)) {
6624 entry = first_entry;
6625 /*
6626 * vm_map_clip_start will be done later.
6627 * We don't want to unnest any nested submaps here !
6628 */
6629 } else {
6630 /* Start address is not in map */
6631 rc = KERN_INVALID_ADDRESS;
6632 goto done;
6633 }
6634
6635 while ((entry != vm_map_to_entry(map)) && (s < end)) {
6636 /*
6637 * At this point, we have wired from "start" to "s".
6638 * We still need to wire from "s" to "end".
6639 *
6640 * "entry" hasn't been clipped, so it could start before "s"
6641 * and/or end after "end".
6642 */
6643
6644 /* "e" is how far we want to wire in this entry */
6645 e = entry->vme_end;
6646 if (e > end) {
6647 e = end;
6648 }
6649
6650 /*
6651 * If another thread is wiring/unwiring this entry then
6652 * block after informing other thread to wake us up.
6653 */
6654 if (entry->in_transition) {
6655 wait_result_t wait_result;
6656
6657 /*
6658 * We have not clipped the entry. Make sure that
6659 * the start address is in range so that the lookup
6660 * below will succeed.
6661 * "s" is the current starting point: we've already
6662 * wired from "start" to "s" and we still have
6663 * to wire from "s" to "end".
6664 */
6665
6666 entry->needs_wakeup = TRUE;
6667
6668 /*
6669 * wake up anybody waiting on entries that we have
6670 * already wired.
6671 */
6672 if (need_wakeup) {
6673 vm_map_entry_wakeup(map);
6674 need_wakeup = FALSE;
6675 }
6676 /*
6677 * User wiring is interruptible
6678 */
6679 wait_result = vm_map_entry_wait(map,
6680 (user_wire) ? THREAD_ABORTSAFE :
6681 THREAD_UNINT);
6682 if (user_wire && wait_result == THREAD_INTERRUPTED) {
6683 /*
6684 * undo the wirings we have done so far
6685 * We do not clear the needs_wakeup flag,
6686 * because we cannot tell if we were the
6687 * only one waiting.
6688 */
6689 rc = KERN_FAILURE;
6690 goto done;
6691 }
6692
6693 /*
6694 * Cannot avoid a lookup here. reset timestamp.
6695 */
6696 last_timestamp = map->timestamp;
6697
6698 /*
6699 * The entry could have been clipped, look it up again.
6700 * Worse that can happen is, it may not exist anymore.
6701 */
6702 if (!vm_map_lookup_entry(map, s, &first_entry)) {
6703 /*
6704 * User: undo everything upto the previous
6705 * entry. let vm_map_unwire worry about
6706 * checking the validity of the range.
6707 */
6708 rc = KERN_FAILURE;
6709 goto done;
6710 }
6711 entry = first_entry;
6712 continue;
6713 }
6714
6715 if (entry->is_sub_map) {
6716 vm_map_offset_t sub_start;
6717 vm_map_offset_t sub_end;
6718 vm_map_offset_t local_start;
6719 vm_map_offset_t local_end;
6720 pmap_t pmap;
6721 vm_map_t sub_map = VM_MAP_NULL;
6722
6723 if (wire_and_extract) {
6724 /*
6725 * Wiring would result in copy-on-write
6726 * which would not be compatible with
6727 * the sharing we have with the original
6728 * provider of this memory.
6729 */
6730 rc = KERN_INVALID_ARGUMENT;
6731 goto done;
6732 }
6733
6734 vm_map_clip_start(map, entry, s);
6735 vm_map_clip_end(map, entry, end);
6736
6737 sub_start = VME_OFFSET(entry);
6738 sub_end = entry->vme_end;
6739 sub_end += VME_OFFSET(entry) - entry->vme_start;
6740
6741 local_end = entry->vme_end;
6742 if (map_pmap == NULL) {
6743 vm_object_t object;
6744 vm_object_offset_t offset;
6745 vm_prot_t prot;
6746 boolean_t wired;
6747 vm_map_entry_t local_entry;
6748 vm_map_version_t version;
6749 vm_map_t lookup_map;
6750
6751 if (entry->use_pmap) {
6752 pmap = VME_SUBMAP(entry)->pmap;
6753 /* ppc implementation requires that */
6754 /* submaps pmap address ranges line */
6755 /* up with parent map */
6756#ifdef notdef
6757 pmap_addr = sub_start;
6758#endif
6759 pmap_addr = s;
6760 } else {
6761 pmap = map->pmap;
6762 pmap_addr = s;
6763 }
6764
6765 if (entry->wired_count) {
6766 if ((rc = add_wire_counts(map, entry, user_wire)) != KERN_SUCCESS) {
6767 goto done;
6768 }
6769
6770 /*
6771 * The map was not unlocked:
6772 * no need to goto re-lookup.
6773 * Just go directly to next entry.
6774 */
6775 entry = entry->vme_next;
6776 s = entry->vme_start;
6777 continue;
6778 }
6779
6780 /* call vm_map_lookup_and_lock_object to */
6781 /* cause any needs copy to be */
6782 /* evaluated */
6783 local_start = entry->vme_start;
6784 lookup_map = map;
6785 vm_map_lock_write_to_read(map);
6786 rc = vm_map_lookup_and_lock_object(
6787 &lookup_map, local_start,
6788 (access_type | extra_prots),
6789 OBJECT_LOCK_EXCLUSIVE,
6790 &version, &object,
6791 &offset, &prot, &wired,
6792 NULL,
6793 &real_map, NULL);
6794 if (rc != KERN_SUCCESS) {
6795 vm_map_unlock_read(lookup_map);
6796 assert(map_pmap == NULL);
6797 vm_map_unwire_nested(map, start,
6798 s, user_wire, PMAP_NULL, 0);
6799 vmlp_api_end(VM_MAP_WIRE_NESTED, rc);
6800 return rc;
6801 }
6802 vm_object_unlock(object);
6803 if (real_map != lookup_map) {
6804 vm_map_unlock(real_map);
6805 }
6806 vm_map_unlock_read(lookup_map);
6807 vm_map_lock(map);
6808
6809 /* we unlocked, so must re-lookup */
6810 if (!vm_map_lookup_entry(map,
6811 local_start,
6812 &local_entry)) {
6813 rc = KERN_FAILURE;
6814 goto done;
6815 }
6816
6817 /*
6818 * entry could have been "simplified",
6819 * so re-clip
6820 */
6821 entry = local_entry;
6822 assert(s == local_start);
6823 vm_map_clip_start(map, entry, s);
6824 vm_map_clip_end(map, entry, end);
6825 /* re-compute "e" */
6826 e = entry->vme_end;
6827 if (e > end) {
6828 e = end;
6829 }
6830
6831 /* did we have a change of type? */
6832 if (!entry->is_sub_map) {
6833 last_timestamp = map->timestamp;
6834 continue;
6835 }
6836 } else {
6837 local_start = entry->vme_start;
6838 pmap = map_pmap;
6839 }
6840
6841 if ((rc = add_wire_counts(map, entry, user_wire)) != KERN_SUCCESS) {
6842 goto done;
6843 }
6844
6845 entry->in_transition = TRUE;
6846
6847 sub_map = VME_SUBMAP(entry);
6848 vm_map_reference(sub_map);
6849 vm_map_unlock(map);
6850 rc = vm_map_wire_nested(sub_map,
6851 sub_start, sub_end,
6852 caller_prot, tag,
6853 user_wire, pmap, pmap_addr,
6854 NULL);
6855 vm_map_deallocate(sub_map);
6856 sub_map = VM_MAP_NULL;
6857 vm_map_lock(map);
6858
6859 /*
6860 * Find the entry again. It could have been clipped
6861 * after we unlocked the map.
6862 */
6863 if (!vm_map_lookup_entry(map, local_start,
6864 &first_entry)) {
6865 panic("vm_map_wire: re-lookup failed");
6866 }
6867 entry = first_entry;
6868
6869 assert(local_start == s);
6870 /* re-compute "e" */
6871 e = entry->vme_end;
6872 if (e > end) {
6873 e = end;
6874 }
6875
6876 last_timestamp = map->timestamp;
6877 while ((entry != vm_map_to_entry(map)) &&
6878 (entry->vme_start < e)) {
6879 assert(entry->in_transition);
6880 entry->in_transition = FALSE;
6881 if (entry->needs_wakeup) {
6882 entry->needs_wakeup = FALSE;
6883 need_wakeup = TRUE;
6884 }
6885 if (rc != KERN_SUCCESS) {/* from vm_*_wire */
6886 subtract_wire_counts(map, entry, user_wire);
6887 }
6888 entry = entry->vme_next;
6889 }
6890 if (rc != KERN_SUCCESS) { /* from vm_*_wire */
6891 goto done;
6892 }
6893
6894 /* no need to relookup again */
6895 s = entry->vme_start;
6896 continue;
6897 }
6898
6899 /*
6900 * If this entry is already wired then increment
6901 * the appropriate wire reference count.
6902 */
6903 if (entry->wired_count) {
6904 if ((entry->protection & access_type) != access_type) {
6905 /* found a protection problem */
6906
6907 /*
6908 * XXX FBDP
6909 * We should always return an error
6910 * in this case but since we didn't
6911 * enforce it before, let's do
6912 * it only for the new "wire_and_extract"
6913 * code path for now...
6914 */
6915 if (wire_and_extract) {
6916 rc = KERN_PROTECTION_FAILURE;
6917 goto done;
6918 }
6919 }
6920
6921 /*
6922 * entry is already wired down, get our reference
6923 * after clipping to our range.
6924 */
6925 vm_map_clip_start(map, entry, s);
6926 vm_map_clip_end(map, entry, end);
6927
6928 if ((rc = add_wire_counts(map, entry, user_wire)) != KERN_SUCCESS) {
6929 goto done;
6930 }
6931
6932 if (wire_and_extract) {
6933 vm_object_t object;
6934 vm_object_offset_t offset;
6935 vm_page_t m;
6936
6937 /*
6938 * We don't have to "wire" the page again
6939 * bit we still have to "extract" its
6940 * physical page number, after some sanity
6941 * checks.
6942 */
6943 assert((entry->vme_end - entry->vme_start)
6944 == PAGE_SIZE);
6945 assert(!entry->needs_copy);
6946 assert(!entry->is_sub_map);
6947 assert(VME_OBJECT(entry));
6948 if (((entry->vme_end - entry->vme_start)
6949 != PAGE_SIZE) ||
6950 entry->needs_copy ||
6951 entry->is_sub_map ||
6952 VME_OBJECT(entry) == VM_OBJECT_NULL) {
6953 rc = KERN_INVALID_ARGUMENT;
6954 goto done;
6955 }
6956
6957 object = VME_OBJECT(entry);
6958 offset = VME_OFFSET(entry);
6959 /* need exclusive lock to update m->dirty */
6960 if (entry->protection & VM_PROT_WRITE) {
6961 vm_object_lock(object);
6962 } else {
6963 vm_object_lock_shared(object);
6964 }
6965 m = vm_page_lookup(object, offset);
6966 assert(m != VM_PAGE_NULL);
6967 assert(VM_PAGE_WIRED(m));
6968 if (m != VM_PAGE_NULL && VM_PAGE_WIRED(m)) {
6969 *physpage_p = VM_PAGE_GET_PHYS_PAGE(m);
6970 if (entry->protection & VM_PROT_WRITE) {
6971 vm_object_lock_assert_exclusive(
6972 object);
6973 m->vmp_dirty = TRUE;
6974 }
6975 } else {
6976 /* not already wired !? */
6977 *physpage_p = 0;
6978 }
6979 vm_object_unlock(object);
6980 }
6981
6982 /* map was not unlocked: no need to relookup */
6983 entry = entry->vme_next;
6984 s = entry->vme_start;
6985 continue;
6986 }
6987
6988 /*
6989 * Unwired entry or wire request transmitted via submap
6990 */
6991
6992 /*
6993 * Wiring would copy the pages to the shadow object.
6994 * The shadow object would not be code-signed so
6995 * attempting to execute code from these copied pages
6996 * would trigger a code-signing violation.
6997 */
6998
6999 if ((entry->protection & VM_PROT_EXECUTE)
7000#if XNU_TARGET_OS_OSX
7001 &&
7002 map->pmap != kernel_pmap &&
7003 (vm_map_cs_enforcement(map)
7004#if __arm64__
7005 || !VM_MAP_IS_EXOTIC(map)
7006#endif /* __arm64__ */
7007 )
7008#endif /* XNU_TARGET_OS_OSX */
7009#if CODE_SIGNING_MONITOR
7010 &&
7011 (csm_address_space_exempt(map->pmap) != KERN_SUCCESS)
7012#endif
7013 ) {
7014#if MACH_ASSERT
7015 printf("pid %d[%s] wiring executable range from "
7016 "0x%llx to 0x%llx: rejected to preserve "
7017 "code-signing\n",
7018 proc_selfpid(),
7019 (get_bsdtask_info(current_task())
7020 ? proc_name_address(get_bsdtask_info(current_task()))
7021 : "?"),
7022 (uint64_t) entry->vme_start,
7023 (uint64_t) entry->vme_end);
7024#endif /* MACH_ASSERT */
7025 DTRACE_VM2(cs_executable_wire,
7026 uint64_t, (uint64_t)entry->vme_start,
7027 uint64_t, (uint64_t)entry->vme_end);
7028 cs_executable_wire++;
7029 rc = KERN_PROTECTION_FAILURE;
7030 goto done;
7031 }
7032
7033 /*
7034 * Perform actions of vm_map_lookup that need the write
7035 * lock on the map: create a shadow object for a
7036 * copy-on-write region, or an object for a zero-fill
7037 * region.
7038 */
7039 size = entry->vme_end - entry->vme_start;
7040 /*
7041 * If wiring a copy-on-write page, we need to copy it now
7042 * even if we're only (currently) requesting read access.
7043 * This is aggressive, but once it's wired we can't move it.
7044 */
7045 if (entry->needs_copy) {
7046 if (wire_and_extract) {
7047 /*
7048 * We're supposed to share with the original
7049 * provider so should not be "needs_copy"
7050 */
7051 rc = KERN_INVALID_ARGUMENT;
7052 goto done;
7053 }
7054
7055 VME_OBJECT_SHADOW(entry, size,
7056 vm_map_always_shadow(map));
7057 entry->needs_copy = FALSE;
7058 } else if (VME_OBJECT(entry) == VM_OBJECT_NULL) {
7059 if (wire_and_extract) {
7060 /*
7061 * We're supposed to share with the original
7062 * provider so should already have an object.
7063 */
7064 rc = KERN_INVALID_ARGUMENT;
7065 goto done;
7066 }
7067 VME_OBJECT_SET(entry, vm_object_allocate(size, map->serial_id), false, 0);
7068 VME_OFFSET_SET(entry, (vm_object_offset_t)0);
7069 assert(entry->use_pmap);
7070 } else if (VME_OBJECT(entry)->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
7071 if (wire_and_extract) {
7072 /*
7073 * We're supposed to share with the original
7074 * provider so should not be COPY_SYMMETRIC.
7075 */
7076 rc = KERN_INVALID_ARGUMENT;
7077 goto done;
7078 }
7079 /*
7080 * Force an unrequested "copy-on-write" but only for
7081 * the range we're wiring.
7082 */
7083// printf("FBDP %s:%d map %p entry %p [ 0x%llx 0x%llx ] s 0x%llx end 0x%llx wire&extract=%d\n", __FUNCTION__, __LINE__, map, entry, (uint64_t)entry->vme_start, (uint64_t)entry->vme_end, (uint64_t)s, (uint64_t)end, wire_and_extract);
7084 vm_map_clip_start(map, entry, s);
7085 vm_map_clip_end(map, entry, end);
7086 /* recompute "size" */
7087 size = entry->vme_end - entry->vme_start;
7088 /* make a shadow object */
7089 vm_object_t orig_object;
7090 vm_object_offset_t orig_offset;
7091 orig_object = VME_OBJECT(entry);
7092 orig_offset = VME_OFFSET(entry);
7093 VME_OBJECT_SHADOW(entry, size, vm_map_always_shadow(map));
7094 if (VME_OBJECT(entry) != orig_object) {
7095 /*
7096 * This mapping has not been shared (or it would be
7097 * COPY_DELAY instead of COPY_SYMMETRIC) and it has
7098 * not been copied-on-write (or it would be marked
7099 * as "needs_copy" and would have been handled above
7100 * and also already write-protected).
7101 * We still need to write-protect here to prevent
7102 * other threads from modifying these pages while
7103 * we're in the process of copying and wiring
7104 * the copied pages.
7105 * Since the mapping is neither shared nor COWed,
7106 * we only need to write-protect the PTEs for this
7107 * mapping.
7108 */
7109 vm_object_pmap_protect(orig_object,
7110 orig_offset,
7111 size,
7112 map->pmap,
7113 VM_MAP_PAGE_SIZE(map),
7114 entry->vme_start,
7115 entry->protection & ~VM_PROT_WRITE);
7116 }
7117 }
7118 if (VME_OBJECT(entry)->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
7119 /*
7120 * Make the object COPY_DELAY to get a stable object
7121 * to wire.
7122 * That should avoid creating long shadow chains while
7123 * wiring/unwiring the same range repeatedly.
7124 * That also prevents part of the object from being
7125 * wired while another part is "needs_copy", which
7126 * could result in conflicting rules wrt copy-on-write.
7127 */
7128 vm_object_t object;
7129
7130 object = VME_OBJECT(entry);
7131 vm_object_lock(object);
7132 if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
7133 assertf(vm_object_round_page(VME_OFFSET(entry) + size) - vm_object_trunc_page(VME_OFFSET(entry)) == object->vo_size,
7134 "object %p size 0x%llx entry %p [0x%llx:0x%llx:0x%llx] size 0x%llx\n",
7135 object, (uint64_t)object->vo_size,
7136 entry,
7137 (uint64_t)entry->vme_start,
7138 (uint64_t)entry->vme_end,
7139 (uint64_t)VME_OFFSET(entry),
7140 (uint64_t)size);
7141 assertf(os_ref_get_count_raw(&object->ref_count) == 1,
7142 "object %p ref_count %d\n",
7143 object, os_ref_get_count_raw(&object->ref_count));
7144 assertf(!entry->needs_copy,
7145 "entry %p\n", entry);
7146 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
7147 VM_OBJECT_SET_TRUE_SHARE(object, TRUE);
7148 }
7149 vm_object_unlock(object);
7150 }
7151
7152 vm_map_clip_start(map, entry, s);
7153 vm_map_clip_end(map, entry, end);
7154
7155 /* re-compute "e" */
7156 e = entry->vme_end;
7157 if (e > end) {
7158 e = end;
7159 }
7160
7161 /*
7162 * Check for holes and protection mismatch.
7163 * Holes: Next entry should be contiguous unless this
7164 * is the end of the region.
7165 * Protection: Access requested must be allowed, unless
7166 * wiring is by protection class
7167 */
7168 if ((entry->vme_end < end) &&
7169 ((entry->vme_next == vm_map_to_entry(map)) ||
7170 (entry->vme_next->vme_start > entry->vme_end))) {
7171 /* found a hole */
7172 rc = KERN_INVALID_ADDRESS;
7173 goto done;
7174 }
7175 if ((entry->protection & access_type) != access_type) {
7176 /* found a protection problem */
7177 rc = KERN_PROTECTION_FAILURE;
7178 goto done;
7179 }
7180
7181 assert(entry->wired_count == 0 && entry->user_wired_count == 0);
7182
7183 if ((rc = add_wire_counts(map, entry, user_wire)) != KERN_SUCCESS) {
7184 goto done;
7185 }
7186
7187 entry->in_transition = TRUE;
7188
7189 /*
7190 * This entry might get split once we unlock the map.
7191 * In vm_fault_wire(), we need the current range as
7192 * defined by this entry. In order for this to work
7193 * along with a simultaneous clip operation, we make a
7194 * temporary copy of this entry and use that for the
7195 * wiring. Note that the underlying objects do not
7196 * change during a clip.
7197 */
7198 tmp_entry = *entry;
7199
7200 /*
7201 * The in_transition state guarentees that the entry
7202 * (or entries for this range, if split occured) will be
7203 * there when the map lock is acquired for the second time.
7204 */
7205 vm_map_unlock(map);
7206
7207 if (!user_wire && cur_thread != THREAD_NULL) {
7208 interruptible_state = thread_interrupt_level(THREAD_UNINT);
7209 } else {
7210 interruptible_state = THREAD_UNINT;
7211 }
7212
7213 if (map_pmap) {
7214 rc = vm_fault_wire(map,
7215 &tmp_entry, caller_prot, tag, map_pmap, pmap_addr,
7216 physpage_p);
7217 } else {
7218 rc = vm_fault_wire(map,
7219 &tmp_entry, caller_prot, tag, map->pmap,
7220 tmp_entry.vme_start,
7221 physpage_p);
7222 }
7223
7224 if (!user_wire && cur_thread != THREAD_NULL) {
7225 thread_interrupt_level(interruptible_state);
7226 }
7227
7228 vm_map_lock(map);
7229
7230 if (last_timestamp + 1 != map->timestamp) {
7231 /*
7232 * Find the entry again. It could have been clipped
7233 * after we unlocked the map.
7234 */
7235 if (!vm_map_lookup_entry(map, tmp_entry.vme_start,
7236 &first_entry)) {
7237 panic("vm_map_wire: re-lookup failed");
7238 }
7239
7240 entry = first_entry;
7241 }
7242
7243 last_timestamp = map->timestamp;
7244
7245 while ((entry != vm_map_to_entry(map)) &&
7246 (entry->vme_start < tmp_entry.vme_end)) {
7247 assert(entry->in_transition);
7248 entry->in_transition = FALSE;
7249 if (entry->needs_wakeup) {
7250 entry->needs_wakeup = FALSE;
7251 need_wakeup = TRUE;
7252 }
7253 if (rc != KERN_SUCCESS) { /* from vm_*_wire */
7254 subtract_wire_counts(map, entry, user_wire);
7255 }
7256 entry = entry->vme_next;
7257 }
7258
7259 if (rc != KERN_SUCCESS) { /* from vm_*_wire */
7260 goto done;
7261 }
7262
7263 if ((entry != vm_map_to_entry(map)) && /* we still have entries in the map */
7264 (tmp_entry.vme_end != end) && /* AND, we are not at the end of the requested range */
7265 (entry->vme_start != tmp_entry.vme_end)) { /* AND, the next entry is not contiguous. */
7266 /* found a "new" hole */
7267 s = tmp_entry.vme_end;
7268 rc = KERN_INVALID_ADDRESS;
7269 goto done;
7270 }
7271
7272 s = entry->vme_start;
7273 } /* end while loop through map entries */
7274
7275done:
7276 if (rc == KERN_SUCCESS) {
7277 /* repair any damage we may have made to the VM map */
7278 vm_map_simplify_range(map, start, end);
7279 }
7280
7281 vm_map_unlock(map);
7282
7283 /*
7284 * wake up anybody waiting on entries we wired.
7285 */
7286 if (need_wakeup) {
7287 vm_map_entry_wakeup(map);
7288 }
7289
7290 if (rc != KERN_SUCCESS) {
7291 /* undo what has been wired so far */
7292 vm_map_unwire_nested(map, start, s, user_wire,
7293 map_pmap, pmap_addr);
7294 if (physpage_p) {
7295 *physpage_p = 0;
7296 }
7297 }
7298
7299 vmlp_api_end(VM_MAP_WIRE_NESTED, rc);
7300 return rc;
7301}
7302
7303static __attribute__((always_inline, warn_unused_result))
7304kern_return_t
7305vm_map_wire_sanitize(
7306 vm_map_t map,
7307 vm_map_offset_ut start_u,
7308 vm_map_offset_ut end_u,
7309 vm_prot_ut prot_u,
7310 vm_sanitize_caller_t vm_sanitize_caller,
7311 vm_map_offset_t *start,
7312 vm_map_offset_t *end,
7313 vm_map_size_t *size,
7314 vm_prot_t *prot)
7315{
7316 kern_return_t kr;
7317
7318 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
7319
7320
7321 kr = vm_sanitize_addr_end(start_u, end_u, vm_sanitize_caller, map,
7322 flags, start, end, size);
7323 if (__improbable(kr != KERN_SUCCESS)) {
7324 return kr;
7325 }
7326
7327 kr = vm_sanitize_prot(prot_u, vm_sanitize_caller, map, prot);
7328 if (__improbable(kr != KERN_SUCCESS)) {
7329 return kr;
7330 }
7331
7332 return KERN_SUCCESS;
7333}
7334
7335/*
7336 * Validation function for vm_map_wire_nested().
7337 */
7338kern_return_t
7339vm_map_wire_impl(
7340 vm_map_t map,
7341 vm_map_offset_ut start_u,
7342 vm_map_offset_ut end_u,
7343 vm_prot_ut prot_u,
7344 vm_tag_t tag,
7345 boolean_t user_wire,
7346 ppnum_t *physpage_p,
7347 vm_sanitize_caller_t vm_sanitize_caller)
7348{
7349 vm_map_offset_t start, end;
7350 vm_map_size_t size;
7351 vm_prot_t prot;
7352 kern_return_t kr;
7353
7354 /*
7355 * Sanitize any input parameters that are addr/size/prot/inherit
7356 */
7357 kr = vm_map_wire_sanitize(map,
7358 start_u,
7359 end_u,
7360 prot_u,
7361 vm_sanitize_caller,
7362 &start,
7363 &end,
7364 &size,
7365 &prot);
7366 if (__improbable(kr != KERN_SUCCESS)) {
7367 if (physpage_p) {
7368 *physpage_p = 0;
7369 }
7370 return vm_sanitize_get_kr(kr);
7371 }
7372
7373 return vm_map_wire_nested(map, start, end, prot, tag, user_wire,
7374 PMAP_NULL, 0, physpage_p);
7375}
7376
7377kern_return_t
7378vm_map_wire_external(
7379 vm_map_t map,
7380 vm_map_offset_ut start_u,
7381 vm_map_offset_ut end_u,
7382 vm_prot_ut prot_u,
7383 boolean_t user_wire)
7384{
7385 vm_tag_t tag = vm_tag_bt();
7386
7387 return vm_map_wire_kernel(map, start_u, end_u, prot_u, tag, user_wire);
7388}
7389
7390kern_return_t
7391vm_map_wire_kernel(
7392 vm_map_t map,
7393 vm_map_offset_ut start_u,
7394 vm_map_offset_ut end_u,
7395 vm_prot_ut prot_u,
7396 vm_tag_t tag,
7397 boolean_t user_wire)
7398{
7399 return vm_map_wire_impl(map, start_u, end_u, prot_u, tag,
7400 user_wire, NULL, VM_SANITIZE_CALLER_VM_MAP_WIRE);
7401}
7402
7403#if XNU_PLATFORM_MacOSX
7404
7405kern_return_t
7406vm_map_wire_and_extract(
7407 vm_map_t map,
7408 vm_map_offset_ut start_u,
7409 vm_prot_ut prot_u,
7410 boolean_t user_wire,
7411 ppnum_t *physpage_p)
7412{
7413 vm_tag_t tag = vm_tag_bt();
7414 vm_map_size_ut size_u = vm_sanitize_wrap_size(VM_MAP_PAGE_SIZE(map));
7415 vm_map_offset_ut end_u = vm_sanitize_compute_ut_end(start_u, size_u);
7416
7417 return vm_map_wire_impl(map, start_u, end_u, prot_u, tag,
7418 user_wire, physpage_p, VM_SANITIZE_CALLER_VM_MAP_WIRE);
7419}
7420
7421#endif /* XNU_PLATFORM_MacOSX */
7422
7423static kern_return_t
7424vm_map_unwire_nested(
7425 vm_map_t map,
7426 vm_map_offset_t start,
7427 vm_map_offset_t end,
7428 boolean_t user_wire,
7429 pmap_t map_pmap,
7430 vm_map_offset_t pmap_addr)
7431{
7432 vm_map_entry_t entry;
7433 struct vm_map_entry *first_entry, tmp_entry;
7434 boolean_t need_wakeup;
7435 boolean_t main_map = FALSE;
7436 unsigned int last_timestamp;
7437
7438 vmlp_api_start(VM_MAP_UNWIRE_NESTED);
7439
7440 VM_MAP_RANGE_CHECK(map, start, end);
7441 assert(VM_MAP_PAGE_ALIGNED(start, VM_MAP_PAGE_MASK(map)));
7442 assert(VM_MAP_PAGE_ALIGNED(end, VM_MAP_PAGE_MASK(map)));
7443
7444 if (start == end) {
7445 /* We unwired what the caller asked for: zero pages */
7446 vmlp_api_end(VM_MAP_UNWIRE_NESTED, KERN_SUCCESS);
7447 return KERN_SUCCESS;
7448 }
7449
7450 vm_map_lock(map);
7451
7452 vmlp_range_event(map, start, end - start);
7453
7454 if (map_pmap == NULL) {
7455 main_map = TRUE;
7456 }
7457 last_timestamp = map->timestamp;
7458
7459 if (vm_map_lookup_entry(map, start, &first_entry)) {
7460 entry = first_entry;
7461 /*
7462 * vm_map_clip_start will be done later.
7463 * We don't want to unnest any nested sub maps here !
7464 */
7465 } else {
7466 if (!user_wire) {
7467 panic("vm_map_unwire: start not found");
7468 }
7469 /* Start address is not in map. */
7470 vm_map_unlock(map);
7471 vmlp_api_end(VM_MAP_UNWIRE_NESTED, KERN_INVALID_ADDRESS);
7472 return KERN_INVALID_ADDRESS;
7473 }
7474
7475 if (entry->superpage_size) {
7476 /* superpages are always wired */
7477 vm_map_unlock(map);
7478 vmlp_api_end(VM_MAP_UNWIRE_NESTED, KERN_INVALID_ADDRESS);
7479 return KERN_INVALID_ADDRESS;
7480 }
7481
7482 need_wakeup = FALSE;
7483 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
7484 if (entry->in_transition) {
7485 /*
7486 * 1)
7487 * Another thread is wiring down this entry. Note
7488 * that if it is not for the other thread we would
7489 * be unwiring an unwired entry. This is not
7490 * permitted. If we wait, we will be unwiring memory
7491 * we did not wire.
7492 *
7493 * 2)
7494 * Another thread is unwiring this entry. We did not
7495 * have a reference to it, because if we did, this
7496 * entry will not be getting unwired now.
7497 */
7498 if (!user_wire) {
7499 /*
7500 * XXX FBDP
7501 * This could happen: there could be some
7502 * overlapping vslock/vsunlock operations
7503 * going on.
7504 * We should probably just wait and retry,
7505 * but then we have to be careful that this
7506 * entry could get "simplified" after
7507 * "in_transition" gets unset and before
7508 * we re-lookup the entry, so we would
7509 * have to re-clip the entry to avoid
7510 * re-unwiring what we have already unwired...
7511 * See vm_map_wire_nested().
7512 *
7513 * Or we could just ignore "in_transition"
7514 * here and proceed to decement the wired
7515 * count(s) on this entry. That should be fine
7516 * as long as "wired_count" doesn't drop all
7517 * the way to 0 (and we should panic if THAT
7518 * happens).
7519 */
7520 panic("vm_map_unwire: in_transition entry");
7521 }
7522
7523 entry = entry->vme_next;
7524 continue;
7525 }
7526
7527 if (entry->is_sub_map) {
7528 vm_map_offset_t sub_start;
7529 vm_map_offset_t sub_end;
7530 vm_map_offset_t local_end;
7531 pmap_t pmap;
7532 vm_map_t sub_map = VM_MAP_NULL;
7533
7534 vm_map_clip_start(map, entry, start);
7535 vm_map_clip_end(map, entry, end);
7536
7537 sub_start = VME_OFFSET(entry);
7538 sub_end = entry->vme_end - entry->vme_start;
7539 sub_end += VME_OFFSET(entry);
7540 local_end = entry->vme_end;
7541 if (map_pmap == NULL) {
7542 if (entry->use_pmap) {
7543 pmap = VME_SUBMAP(entry)->pmap;
7544 pmap_addr = sub_start;
7545 } else {
7546 pmap = map->pmap;
7547 pmap_addr = start;
7548 }
7549 if (entry->wired_count == 0 ||
7550 (user_wire && entry->user_wired_count == 0)) {
7551 if (!user_wire) {
7552 panic("vm_map_unwire: entry is unwired");
7553 }
7554 entry = entry->vme_next;
7555 continue;
7556 }
7557
7558 /*
7559 * Check for holes
7560 * Holes: Next entry should be contiguous unless
7561 * this is the end of the region.
7562 */
7563 if (((entry->vme_end < end) &&
7564 ((entry->vme_next == vm_map_to_entry(map)) ||
7565 (entry->vme_next->vme_start
7566 > entry->vme_end)))) {
7567 if (!user_wire) {
7568 panic("vm_map_unwire: non-contiguous region");
7569 }
7570/*
7571 * entry = entry->vme_next;
7572 * continue;
7573 */
7574 }
7575
7576 subtract_wire_counts(map, entry, user_wire);
7577
7578 if (entry->wired_count != 0) {
7579 entry = entry->vme_next;
7580 continue;
7581 }
7582
7583 entry->in_transition = TRUE;
7584 tmp_entry = *entry;/* see comment in vm_map_wire() */
7585
7586 /*
7587 * We can unlock the map now. The in_transition state
7588 * guarantees existance of the entry.
7589 */
7590 sub_map = VME_SUBMAP(entry);
7591 vm_map_reference(sub_map);
7592 vm_map_unlock(map);
7593 vm_map_unwire_nested(sub_map,
7594 sub_start, sub_end, user_wire, pmap, pmap_addr);
7595 vm_map_deallocate(sub_map);
7596 sub_map = VM_MAP_NULL;
7597 vm_map_lock(map);
7598
7599 if (last_timestamp + 1 != map->timestamp) {
7600 /*
7601 * Find the entry again. It could have been
7602 * clipped or deleted after we unlocked the map.
7603 */
7604 if (!vm_map_lookup_entry(map,
7605 tmp_entry.vme_start,
7606 &first_entry)) {
7607 if (!user_wire) {
7608 panic("vm_map_unwire: re-lookup failed");
7609 }
7610 entry = first_entry->vme_next;
7611 } else {
7612 entry = first_entry;
7613 }
7614 }
7615 last_timestamp = map->timestamp;
7616
7617 /*
7618 * clear transition bit for all constituent entries
7619 * that were in the original entry (saved in
7620 * tmp_entry). Also check for waiters.
7621 */
7622 while ((entry != vm_map_to_entry(map)) &&
7623 (entry->vme_start < tmp_entry.vme_end)) {
7624 assert(entry->in_transition);
7625 entry->in_transition = FALSE;
7626 if (entry->needs_wakeup) {
7627 entry->needs_wakeup = FALSE;
7628 need_wakeup = TRUE;
7629 }
7630 entry = entry->vme_next;
7631 }
7632 continue;
7633 } else {
7634 tmp_entry = *entry;
7635 sub_map = VME_SUBMAP(entry);
7636 vm_map_reference(sub_map);
7637 vm_map_unlock(map);
7638 vm_map_unwire_nested(sub_map,
7639 sub_start, sub_end, user_wire, map_pmap,
7640 pmap_addr);
7641 vm_map_deallocate(sub_map);
7642 sub_map = VM_MAP_NULL;
7643 vm_map_lock(map);
7644
7645 if (last_timestamp + 1 != map->timestamp) {
7646 /*
7647 * Find the entry again. It could have been
7648 * clipped or deleted after we unlocked the map.
7649 */
7650 if (!vm_map_lookup_entry(map,
7651 tmp_entry.vme_start,
7652 &first_entry)) {
7653 if (!user_wire) {
7654 panic("vm_map_unwire: re-lookup failed");
7655 }
7656 entry = first_entry->vme_next;
7657 } else {
7658 entry = first_entry;
7659 }
7660 }
7661 last_timestamp = map->timestamp;
7662 }
7663 }
7664
7665
7666 if ((entry->wired_count == 0) ||
7667 (user_wire && entry->user_wired_count == 0)) {
7668 if (!user_wire) {
7669 panic("vm_map_unwire: entry is unwired");
7670 }
7671
7672 entry = entry->vme_next;
7673 continue;
7674 }
7675
7676 assert(entry->wired_count > 0 &&
7677 (!user_wire || entry->user_wired_count > 0));
7678
7679 vm_map_clip_start(map, entry, start);
7680 vm_map_clip_end(map, entry, end);
7681
7682 /*
7683 * Check for holes
7684 * Holes: Next entry should be contiguous unless
7685 * this is the end of the region.
7686 */
7687 if (((entry->vme_end < end) &&
7688 ((entry->vme_next == vm_map_to_entry(map)) ||
7689 (entry->vme_next->vme_start > entry->vme_end)))) {
7690 if (!user_wire) {
7691 panic("vm_map_unwire: non-contiguous region");
7692 }
7693 /*
7694 * entry = entry->vme_next;
7695 * continue;
7696 */
7697 }
7698
7699 subtract_wire_counts(map, entry, user_wire);
7700
7701 if (entry->wired_count != 0) {
7702 entry = entry->vme_next;
7703 continue;
7704 }
7705
7706 if (entry->zero_wired_pages) {
7707 entry->zero_wired_pages = FALSE;
7708 }
7709
7710 entry->in_transition = TRUE;
7711 tmp_entry = *entry; /* see comment in vm_map_wire() */
7712
7713 /*
7714 * We can unlock the map now. The in_transition state
7715 * guarantees existance of the entry.
7716 */
7717 vm_map_unlock(map);
7718 if (map_pmap) {
7719 vm_fault_unwire(map, &tmp_entry, FALSE, map_pmap,
7720 pmap_addr, tmp_entry.vme_end);
7721 } else {
7722 vm_fault_unwire(map, &tmp_entry, FALSE, map->pmap,
7723 tmp_entry.vme_start, tmp_entry.vme_end);
7724 }
7725 vm_map_lock(map);
7726
7727 if (last_timestamp + 1 != map->timestamp) {
7728 /*
7729 * Find the entry again. It could have been clipped
7730 * or deleted after we unlocked the map.
7731 */
7732 if (!vm_map_lookup_entry(map, tmp_entry.vme_start,
7733 &first_entry)) {
7734 if (!user_wire) {
7735 panic("vm_map_unwire: re-lookup failed");
7736 }
7737 entry = first_entry->vme_next;
7738 } else {
7739 entry = first_entry;
7740 }
7741 }
7742 last_timestamp = map->timestamp;
7743
7744 /*
7745 * clear transition bit for all constituent entries that
7746 * were in the original entry (saved in tmp_entry). Also
7747 * check for waiters.
7748 */
7749 while ((entry != vm_map_to_entry(map)) &&
7750 (entry->vme_start < tmp_entry.vme_end)) {
7751 assert(entry->in_transition);
7752 entry->in_transition = FALSE;
7753 if (entry->needs_wakeup) {
7754 entry->needs_wakeup = FALSE;
7755 need_wakeup = TRUE;
7756 }
7757 entry = entry->vme_next;
7758 }
7759 }
7760
7761 /*
7762 * We might have fragmented the address space when we wired this
7763 * range of addresses. Attempt to re-coalesce these VM map entries
7764 * with their neighbors now that they're no longer wired.
7765 * Under some circumstances, address space fragmentation can
7766 * prevent VM object shadow chain collapsing, which can cause
7767 * swap space leaks.
7768 */
7769 vm_map_simplify_range(map, start, end);
7770
7771 vm_map_unlock(map);
7772 /*
7773 * wake up anybody waiting on entries that we have unwired.
7774 */
7775 if (need_wakeup) {
7776 vm_map_entry_wakeup(map);
7777 }
7778 vmlp_api_end(VM_MAP_UNWIRE_NESTED, KERN_SUCCESS);
7779 return KERN_SUCCESS;
7780}
7781
7782kern_return_t
7783vm_map_unwire(
7784 vm_map_t map,
7785 vm_map_offset_ut start_u,
7786 vm_map_offset_ut end_u,
7787 boolean_t user_wire)
7788{
7789 return vm_map_unwire_impl(map, start_u, end_u, user_wire,
7790 VM_SANITIZE_CALLER_VM_MAP_UNWIRE);
7791}
7792
7793static __attribute__((always_inline, warn_unused_result))
7794kern_return_t
7795vm_map_unwire_sanitize(
7796 vm_map_t map,
7797 vm_map_offset_ut start_u,
7798 vm_map_offset_ut end_u,
7799 vm_sanitize_caller_t vm_sanitize_caller,
7800 vm_map_offset_t *start,
7801 vm_map_offset_t *end,
7802 vm_map_size_t *size)
7803{
7804 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
7805
7806
7807 return vm_sanitize_addr_end(start_u, end_u, vm_sanitize_caller, map,
7808 flags, start, end, size);
7809}
7810
7811kern_return_t
7812vm_map_unwire_impl(
7813 vm_map_t map,
7814 vm_map_offset_ut start_u,
7815 vm_map_offset_ut end_u,
7816 boolean_t user_wire,
7817 vm_sanitize_caller_t vm_sanitize_caller)
7818{
7819 vm_map_offset_t start, end;
7820 vm_map_size_t size;
7821 kern_return_t kr;
7822
7823 /*
7824 * Sanitize any input parameters that are addr/size/prot/inherit
7825 */
7826 kr = vm_map_unwire_sanitize(
7827 map,
7828 start_u,
7829 end_u,
7830 vm_sanitize_caller,
7831 &start,
7832 &end,
7833 &size);
7834 if (__improbable(kr != KERN_SUCCESS)) {
7835 return vm_sanitize_get_kr(kr);
7836 }
7837
7838 return vm_map_unwire_nested(map, start, end,
7839 user_wire, (pmap_t)NULL, 0);
7840}
7841
7842
7843/*
7844 * vm_map_entry_zap: [ internal use only ]
7845 *
7846 * Remove the entry from the target map
7847 * and put it on a zap list.
7848 */
7849static void
7850vm_map_entry_zap(
7851 vm_map_t map,
7852 vm_map_entry_t entry,
7853 vm_map_zap_t zap)
7854{
7855 vm_map_offset_t s, e;
7856
7857 s = entry->vme_start;
7858 e = entry->vme_end;
7859 assert(VM_MAP_PAGE_ALIGNED(s, VM_MAP_PAGE_MASK(map)));
7860 assert(VM_MAP_PAGE_ALIGNED(e, VM_MAP_PAGE_MASK(map)));
7861 assert(entry->wired_count == 0);
7862 assert(entry->user_wired_count == 0);
7863 assert(!entry->vme_permanent);
7864
7865 vm_map_store_entry_unlink(map, entry, false);
7866 map->size -= e - s;
7867
7868 vm_map_zap_append(zap, entry);
7869}
7870
7871static void
7872vm_map_submap_pmap_clean(
7873 vm_map_t map,
7874 vm_map_offset_t start,
7875 vm_map_offset_t end,
7876 vm_map_t sub_map,
7877 vm_map_offset_t offset)
7878{
7879 vm_map_offset_t submap_start;
7880 vm_map_offset_t submap_end;
7881 vm_map_size_t remove_size;
7882 vm_map_entry_t entry;
7883
7884 vmlp_api_start(VM_MAP_SUBMAP_PMAP_CLEAN);
7885
7886 submap_end = offset + (end - start);
7887 submap_start = offset;
7888
7889 vm_map_lock_read(sub_map);
7890 if (vm_map_lookup_entry(sub_map, offset, &entry)) {
7891 remove_size = (entry->vme_end - entry->vme_start);
7892 if (offset > entry->vme_start) {
7893 remove_size -= offset - entry->vme_start;
7894 }
7895
7896
7897 if (submap_end < entry->vme_end) {
7898 remove_size -=
7899 entry->vme_end - submap_end;
7900 }
7901 if (entry->is_sub_map) {
7902 vm_map_submap_pmap_clean(
7903 sub_map,
7904 start,
7905 start + remove_size,
7906 VME_SUBMAP(entry),
7907 VME_OFFSET(entry));
7908 } else {
7909 vmlp_range_event_entry(sub_map, entry);
7910 if (map->mapped_in_other_pmaps &&
7911 os_ref_get_count_raw(&map->map_refcnt) != 0 &&
7912 VME_OBJECT(entry) != NULL) {
7913 vm_object_pmap_protect_options(
7914 VME_OBJECT(entry),
7915 (VME_OFFSET(entry) +
7916 offset -
7917 entry->vme_start),
7918 remove_size,
7919 PMAP_NULL,
7920 PAGE_SIZE,
7921 entry->vme_start,
7922 VM_PROT_NONE,
7923 PMAP_OPTIONS_REMOVE);
7924 } else {
7925 pmap_remove(map->pmap,
7926 (addr64_t)start,
7927 (addr64_t)(start + remove_size));
7928 }
7929 }
7930 }
7931
7932 entry = entry->vme_next;
7933
7934 while ((entry != vm_map_to_entry(sub_map))
7935 && (entry->vme_start < submap_end)) {
7936 remove_size = (entry->vme_end - entry->vme_start);
7937 if (submap_end < entry->vme_end) {
7938 remove_size -= entry->vme_end - submap_end;
7939 }
7940 if (entry->is_sub_map) {
7941 vm_map_submap_pmap_clean(
7942 sub_map,
7943 (start + entry->vme_start) - offset,
7944 ((start + entry->vme_start) - offset) + remove_size,
7945 VME_SUBMAP(entry),
7946 VME_OFFSET(entry));
7947 } else {
7948 vmlp_range_event_entry(sub_map, entry);
7949 if (map->mapped_in_other_pmaps &&
7950 os_ref_get_count_raw(&map->map_refcnt) != 0 &&
7951 VME_OBJECT(entry) != NULL) {
7952 vm_object_pmap_protect_options(
7953 VME_OBJECT(entry),
7954 VME_OFFSET(entry),
7955 remove_size,
7956 PMAP_NULL,
7957 PAGE_SIZE,
7958 entry->vme_start,
7959 VM_PROT_NONE,
7960 PMAP_OPTIONS_REMOVE);
7961 } else {
7962 pmap_remove(map->pmap,
7963 (addr64_t)((start + entry->vme_start)
7964 - offset),
7965 (addr64_t)(((start + entry->vme_start)
7966 - offset) + remove_size));
7967 }
7968 }
7969 entry = entry->vme_next;
7970 }
7971 vm_map_unlock_read(sub_map);
7972 vmlp_api_end(VM_MAP_SUBMAP_PMAP_CLEAN, 0);
7973 return;
7974}
7975
7976
7977
7978/*
7979 * virt_memory_guard_ast:
7980 *
7981 * Handle the AST callout for a virtual memory guard.
7982 * raise an EXC_GUARD exception and terminate the task
7983 * if configured to do so.
7984 */
7985void
7986virt_memory_guard_ast(
7987 thread_t thread,
7988 mach_exception_data_type_t code,
7989 mach_exception_data_type_t subcode)
7990{
7991 task_t task = get_threadtask(thread);
7992 assert(task != kernel_task);
7993 assert(task == current_task());
7994 kern_return_t sync_exception_result;
7995 uint32_t behavior;
7996
7997 behavior = task->task_exc_guard;
7998
7999
8000 /* Is delivery enabled */
8001 if ((behavior & TASK_EXC_GUARD_VM_DELIVER) == 0) {
8002 return;
8003 }
8004
8005 /* If only once, make sure we're that once */
8006 while (behavior & TASK_EXC_GUARD_VM_ONCE) {
8007 uint32_t new_behavior = behavior & ~TASK_EXC_GUARD_VM_DELIVER;
8008
8009 if (OSCompareAndSwap(behavior, new_behavior, &task->task_exc_guard)) {
8010 break;
8011 }
8012 behavior = task->task_exc_guard;
8013 if ((behavior & TASK_EXC_GUARD_VM_DELIVER) == 0) {
8014 return;
8015 }
8016 }
8017
8018 const bool fatal = task->task_exc_guard & TASK_EXC_GUARD_VM_FATAL;
8019 /* Raise exception synchronously and see if handler claimed it */
8020 sync_exception_result = task_exception_notify(EXC_GUARD, code, subcode, fatal);
8021
8022 if (fatal) {
8023 /*
8024 * If Synchronous EXC_GUARD delivery was successful then
8025 * kill the process and return, else kill the process
8026 * and deliver the exception via EXC_CORPSE_NOTIFY.
8027 */
8028
8029
8030 int flags = PX_DEBUG_NO_HONOR;
8031 exception_info_t info = {
8032 .os_reason = OS_REASON_GUARD,
8033 .exception_type = EXC_GUARD,
8034 .mx_code = code,
8035 .mx_subcode = subcode
8036 };
8037
8038 if (sync_exception_result == KERN_SUCCESS) {
8039 flags |= PX_PSIGNAL;
8040 }
8041 exit_with_mach_exception(current_proc(), info, flags);
8042 } else if (task->task_exc_guard & TASK_EXC_GUARD_VM_CORPSE) {
8043 /*
8044 * If the synchronous EXC_GUARD delivery was not successful,
8045 * raise a simulated crash.
8046 */
8047 if (sync_exception_result != KERN_SUCCESS) {
8048 task_violated_guard(code, subcode, NULL, FALSE);
8049 }
8050 }
8051}
8052
8053/*
8054 * Validate policy for VM guard exceptions and encode the correct Mach exception
8055 * code and subcode if the policy allows delivering a guard exception here.
8056 */
8057static bool
8058vm_map_guard_exception_internal(
8059 vm_map_offset_t address,
8060 unsigned reason,
8061 mach_exception_code_t *code,
8062 mach_exception_data_type_t *subcode)
8063{
8064 unsigned int guard_type = GUARD_TYPE_VIRT_MEMORY;
8065 unsigned int target = 0; /* should we pass in pid associated with map? */
8066
8067 task_t task = current_task_early();
8068
8069 /* Can't deliver exceptions to a NULL task (early boot) or kernel task */
8070 if (task == NULL || task == kernel_task) {
8071 return false;
8072 }
8073
8074 *code = 0;
8075 EXC_GUARD_ENCODE_TYPE(*code, guard_type);
8076 EXC_GUARD_ENCODE_FLAVOR(*code, reason);
8077 EXC_GUARD_ENCODE_TARGET(*code, target);
8078 *subcode = (uint64_t)address;
8079
8080 return true;
8081}
8082
8083/*
8084 * vm_map_guard_exception:
8085 *
8086 * Generate a GUARD_TYPE_VIRTUAL_MEMORY EXC_GUARD exception.
8087 *
8088 * `reason` is kGUARD_EXC_DEALLOC_GAP when we find nothing mapped,
8089 * or if there is a gap in the mapping when a user address space
8090 * was requested. We report the address of the first gap found.
8091 */
8092
8093void
8094vm_map_guard_exception(
8095 vm_map_offset_t address,
8096 unsigned reason)
8097{
8098 mach_exception_code_t code;
8099 mach_exception_data_type_t subcode;
8100 if (vm_map_guard_exception_internal(address, reason, &code, &subcode)) {
8101 task_t task = current_task();
8102 bool fatal = task->task_exc_guard & TASK_EXC_GUARD_VM_FATAL;
8103 thread_guard_violation(current_thread(), code, subcode, fatal);
8104 }
8105}
8106
8107
8108static kern_return_t
8109vm_map_delete_submap_recurse(
8110 vm_map_t submap,
8111 vm_map_offset_t submap_start,
8112 vm_map_offset_t submap_end)
8113{
8114 vm_map_entry_t submap_entry;
8115
8116 vmlp_api_start(VM_MAP_DELETE_SUBMAP_RECURSE);
8117
8118 /*
8119 * Verify that the submap does not contain any "permanent" entries
8120 * within the specified range. We permit TPRO ranges to be overwritten
8121 * as we only reach this path if TPRO const protection is disabled for a
8122 * given map.
8123 *
8124 * We do not care about gaps.
8125 */
8126
8127 vm_map_lock_read(submap);
8128
8129 if (!vm_map_lookup_entry(submap, submap_start, &submap_entry)) {
8130 submap_entry = submap_entry->vme_next;
8131 }
8132
8133 for (;
8134 submap_entry != vm_map_to_entry(submap) &&
8135 submap_entry->vme_start < submap_end;
8136 submap_entry = submap_entry->vme_next) {
8137 vmlp_range_event_entry(submap, submap_entry);
8138 if (submap_entry->vme_permanent
8139#ifdef __arm64e__
8140 /* allow TPRO submap entries to be overwritten */
8141 && !submap_entry->used_for_tpro
8142#endif
8143 ) {
8144 /* "permanent" entry -> fail */
8145 vm_map_unlock_read(submap);
8146 vmlp_api_end(VM_MAP_DELETE_SUBMAP_RECURSE, KERN_PROTECTION_FAILURE);
8147 return KERN_PROTECTION_FAILURE;
8148 }
8149 }
8150 /* no "permanent" entries in the range -> success */
8151 vm_map_unlock_read(submap);
8152 vmlp_api_end(VM_MAP_DELETE_SUBMAP_RECURSE, KERN_SUCCESS);
8153 return KERN_SUCCESS;
8154}
8155
8156__abortlike
8157static void
8158__vm_map_delete_misaligned_panic(
8159 vm_map_t map,
8160 vm_map_offset_t start,
8161 vm_map_offset_t end)
8162{
8163 panic("vm_map_delete(%p,0x%llx,0x%llx): start is not aligned to 0x%x",
8164 map, (uint64_t)start, (uint64_t)end, VM_MAP_PAGE_SIZE(map));
8165}
8166
8167__abortlike
8168static void
8169__vm_map_delete_failed_panic(
8170 vm_map_t map,
8171 vm_map_offset_t start,
8172 vm_map_offset_t end,
8173 kern_return_t kr)
8174{
8175 panic("vm_map_delete(%p,0x%llx,0x%llx): failed unexpected with %d",
8176 map, (uint64_t)start, (uint64_t)end, kr);
8177}
8178
8179__abortlike
8180static void
8181__vm_map_delete_gap_panic(
8182 vm_map_t map,
8183 vm_map_offset_t where,
8184 vm_map_offset_t start,
8185 vm_map_offset_t end)
8186{
8187 panic("vm_map_delete(%p,0x%llx,0x%llx): no map entry at 0x%llx",
8188 map, (uint64_t)start, (uint64_t)end, (uint64_t)where);
8189}
8190
8191__abortlike
8192static void
8193__vm_map_delete_permanent_panic(
8194 vm_map_t map,
8195 vm_map_offset_t start,
8196 vm_map_offset_t end,
8197 vm_map_entry_t entry)
8198{
8199 panic("vm_map_delete(%p,0x%llx,0x%llx): "
8200 "Attempting to remove permanent VM map entry %p [0x%llx:0x%llx]",
8201 map, (uint64_t)start, (uint64_t)end, entry,
8202 (uint64_t)entry->vme_start,
8203 (uint64_t)entry->vme_end);
8204}
8205
8206__options_decl(vm_map_delete_state_t, uint32_t, {
8207 VMDS_NONE = 0x0000,
8208
8209 VMDS_FOUND_GAP = 0x0001,
8210 VMDS_GAPS_OK = 0x0002,
8211
8212 VMDS_KERNEL_PMAP = 0x0004,
8213 VMDS_NEEDS_LOOKUP = 0x0008,
8214 VMDS_NEEDS_WAKEUP = 0x0010,
8215 VMDS_KERNEL_KMEMPTR = 0x0020
8216});
8217
8218/*
8219 * vm_map_clamp_to_pmap(map, start, end)
8220 *
8221 * Modify *start and *end so they fall within the bounds of map->pmap.
8222 */
8223#if MACH_ASSERT
8224static void
8225vm_map_clamp_to_pmap(vm_map_t map, vm_map_address_t *start, vm_map_address_t *end)
8226{
8227 vm_map_address_t min;
8228 vm_map_address_t max;
8229
8230#if __x86_64__
8231 /* x86_64 struct pmap does not have min and max fields */
8232 if (map->pmap == kernel_pmap) {
8233 min = VM_MIN_KERNEL_AND_KEXT_ADDRESS;
8234 max = VM_MAX_KERNEL_ADDRESS;
8235 } else {
8236 min = VM_MAP_MIN_ADDRESS;
8237 max = VM_MAP_MAX_ADDRESS;
8238 }
8239#else
8240 min = map->pmap->min;
8241 max = map->pmap->max;
8242#endif
8243
8244 if (*start < min) {
8245 *start = min;
8246 } else if (*start > max) {
8247 *start = max;
8248 }
8249 if (*end < min) {
8250 *end = min;
8251 } else if (*end > max) {
8252 *end = max;
8253 }
8254}
8255#endif
8256
8257int vm_log_map_delete_permanent_prot_none = 0;
8258/*
8259 * vm_map_delete: [ internal use only ]
8260 *
8261 * Deallocates the given address range from the target map.
8262 * Removes all user wirings. Unwires one kernel wiring if
8263 * VM_MAP_REMOVE_KUNWIRE is set. Waits for kernel wirings to go
8264 * away if VM_MAP_REMOVE_WAIT_FOR_KWIRE is set. Sleeps
8265 * interruptibly if VM_MAP_REMOVE_INTERRUPTIBLE is set.
8266 *
8267 *
8268 * When the map is a kernel map, then any error in removing mappings
8269 * will lead to a panic so that clients do not have to repeat the panic
8270 * code at each call site. If VM_MAP_REMOVE_INTERRUPTIBLE
8271 * is also passed, then KERN_ABORTED will not lead to a panic.
8272 *
8273 * This routine is called with map locked and leaves map locked.
8274 */
8275static kmem_return_t
8276vm_map_delete(
8277 vm_map_t map,
8278 vm_map_offset_t start,
8279 vm_map_offset_t end,
8280 vmr_flags_t flags,
8281 kmem_guard_t guard,
8282 vm_map_zap_t zap_list)
8283{
8284 vm_map_entry_t entry, next;
8285 int interruptible;
8286 vm_map_offset_t gap_start = 0;
8287 vm_map_offset_t clear_in_transition_end = 0;
8288 __unused vm_map_offset_t save_start = start;
8289 __unused vm_map_offset_t save_end = end;
8290 vm_map_delete_state_t state = VMDS_NONE;
8291 kmem_return_t ret = { };
8292 vm_map_range_id_t range_id = 0;
8293 struct kmem_page_meta *meta = NULL;
8294 uint32_t size_idx, slot_idx;
8295 struct mach_vm_range slot;
8296
8297 vmlp_api_start(VM_MAP_DELETE);
8298 vmlp_range_event(map, start, end - start);
8299
8300 if (vm_map_pmap(map) == kernel_pmap) {
8301 state |= VMDS_KERNEL_PMAP;
8302 range_id = kmem_addr_get_range(start, end - start);
8303 if (kmem_is_ptr_range(range_id)) {
8304 state |= VMDS_KERNEL_KMEMPTR;
8305 slot_idx = kmem_addr_get_slot_idx(start, end, range_id, &meta,
8306 &size_idx, &slot);
8307 }
8308 }
8309
8310 if (map->terminated || os_ref_get_count_raw(&map->map_refcnt) == 0) {
8311 state |= VMDS_GAPS_OK;
8312 }
8313
8314 if (map->corpse_source &&
8315 !(flags & VM_MAP_REMOVE_TO_OVERWRITE) &&
8316 !map->terminated) {
8317 /*
8318 * The map is being used for corpses related diagnostics.
8319 * So skip any entry removal to avoid perturbing the map state.
8320 * The cleanup will happen in task_terminate_internal after the
8321 * call to task_port_no_senders.
8322 */
8323 goto out;
8324 }
8325
8326 interruptible = (flags & VM_MAP_REMOVE_INTERRUPTIBLE) ?
8327 THREAD_ABORTSAFE : THREAD_UNINT;
8328
8329 if (start & VM_MAP_PAGE_MASK(map)) {
8330 __vm_map_delete_misaligned_panic(map, start, end);
8331 }
8332
8333 if ((state & VMDS_GAPS_OK) == 0) {
8334 /*
8335 * If the map isn't terminated then all deletions must have
8336 * no gaps, and be within the [min, max) of the map.
8337 *
8338 * We got here without VM_MAP_RANGE_CHECK() being called,
8339 * and hence must validate bounds manually.
8340 *
8341 * It is worth noting that because vm_deallocate() will
8342 * round_page() the deallocation size, it's possible for "end"
8343 * to be 0 here due to overflow. We hence must treat it as being
8344 * beyond vm_map_max(map).
8345 *
8346 * Similarly, end < start means some wrap around happend,
8347 * which should cause an error or panic.
8348 */
8349 if (end == 0 || end > vm_map_max(map)) {
8350 state |= VMDS_FOUND_GAP;
8351 gap_start = vm_map_max(map);
8352 if (state & VMDS_KERNEL_PMAP) {
8353 __vm_map_delete_gap_panic(map,
8354 gap_start, start, end);
8355 }
8356 goto out;
8357 }
8358
8359 if (end < start) {
8360 if (state & VMDS_KERNEL_PMAP) {
8361 __vm_map_delete_gap_panic(map,
8362 vm_map_max(map), start, end);
8363 }
8364 ret.kmr_return = KERN_INVALID_ARGUMENT;
8365 goto out;
8366 }
8367
8368 if (start < vm_map_min(map)) {
8369 state |= VMDS_FOUND_GAP;
8370 gap_start = start;
8371 if (state & VMDS_KERNEL_PMAP) {
8372 __vm_map_delete_gap_panic(map,
8373 gap_start, start, end);
8374 }
8375 goto out;
8376 }
8377 } else {
8378 /*
8379 * If the map is terminated, we must accept start/end
8380 * being beyond the boundaries of the map as this is
8381 * how some of the mappings like commpage mappings
8382 * can be destroyed (they're outside of those bounds).
8383 *
8384 * end < start is still something we can't cope with,
8385 * so just bail.
8386 */
8387 if (end < start) {
8388 goto out;
8389 }
8390 }
8391
8392
8393 /*
8394 * Find the start of the region.
8395 *
8396 * If in a superpage, extend the range
8397 * to include the start of the mapping.
8398 */
8399 while (vm_map_lookup_entry_or_next(map, start, &entry)) {
8400 if (entry->superpage_size && (start & ~SUPERPAGE_MASK)) {
8401 start = SUPERPAGE_ROUND_DOWN(start);
8402 } else {
8403 SAVE_HINT_MAP_WRITE(map, VME_PREV(entry));
8404 break;
8405 }
8406 }
8407
8408 if (entry->superpage_size) {
8409 end = SUPERPAGE_ROUND_UP(end);
8410 }
8411
8412 /*
8413 * Step through all entries in this region
8414 */
8415 for (vm_map_offset_t s = start; s < end;) {
8416 /*
8417 * At this point, we have deleted all the memory entries
8418 * in [start, s) and are proceeding with the [s, end) range.
8419 *
8420 * This loop might drop the map lock, and it is possible that
8421 * some memory was already reallocated within [start, s)
8422 * and we don't want to mess with those entries.
8423 *
8424 * Some of those entries could even have been re-assembled
8425 * with an entry after "s" (in vm_map_simplify_entry()), so
8426 * we may have to vm_map_clip_start() again.
8427 *
8428 * When clear_in_transition_end is set, the we had marked
8429 * [start, clear_in_transition_end) as "in_transition"
8430 * during a previous iteration and we need to clear it.
8431 */
8432
8433 /*
8434 * Step 1: If needed (because we dropped locks),
8435 * lookup the entry again.
8436 *
8437 * If we're coming back from unwiring (Step 5),
8438 * we also need to mark the entries as no longer
8439 * in transition after that.
8440 */
8441
8442 if (state & VMDS_NEEDS_LOOKUP) {
8443 state &= ~VMDS_NEEDS_LOOKUP;
8444
8445 if (vm_map_lookup_entry_or_next(map, s, &entry)) {
8446 SAVE_HINT_MAP_WRITE(map, VME_PREV(entry));
8447 }
8448
8449 if (state & VMDS_KERNEL_KMEMPTR) {
8450 kmem_validate_slot(s, meta, size_idx, slot_idx);
8451 }
8452 }
8453
8454 if (clear_in_transition_end) {
8455 for (vm_map_entry_t it = entry;
8456 it != vm_map_to_entry(map) &&
8457 it->vme_start < clear_in_transition_end;
8458 it = it->vme_next) {
8459 assert(it->in_transition);
8460 it->in_transition = FALSE;
8461 if (it->needs_wakeup) {
8462 it->needs_wakeup = FALSE;
8463 state |= VMDS_NEEDS_WAKEUP;
8464 }
8465 }
8466
8467 clear_in_transition_end = 0;
8468 }
8469
8470
8471 /*
8472 * Step 2: Perform various policy checks
8473 * before we do _anything_ to this entry.
8474 */
8475
8476 if (entry == vm_map_to_entry(map) || s < entry->vme_start) {
8477 if (state & (VMDS_GAPS_OK | VMDS_FOUND_GAP)) {
8478 /*
8479 * Either we found a gap already,
8480 * or we are tearing down a map,
8481 * keep going.
8482 */
8483 } else if (state & VMDS_KERNEL_PMAP) {
8484 __vm_map_delete_gap_panic(map, s, start, end);
8485 } else if (s < end) {
8486 state |= VMDS_FOUND_GAP;
8487 gap_start = s;
8488 }
8489
8490 if (entry == vm_map_to_entry(map) ||
8491 end <= entry->vme_start) {
8492 break;
8493 }
8494
8495 s = entry->vme_start;
8496 }
8497
8498 if (state & VMDS_KERNEL_PMAP) {
8499 /*
8500 * In the kernel map and its submaps,
8501 * permanent entries never die, even
8502 * if VM_MAP_REMOVE_IMMUTABLE is passed.
8503 */
8504 if (entry->vme_permanent) {
8505 __vm_map_delete_permanent_panic(map, start, end, entry);
8506 }
8507
8508 if (flags & VM_MAP_REMOVE_GUESS_SIZE) {
8509 end = entry->vme_end;
8510 flags &= ~VM_MAP_REMOVE_GUESS_SIZE;
8511 }
8512
8513 /*
8514 * In the kernel map and its submaps,
8515 * the removal of an atomic/guarded entry is strict.
8516 *
8517 * An atomic entry is processed only if it was
8518 * specifically targeted.
8519 *
8520 * We might have deleted non-atomic entries before
8521 * we reach this this point however...
8522 */
8523 kmem_entry_validate_guard(map, entry,
8524 start, end - start, guard);
8525 }
8526
8527 /*
8528 * Step 2.1: handle "permanent" and "submap" entries
8529 * *before* clipping to avoid triggering some unnecessary
8530 * un-nesting of the shared region.
8531 */
8532 if (entry->vme_permanent && entry->is_sub_map) {
8533// printf("FBDP %s:%d permanent submap...\n", __FUNCTION__, __LINE__);
8534 /*
8535 * Un-mapping a "permanent" mapping of a user-space
8536 * submap is not allowed unless...
8537 */
8538 if (flags & VM_MAP_REMOVE_IMMUTABLE) {
8539 /*
8540 * a. explicitly requested by the kernel caller.
8541 */
8542// printf("FBDP %s:%d flags & REMOVE_IMMUTABLE\n", __FUNCTION__, __LINE__);
8543 } else if ((flags & VM_MAP_REMOVE_IMMUTABLE_CODE) &&
8544 developer_mode_state()) {
8545 /*
8546 * b. we're in "developer" mode (for
8547 * breakpoints, dtrace probes, ...).
8548 */
8549// printf("FBDP %s:%d flags & REMOVE_IMMUTABLE_CODE\n", __FUNCTION__, __LINE__);
8550 } else if (map->terminated) {
8551 /*
8552 * c. this is the final address space cleanup.
8553 */
8554// printf("FBDP %s:%d map->terminated\n", __FUNCTION__, __LINE__);
8555 } else {
8556 vm_map_offset_t submap_start, submap_end;
8557 kern_return_t submap_kr;
8558
8559 /*
8560 * Check if there are any "permanent" mappings
8561 * in this range in the submap.
8562 */
8563 if (entry->in_transition) {
8564 /* can that even happen ? */
8565 goto in_transition;
8566 }
8567 /* compute the clipped range in the submap */
8568 submap_start = s - entry->vme_start;
8569 submap_start += VME_OFFSET(entry);
8570 submap_end = end - entry->vme_start;
8571 submap_end += VME_OFFSET(entry);
8572 submap_kr = vm_map_delete_submap_recurse(
8573 VME_SUBMAP(entry),
8574 submap_start,
8575 submap_end);
8576 if (submap_kr != KERN_SUCCESS) {
8577 /*
8578 * There are some "permanent" mappings
8579 * in the submap: we are not allowed
8580 * to remove this range.
8581 */
8582 printf("%d[%s] removing permanent submap entry "
8583 "%p [0x%llx:0x%llx] prot 0x%x/0x%x -> KERN_PROT_FAILURE\n",
8584 proc_selfpid(),
8585 (get_bsdtask_info(current_task())
8586 ? proc_name_address(get_bsdtask_info(current_task()))
8587 : "?"), entry,
8588 (uint64_t)entry->vme_start,
8589 (uint64_t)entry->vme_end,
8590 entry->protection,
8591 entry->max_protection);
8592 DTRACE_VM6(vm_map_delete_permanent_deny_submap,
8593 vm_map_entry_t, entry,
8594 vm_map_offset_t, entry->vme_start,
8595 vm_map_offset_t, entry->vme_end,
8596 vm_prot_t, entry->protection,
8597 vm_prot_t, entry->max_protection,
8598 int, VME_ALIAS(entry));
8599 ret.kmr_return = KERN_PROTECTION_FAILURE;
8600 goto out;
8601 }
8602 /* no permanent mappings: proceed */
8603 }
8604 }
8605
8606 /*
8607 * Step 3: Perform any clipping needed.
8608 *
8609 * After this, "entry" starts at "s", ends before "end"
8610 */
8611
8612 if (entry->vme_start < s) {
8613 vm_map_clip_start(map, entry, s);
8614 SAVE_HINT_MAP_WRITE(map, VME_PREV(entry));
8615 }
8616
8617 if (end < entry->vme_end) {
8618 vm_map_clip_end(map, entry, end);
8619 }
8620
8621 if (entry->vme_permanent && entry->is_sub_map) {
8622 /*
8623 * We already went through step 2.1 which did not deny
8624 * the removal of this "permanent" and "is_sub_map"
8625 * entry.
8626 * Now that we've clipped what we actually want to
8627 * delete, undo the "permanent" part to allow the
8628 * removal to proceed.
8629 */
8630 DTRACE_VM6(vm_map_delete_permanent_allow_submap,
8631 vm_map_entry_t, entry,
8632 vm_map_offset_t, entry->vme_start,
8633 vm_map_offset_t, entry->vme_end,
8634 vm_prot_t, entry->protection,
8635 vm_prot_t, entry->max_protection,
8636 int, VME_ALIAS(entry));
8637 entry->vme_permanent = false;
8638 }
8639
8640 assert(s == entry->vme_start);
8641 assert(entry->vme_end <= end);
8642
8643
8644 /*
8645 * Step 4: If the entry is in flux, wait for this to resolve.
8646 */
8647
8648 if (entry->in_transition) {
8649 wait_result_t wait_result;
8650
8651in_transition:
8652 /*
8653 * Another thread is wiring/unwiring this entry.
8654 * Let the other thread know we are waiting.
8655 */
8656
8657 entry->needs_wakeup = TRUE;
8658
8659 /*
8660 * wake up anybody waiting on entries that we have
8661 * already unwired/deleted.
8662 */
8663 if (state & VMDS_NEEDS_WAKEUP) {
8664 vm_map_entry_wakeup(map);
8665 state &= ~VMDS_NEEDS_WAKEUP;
8666 }
8667
8668 wait_result = vm_map_entry_wait(map, interruptible);
8669
8670 if (interruptible &&
8671 wait_result == THREAD_INTERRUPTED) {
8672 /*
8673 * We do not clear the needs_wakeup flag,
8674 * since we cannot tell if we were the only one.
8675 */
8676 ret.kmr_return = KERN_ABORTED;
8677 vmlp_api_end(VM_MAP_DELETE, KERN_ABORTED);
8678 return ret;
8679 }
8680
8681 /*
8682 * The entry could have been clipped or it
8683 * may not exist anymore. Look it up again.
8684 */
8685 state |= VMDS_NEEDS_LOOKUP;
8686 continue;
8687 }
8688
8689
8690 /*
8691 * Step 5: Handle wiring
8692 */
8693
8694 if (entry->wired_count) {
8695 struct vm_map_entry tmp_entry;
8696 boolean_t user_wire;
8697 unsigned int last_timestamp;
8698
8699 user_wire = entry->user_wired_count > 0;
8700
8701 /*
8702 * Remove a kernel wiring if requested
8703 */
8704 if (flags & VM_MAP_REMOVE_KUNWIRE) {
8705 entry->wired_count--;
8706 vme_btref_consider_and_put(entry);
8707 }
8708
8709 /*
8710 * Remove all user wirings for proper accounting
8711 */
8712 while (entry->user_wired_count) {
8713 subtract_wire_counts(map, entry, user_wire);
8714 }
8715
8716 /*
8717 * All our DMA I/O operations in IOKit are currently
8718 * done by wiring through the map entries of the task
8719 * requesting the I/O.
8720 *
8721 * Because of this, we must always wait for kernel wirings
8722 * to go away on the entries before deleting them.
8723 *
8724 * Any caller who wants to actually remove a kernel wiring
8725 * should explicitly set the VM_MAP_REMOVE_KUNWIRE flag to
8726 * properly remove one wiring instead of blasting through
8727 * them all.
8728 */
8729 if (entry->wired_count != 0) {
8730 assert(map != kernel_map);
8731 /*
8732 * Cannot continue. Typical case is when
8733 * a user thread has physical io pending on
8734 * on this page. Either wait for the
8735 * kernel wiring to go away or return an
8736 * error.
8737 */
8738 wait_result_t wait_result;
8739
8740 entry->needs_wakeup = TRUE;
8741 wait_result = vm_map_entry_wait(map,
8742 interruptible);
8743
8744 if (interruptible &&
8745 wait_result == THREAD_INTERRUPTED) {
8746 /*
8747 * We do not clear the
8748 * needs_wakeup flag, since we
8749 * cannot tell if we were the
8750 * only one.
8751 */
8752 ret.kmr_return = KERN_ABORTED;
8753 vmlp_api_end(VM_MAP_DELETE, KERN_ABORTED);
8754 return ret;
8755 }
8756
8757
8758 /*
8759 * The entry could have been clipped or
8760 * it may not exist anymore. Look it
8761 * up again.
8762 */
8763 state |= VMDS_NEEDS_LOOKUP;
8764 continue;
8765 }
8766
8767 /*
8768 * We can unlock the map now.
8769 *
8770 * The entry might be split once we unlock the map,
8771 * but we need the range as defined by this entry
8772 * to be stable. So we must make a local copy.
8773 *
8774 * The underlying objects do not change during clips,
8775 * and the in_transition state guarentees existence
8776 * of the entry.
8777 */
8778 last_timestamp = map->timestamp;
8779 entry->in_transition = TRUE;
8780 tmp_entry = *entry;
8781 vm_map_unlock(map);
8782
8783 if (tmp_entry.is_sub_map) {
8784 vm_map_t sub_map;
8785 vm_map_offset_t sub_start, sub_end;
8786 pmap_t pmap;
8787 vm_map_offset_t pmap_addr;
8788
8789
8790 sub_map = VME_SUBMAP(&tmp_entry);
8791 sub_start = VME_OFFSET(&tmp_entry);
8792 sub_end = sub_start + (tmp_entry.vme_end -
8793 tmp_entry.vme_start);
8794 if (tmp_entry.use_pmap) {
8795 pmap = sub_map->pmap;
8796 pmap_addr = tmp_entry.vme_start;
8797 } else {
8798 pmap = map->pmap;
8799 pmap_addr = tmp_entry.vme_start;
8800 }
8801 (void) vm_map_unwire_nested(sub_map,
8802 sub_start, sub_end,
8803 user_wire,
8804 pmap, pmap_addr);
8805 } else {
8806 vm_map_offset_t entry_end = tmp_entry.vme_end;
8807 vm_map_offset_t max_end;
8808
8809 if (flags & VM_MAP_REMOVE_NOKUNWIRE_LAST) {
8810 max_end = end - VM_MAP_PAGE_SIZE(map);
8811 if (entry_end > max_end) {
8812 entry_end = max_end;
8813 }
8814 }
8815
8816 if (tmp_entry.vme_kernel_object) {
8817 pmap_protect_options(
8818 map->pmap,
8819 tmp_entry.vme_start,
8820 entry_end,
8821 VM_PROT_NONE,
8822 PMAP_OPTIONS_REMOVE,
8823 NULL);
8824 }
8825 vm_fault_unwire(map, &tmp_entry,
8826 tmp_entry.vme_kernel_object, map->pmap,
8827 tmp_entry.vme_start, entry_end);
8828 }
8829
8830 vm_map_lock(map);
8831
8832 /*
8833 * Unwiring happened, we can now go back to deleting
8834 * them (after we clear the in_transition bit for the range).
8835 */
8836 if (last_timestamp + 1 != map->timestamp) {
8837 state |= VMDS_NEEDS_LOOKUP;
8838 }
8839 clear_in_transition_end = tmp_entry.vme_end;
8840 continue;
8841 }
8842
8843 assert(entry->wired_count == 0);
8844 assert(entry->user_wired_count == 0);
8845
8846
8847 /*
8848 * Step 6: Entry is unwired and ready for us to delete !
8849 */
8850
8851 if (!entry->vme_permanent) {
8852 /*
8853 * Typical case: the entry really shouldn't be permanent
8854 */
8855 } else if ((flags & VM_MAP_REMOVE_IMMUTABLE_CODE) &&
8856 (entry->protection & VM_PROT_EXECUTE) &&
8857 developer_mode_state()) {
8858 /*
8859 * Allow debuggers to undo executable mappings
8860 * when developer mode is on.
8861 */
8862#if 0
8863 printf("FBDP %d[%s] removing permanent executable entry "
8864 "%p [0x%llx:0x%llx] prot 0x%x/0x%x\n",
8865 proc_selfpid(),
8866 (current_task()->bsd_info
8867 ? proc_name_address(current_task()->bsd_info)
8868 : "?"), entry,
8869 (uint64_t)entry->vme_start,
8870 (uint64_t)entry->vme_end,
8871 entry->protection,
8872 entry->max_protection);
8873#endif
8874 entry->vme_permanent = FALSE;
8875 } else if ((flags & VM_MAP_REMOVE_IMMUTABLE) || map->terminated) {
8876#if 0
8877 printf("FBDP %d[%s] removing permanent entry "
8878 "%p [0x%llx:0x%llx] prot 0x%x/0x%x\n",
8879 proc_selfpid(),
8880 (current_task()->bsd_info
8881 ? proc_name_address(current_task()->bsd_info)
8882 : "?"), entry,
8883 (uint64_t)entry->vme_start,
8884 (uint64_t)entry->vme_end,
8885 entry->protection,
8886 entry->max_protection);
8887#endif
8888 entry->vme_permanent = FALSE;
8889#if CODE_SIGNING_MONITOR
8890 } else if ((entry->protection & VM_PROT_EXECUTE) && !csm_enabled()) {
8891 entry->vme_permanent = FALSE;
8892
8893 printf("%d[%s] %s(0x%llx,0x%llx): "
8894 "code signing monitor disabled, allowing for permanent executable entry [0x%llx:0x%llx] "
8895 "prot 0x%x/0x%x\n",
8896 proc_selfpid(),
8897 (get_bsdtask_info(current_task())
8898 ? proc_name_address(get_bsdtask_info(current_task()))
8899 : "?"),
8900 __FUNCTION__,
8901 (uint64_t)start,
8902 (uint64_t)end,
8903 (uint64_t)entry->vme_start,
8904 (uint64_t)entry->vme_end,
8905 entry->protection,
8906 entry->max_protection);
8907#endif
8908 } else {
8909 DTRACE_VM6(vm_map_delete_permanent,
8910 vm_map_entry_t, entry,
8911 vm_map_offset_t, entry->vme_start,
8912 vm_map_offset_t, entry->vme_end,
8913 vm_prot_t, entry->protection,
8914 vm_prot_t, entry->max_protection,
8915 int, VME_ALIAS(entry));
8916 }
8917
8918 if (entry->is_sub_map) {
8919 assertf(VM_MAP_PAGE_SHIFT(VME_SUBMAP(entry)) >= VM_MAP_PAGE_SHIFT(map),
8920 "map %p (%d) entry %p submap %p (%d)\n",
8921 map, VM_MAP_PAGE_SHIFT(map), entry,
8922 VME_SUBMAP(entry),
8923 VM_MAP_PAGE_SHIFT(VME_SUBMAP(entry)));
8924 if (entry->use_pmap) {
8925#ifndef NO_NESTED_PMAP
8926 int pmap_flags;
8927
8928 if (map->terminated) {
8929 /*
8930 * This is the final cleanup of the
8931 * address space being terminated.
8932 * No new mappings are expected and
8933 * we don't really need to unnest the
8934 * shared region (and lose the "global"
8935 * pmap mappings, if applicable).
8936 *
8937 * Tell the pmap layer that we're
8938 * "clean" wrt nesting.
8939 */
8940 pmap_flags = PMAP_UNNEST_CLEAN;
8941 } else {
8942 /*
8943 * We're unmapping part of the nested
8944 * shared region, so we can't keep the
8945 * nested pmap.
8946 */
8947 pmap_flags = 0;
8948 }
8949 pmap_unnest_options(
8950 map->pmap,
8951 (addr64_t)entry->vme_start,
8952 entry->vme_end - entry->vme_start,
8953 pmap_flags);
8954#endif /* NO_NESTED_PMAP */
8955 if (map->mapped_in_other_pmaps &&
8956 os_ref_get_count_raw(&map->map_refcnt) != 0) {
8957 /* clean up parent map/maps */
8958 vm_map_submap_pmap_clean(
8959 map, entry->vme_start,
8960 entry->vme_end,
8961 VME_SUBMAP(entry),
8962 VME_OFFSET(entry));
8963 }
8964 } else {
8965 vm_map_submap_pmap_clean(
8966 map, entry->vme_start, entry->vme_end,
8967 VME_SUBMAP(entry),
8968 VME_OFFSET(entry));
8969 }
8970 } else if (entry->vme_kernel_object ||
8971 VME_OBJECT(entry) == compressor_object) {
8972 /*
8973 * nothing to do
8974 */
8975 } else if (map->mapped_in_other_pmaps &&
8976 os_ref_get_count_raw(&map->map_refcnt) != 0) {
8977 vm_object_pmap_protect_options(
8978 VME_OBJECT(entry), VME_OFFSET(entry),
8979 entry->vme_end - entry->vme_start,
8980 PMAP_NULL,
8981 PAGE_SIZE,
8982 entry->vme_start,
8983 VM_PROT_NONE,
8984 PMAP_OPTIONS_REMOVE);
8985 } else if ((VME_OBJECT(entry) != VM_OBJECT_NULL) ||
8986 (state & VMDS_KERNEL_PMAP)) {
8987 /* Remove translations associated
8988 * with this range unless the entry
8989 * does not have an object, or
8990 * it's the kernel map or a descendant
8991 * since the platform could potentially
8992 * create "backdoor" mappings invisible
8993 * to the VM. It is expected that
8994 * objectless, non-kernel ranges
8995 * do not have such VM invisible
8996 * translations.
8997 */
8998 vm_map_address_t remove_start = entry->vme_start;
8999 vm_map_address_t remove_end = entry->vme_end;
9000#if MACH_ASSERT
9001 /*
9002 * Prevent panics in pmap_remove() from some vm test code
9003 * which uses virtual address ranges that pmap disallows.
9004 */
9005 if (thread_get_test_option(test_option_vm_map_clamp_pmap_remove)) {
9006 vm_map_clamp_to_pmap(map, &remove_start, &remove_end);
9007 }
9008#endif /* MACH_ASSERT */
9009 pmap_remove(map->pmap, remove_start, remove_end);
9010 }
9011
9012#if DEBUG
9013 /*
9014 * All pmap mappings for this map entry must have been
9015 * cleared by now.
9016 */
9017 assert(pmap_is_empty(map->pmap,
9018 entry->vme_start,
9019 entry->vme_end));
9020#endif /* DEBUG */
9021
9022 if (entry->iokit_acct) {
9023 /* alternate accounting */
9024 DTRACE_VM4(vm_map_iokit_unmapped_region,
9025 vm_map_t, map,
9026 vm_map_offset_t, entry->vme_start,
9027 vm_map_offset_t, entry->vme_end,
9028 int, VME_ALIAS(entry));
9029 vm_map_iokit_unmapped_region(map,
9030 (entry->vme_end -
9031 entry->vme_start));
9032 entry->iokit_acct = FALSE;
9033 entry->use_pmap = FALSE;
9034 }
9035
9036 /* move "s" forward */
9037 s = entry->vme_end;
9038 next = entry->vme_next;
9039 ret.kmr_size += s - entry->vme_start;
9040
9041 if (entry->vme_permanent) {
9042 /*
9043 * A permanent entry can not be removed, so leave it
9044 * in place but remove all access permissions.
9045 */
9046 if (__improbable(vm_log_map_delete_permanent_prot_none)) {
9047 printf("%s:%d %d[%s] map %p entry %p [ 0x%llx - 0x%llx ] submap %d prot 0x%x/0x%x -> 0/0\n",
9048 __FUNCTION__, __LINE__,
9049 proc_selfpid(),
9050 (get_bsdtask_info(current_task())
9051 ? proc_name_address(get_bsdtask_info(current_task()))
9052 : "?"),
9053 map,
9054 entry,
9055 (uint64_t)entry->vme_start,
9056 (uint64_t)entry->vme_end,
9057 entry->is_sub_map,
9058 entry->protection,
9059 entry->max_protection);
9060 }
9061 DTRACE_VM6(vm_map_delete_permanent_prot_none,
9062 vm_map_entry_t, entry,
9063 vm_map_offset_t, entry->vme_start,
9064 vm_map_offset_t, entry->vme_end,
9065 vm_prot_t, entry->protection,
9066 vm_prot_t, entry->max_protection,
9067 int, VME_ALIAS(entry));
9068 entry->protection = VM_PROT_NONE;
9069 entry->max_protection = VM_PROT_NONE;
9070#ifdef __arm64e__
9071 entry->used_for_tpro = FALSE;
9072#endif
9073 } else {
9074 vm_map_entry_zap(map, entry, zap_list);
9075 }
9076
9077 entry = next;
9078 next = VM_MAP_ENTRY_NULL;
9079
9080 if ((flags & VM_MAP_REMOVE_NO_YIELD) == 0 && s < end) {
9081 vmlp_lock_event_locked(VMLP_EVENT_LOCK_YIELD_BEGIN, map);
9082 unsigned int last_timestamp = map->timestamp++;
9083
9084 if (lck_rw_lock_yield_exclusive(&map->lock,
9085 LCK_RW_YIELD_ANY_WAITER)) {
9086 if (last_timestamp != map->timestamp + 1) {
9087 state |= VMDS_NEEDS_LOOKUP;
9088 }
9089 } else {
9090 /* we didn't yield, undo our change */
9091 map->timestamp--;
9092 }
9093 vmlp_lock_event_locked(VMLP_EVENT_LOCK_YIELD_END, map);
9094 }
9095 }
9096
9097 if (map->wait_for_space) {
9098 thread_wakeup((event_t) map);
9099 }
9100
9101 if (state & VMDS_NEEDS_WAKEUP) {
9102 vm_map_entry_wakeup(map);
9103 }
9104
9105out:
9106 if ((state & VMDS_KERNEL_PMAP) && ret.kmr_return) {
9107 __vm_map_delete_failed_panic(map, start, end, ret.kmr_return);
9108 }
9109
9110 if (state & VMDS_KERNEL_KMEMPTR) {
9111 kmem_free_space(start, end, range_id, &slot);
9112 }
9113
9114 if (state & VMDS_FOUND_GAP) {
9115 DTRACE_VM3(kern_vm_deallocate_gap,
9116 vm_map_offset_t, gap_start,
9117 vm_map_offset_t, save_start,
9118 vm_map_offset_t, save_end);
9119 if (flags & VM_MAP_REMOVE_GAPS_FAIL) {
9120 ret.kmr_return = KERN_INVALID_VALUE;
9121 } else {
9122 vm_map_guard_exception(gap_start, kGUARD_EXC_DEALLOC_GAP);
9123 }
9124 }
9125
9126 vmlp_api_end(VM_MAP_DELETE, ret.kmr_return);
9127 return ret;
9128}
9129
9130kmem_return_t
9131vm_map_remove_and_unlock(
9132 vm_map_t map,
9133 vm_map_offset_t start,
9134 vm_map_offset_t end,
9135 vmr_flags_t flags,
9136 kmem_guard_t guard)
9137{
9138 kmem_return_t ret;
9139 VM_MAP_ZAP_DECLARE(zap);
9140
9141 vmlp_api_start(VM_MAP_REMOVE_AND_UNLOCK);
9142 vmlp_range_event(map, start, end - start);
9143
9144 ret = vm_map_delete(map, start, end, flags, guard, &zap);
9145 vm_map_unlock(map);
9146
9147 vm_map_zap_dispose(&zap);
9148
9149 vmlp_api_end(VM_MAP_REMOVE_AND_UNLOCK, ret.kmr_return);
9150 return ret;
9151}
9152
9153/*
9154 * vm_map_remove_guard:
9155 *
9156 * Remove the given address range from the target map.
9157 * This is the exported form of vm_map_delete.
9158 */
9159kmem_return_t
9160vm_map_remove_guard(
9161 vm_map_t map,
9162 vm_map_offset_t start,
9163 vm_map_offset_t end,
9164 vmr_flags_t flags,
9165 kmem_guard_t guard)
9166{
9167 kmem_return_t ret;
9168 vmlp_api_start(VM_MAP_REMOVE_GUARD);
9169 vm_map_lock(map);
9170 vmlp_range_event(map, start, end - start);
9171 ret = vm_map_remove_and_unlock(map, start, end, flags, guard);
9172 vmlp_api_end(VM_MAP_REMOVE_GUARD, ret.kmr_return);
9173 return ret;
9174}
9175
9176
9177/*
9178 * vm_map_setup:
9179 *
9180 * Perform any required setup on a new task's map. Must be called before the task
9181 * is enabled for IPC access, since after this point other threads may be able
9182 * to look up the task port and make VM API calls.
9183 */
9184void
9185vm_map_setup(vm_map_t map, task_t task)
9186{
9187 /*
9188 * map does NOT take a reference on owning_task. If the map has terminated,
9189 * it is possible that the pointer is NULL, so reads of owning_task must
9190 * happen under the map lock and explicitly check for NULL.
9191 */
9192 vm_map_lock(map);
9193 assert(!map->owning_task);
9194 map->owning_task = task;
9195 vm_map_unlock(map);
9196#if CONFIG_DEFERRED_RECLAIM
9197 vm_deferred_reclamation_metadata_t vdrm = task->deferred_reclamation_metadata;
9198 if (vdrm) {
9199 vm_deferred_reclamation_task_fork_register(vdrm);
9200 }
9201#endif /* CONFIG_DEFERRED_RECLAIM */
9202}
9203
9204/*
9205 * vm_map_terminate:
9206 *
9207 * Clean out a task's map.
9208 */
9209kern_return_t
9210vm_map_terminate(
9211 vm_map_t map)
9212{
9213 vmlp_api_start(VM_MAP_TERMINATE);
9214 vmlp_range_event_all(map);
9215 vm_map_lock(map);
9216 map->terminated = TRUE;
9217 map->owning_task = NULL;
9218 vm_map_disable_hole_optimization(map);
9219 (void)vm_map_remove_and_unlock(map, map->min_offset, map->max_offset,
9220 VM_MAP_REMOVE_NO_FLAGS, KMEM_GUARD_NONE);
9221 vmlp_api_end(VM_MAP_TERMINATE, KERN_SUCCESS);
9222 return KERN_SUCCESS;
9223}
9224
9225/*
9226 * Routine: vm_map_copy_allocate
9227 *
9228 * Description:
9229 * Allocates and initializes a map copy object.
9230 */
9231static vm_map_copy_t
9232vm_map_copy_allocate(uint16_t type)
9233{
9234 vm_map_copy_t new_copy;
9235
9236 new_copy = zalloc_id(ZONE_ID_VM_MAP_COPY, Z_WAITOK | Z_ZERO);
9237 new_copy->type = type;
9238 if (type == VM_MAP_COPY_ENTRY_LIST) {
9239 new_copy->c_u.hdr.rb_head_store.rbh_root = (void*)(int)SKIP_RB_TREE;
9240 vm_map_store_init(&new_copy->cpy_hdr);
9241 }
9242 return new_copy;
9243}
9244
9245/*
9246 * Routine: vm_map_copy_discard
9247 *
9248 * Description:
9249 * Dispose of a map copy object (returned by
9250 * vm_map_copyin).
9251 */
9252void
9253vm_map_copy_discard(
9254 vm_map_copy_t copy)
9255{
9256 if (copy == VM_MAP_COPY_NULL) {
9257 return;
9258 }
9259
9260 /*
9261 * Assert that the vm_map_copy is coming from the right
9262 * zone and hasn't been forged
9263 */
9264 vm_map_copy_require(copy);
9265
9266 switch (copy->type) {
9267 case VM_MAP_COPY_ENTRY_LIST:
9268 while (vm_map_copy_first_entry(copy) !=
9269 vm_map_copy_to_entry(copy)) {
9270 vm_map_entry_t entry = vm_map_copy_first_entry(copy);
9271
9272 vm_map_copy_entry_unlink(copy, entry);
9273 if (entry->is_sub_map) {
9274 vm_map_deallocate(VME_SUBMAP(entry));
9275 } else {
9276 vm_object_deallocate(VME_OBJECT(entry));
9277 }
9278 vm_map_copy_entry_dispose(entry);
9279 }
9280 break;
9281 case VM_MAP_COPY_KERNEL_BUFFER:
9282
9283 /*
9284 * The vm_map_copy_t and possibly the data buffer were
9285 * allocated by a single call to kalloc_data(), i.e. the
9286 * vm_map_copy_t was not allocated out of the zone.
9287 */
9288 if (copy->size > msg_ool_size_small || copy->offset) {
9289 panic("Invalid vm_map_copy_t sz:%lld, ofst:%lld",
9290 (long long)copy->size, (long long)copy->offset);
9291 }
9292 kfree_data(copy->cpy_kdata, copy->size);
9293 }
9294 zfree_id(ZONE_ID_VM_MAP_COPY, copy);
9295}
9296
9297#if XNU_PLATFORM_MacOSX
9298
9299__exported
9300extern vm_map_copy_t vm_map_copy_copy(vm_map_copy_t copy);
9301
9302/*
9303 * Routine: vm_map_copy_copy
9304 *
9305 * Description:
9306 * Move the information in a map copy object to
9307 * a new map copy object, leaving the old one
9308 * empty.
9309 *
9310 * This is used by kernel routines that need
9311 * to look at out-of-line data (in copyin form)
9312 * before deciding whether to return SUCCESS.
9313 * If the routine returns FAILURE, the original
9314 * copy object will be deallocated; therefore,
9315 * these routines must make a copy of the copy
9316 * object and leave the original empty so that
9317 * deallocation will not fail.
9318 */
9319vm_map_copy_t
9320vm_map_copy_copy(
9321 vm_map_copy_t copy)
9322{
9323 vm_map_copy_t new_copy;
9324
9325 if (copy == VM_MAP_COPY_NULL) {
9326 return VM_MAP_COPY_NULL;
9327 }
9328
9329 /*
9330 * Assert that the vm_map_copy is coming from the right
9331 * zone and hasn't been forged
9332 */
9333 vm_map_copy_require(copy);
9334
9335 /*
9336 * Allocate a new copy object, and copy the information
9337 * from the old one into it.
9338 */
9339
9340 new_copy = zalloc_id(ZONE_ID_VM_MAP_COPY, Z_WAITOK | Z_ZERO | Z_NOFAIL);
9341 memcpy((void *) new_copy, (void *) copy, sizeof(struct vm_map_copy));
9342#if __has_feature(ptrauth_calls)
9343 if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
9344 new_copy->cpy_kdata = copy->cpy_kdata;
9345 }
9346#endif
9347
9348 if (copy->type == VM_MAP_COPY_ENTRY_LIST) {
9349 /*
9350 * The links in the entry chain must be
9351 * changed to point to the new copy object.
9352 */
9353 VME_PREV_SET(vm_map_copy_first_entry(copy), vm_map_copy_to_entry(new_copy));
9354 vm_map_copy_last_entry(copy)->vme_next
9355 = vm_map_copy_to_entry(new_copy);
9356 }
9357
9358 /*
9359 * Change the old copy object into one that contains
9360 * nothing to be deallocated.
9361 */
9362 bzero(copy, sizeof(struct vm_map_copy));
9363 copy->type = VM_MAP_COPY_KERNEL_BUFFER;
9364
9365 /*
9366 * Return the new object.
9367 */
9368 return new_copy;
9369}
9370
9371#endif /* XNU_PLATFORM_MacOSX */
9372
9373static boolean_t
9374vm_map_entry_is_overwritable(
9375 vm_map_t dst_map __unused,
9376 vm_map_entry_t entry)
9377{
9378 if (!(entry->protection & VM_PROT_WRITE)) {
9379 /* can't overwrite if not writable */
9380 return FALSE;
9381 }
9382#if !__x86_64__
9383 if (entry->used_for_jit &&
9384 vm_map_cs_enforcement(dst_map) &&
9385 !dst_map->cs_debugged) {
9386 /*
9387 * Can't overwrite a JIT region while cs_enforced
9388 * and not cs_debugged.
9389 */
9390 return FALSE;
9391 }
9392
9393#if __arm64e__
9394 /* Do not allow overwrite HW assisted TPRO entries */
9395 if (entry->used_for_tpro) {
9396 return FALSE;
9397 }
9398#endif /* __arm64e__ */
9399
9400 if (entry->vme_permanent) {
9401 if (entry->is_sub_map) {
9402 /*
9403 * We can't tell if the submap contains "permanent"
9404 * entries within the range targeted by the caller.
9405 * The caller will have to check for that with
9406 * vm_map_overwrite_submap_recurse() for example.
9407 */
9408 } else {
9409 /*
9410 * Do not allow overwriting of a "permanent"
9411 * entry.
9412 */
9413 DTRACE_VM6(vm_map_delete_permanent_deny_overwrite,
9414 vm_map_entry_t, entry,
9415 vm_map_offset_t, entry->vme_start,
9416 vm_map_offset_t, entry->vme_end,
9417 vm_prot_t, entry->protection,
9418 vm_prot_t, entry->max_protection,
9419 int, VME_ALIAS(entry));
9420 return FALSE;
9421 }
9422 }
9423#endif /* !__x86_64__ */
9424
9425 if (entry->is_sub_map) {
9426 /* remember not to assume every entry has a VM object... */
9427 }
9428
9429
9430 return TRUE;
9431}
9432
9433static kern_return_t
9434vm_map_overwrite_submap_recurse(
9435 vm_map_t dst_map,
9436 vm_map_offset_t dst_addr,
9437 vm_map_size_t dst_size)
9438{
9439 vm_map_offset_t dst_end;
9440 vm_map_entry_t tmp_entry;
9441 vm_map_entry_t entry;
9442 kern_return_t result;
9443 boolean_t encountered_sub_map = FALSE;
9444
9445 vmlp_api_start(VM_MAP_OVERWRITE_SUBMAP_RECURSE);
9446
9447 /*
9448 * Verify that the destination is all writeable
9449 * initially. We have to trunc the destination
9450 * address and round the copy size or we'll end up
9451 * splitting entries in strange ways.
9452 */
9453
9454 dst_end = vm_map_round_page(dst_addr + dst_size,
9455 VM_MAP_PAGE_MASK(dst_map));
9456 vm_map_lock(dst_map);
9457
9458start_pass_1:
9459 if (!vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry)) {
9460 vm_map_unlock(dst_map);
9461 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_INVALID_ADDRESS);
9462 return KERN_INVALID_ADDRESS;
9463 }
9464
9465 vm_map_clip_start(dst_map,
9466 tmp_entry,
9467 vm_map_trunc_page(dst_addr,
9468 VM_MAP_PAGE_MASK(dst_map)));
9469 if (tmp_entry->is_sub_map) {
9470 /* clipping did unnest if needed */
9471 assert(!tmp_entry->use_pmap);
9472 }
9473
9474 for (entry = tmp_entry;;) {
9475 vm_map_entry_t next;
9476
9477 next = entry->vme_next;
9478 while (entry->is_sub_map) {
9479 vm_map_offset_t sub_start;
9480 vm_map_offset_t sub_end;
9481 vm_map_offset_t local_end;
9482 vm_map_t sub_map;
9483
9484 if (entry->in_transition) {
9485 /*
9486 * Say that we are waiting, and wait for entry.
9487 */
9488 entry->needs_wakeup = TRUE;
9489 vm_map_entry_wait(dst_map, THREAD_UNINT);
9490
9491 goto start_pass_1;
9492 }
9493
9494 encountered_sub_map = TRUE;
9495 sub_start = VME_OFFSET(entry);
9496
9497 if (entry->vme_end < dst_end) {
9498 sub_end = entry->vme_end;
9499 } else {
9500 sub_end = dst_end;
9501 }
9502 sub_end -= entry->vme_start;
9503 sub_end += VME_OFFSET(entry);
9504 local_end = entry->vme_end;
9505 sub_map = VME_SUBMAP(entry);
9506 vm_map_reference(sub_map);
9507 vm_map_unlock(dst_map);
9508
9509 result = vm_map_overwrite_submap_recurse(
9510 sub_map,
9511 sub_start,
9512 sub_end - sub_start);
9513
9514 vm_map_deallocate(sub_map);
9515 sub_map = VM_MAP_NULL;
9516
9517 if (result != KERN_SUCCESS) {
9518 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, result);
9519 return result;
9520 }
9521 if (dst_end <= entry->vme_end) {
9522 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_SUCCESS);
9523 return KERN_SUCCESS;
9524 }
9525 vm_map_lock(dst_map);
9526 if (!vm_map_lookup_entry(dst_map, local_end,
9527 &tmp_entry)) {
9528 vm_map_unlock(dst_map);
9529 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_INVALID_ADDRESS);
9530 return KERN_INVALID_ADDRESS;
9531 }
9532 entry = tmp_entry;
9533 next = entry->vme_next;
9534 }
9535 assert(!entry->is_sub_map);
9536
9537 if (!(entry->protection & VM_PROT_WRITE)) {
9538 vm_map_unlock(dst_map);
9539 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_PROTECTION_FAILURE);
9540 return KERN_PROTECTION_FAILURE;
9541 }
9542
9543 if (!vm_map_entry_is_overwritable(dst_map, entry)) {
9544 vm_map_unlock(dst_map);
9545 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_PROTECTION_FAILURE);
9546 return KERN_PROTECTION_FAILURE;
9547 }
9548
9549 vmlp_range_event_entry(dst_map, entry);
9550
9551 /*
9552 * If the entry is in transition, we must wait
9553 * for it to exit that state. Anything could happen
9554 * when we unlock the map, so start over.
9555 */
9556 if (entry->in_transition) {
9557 /*
9558 * Say that we are waiting, and wait for entry.
9559 */
9560 entry->needs_wakeup = TRUE;
9561 vm_map_entry_wait(dst_map, THREAD_UNINT);
9562
9563 goto start_pass_1;
9564 }
9565
9566/*
9567 * our range is contained completely within this map entry
9568 */
9569 if (dst_end <= entry->vme_end) {
9570 vm_map_unlock(dst_map);
9571 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_SUCCESS);
9572 return KERN_SUCCESS;
9573 }
9574/*
9575 * check that range specified is contiguous region
9576 */
9577 if ((next == vm_map_to_entry(dst_map)) ||
9578 (next->vme_start != entry->vme_end)) {
9579 vm_map_unlock(dst_map);
9580 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_INVALID_ADDRESS);
9581 return KERN_INVALID_ADDRESS;
9582 }
9583
9584 /*
9585 * Check for permanent objects in the destination.
9586 */
9587 assert(!entry->is_sub_map);
9588 if ((VME_OBJECT(entry) != VM_OBJECT_NULL) &&
9589 ((!VME_OBJECT(entry)->internal) ||
9590 (VME_OBJECT(entry)->true_share))) {
9591 if (encountered_sub_map) {
9592 vm_map_unlock(dst_map);
9593 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_INVALID_ADDRESS);
9594 return KERN_FAILURE;
9595 }
9596 }
9597
9598
9599 entry = next;
9600 }/* for */
9601 vm_map_unlock(dst_map);
9602 vmlp_api_end(VM_MAP_OVERWRITE_SUBMAP_RECURSE, KERN_SUCCESS);
9603 return KERN_SUCCESS;
9604}
9605
9606/*
9607 * Routine: vm_map_copy_overwrite
9608 *
9609 * Description:
9610 * Copy the memory described by the map copy
9611 * object (copy; returned by vm_map_copyin) onto
9612 * the specified destination region (dst_map, dst_addr).
9613 * The destination must be writeable.
9614 *
9615 * Unlike vm_map_copyout, this routine actually
9616 * writes over previously-mapped memory. If the
9617 * previous mapping was to a permanent (user-supplied)
9618 * memory object, it is preserved.
9619 *
9620 * The attributes (protection and inheritance) of the
9621 * destination region are preserved.
9622 *
9623 * If successful, consumes the copy object.
9624 * Otherwise, the caller is responsible for it.
9625 *
9626 * Implementation notes:
9627 * To overwrite aligned temporary virtual memory, it is
9628 * sufficient to remove the previous mapping and insert
9629 * the new copy. This replacement is done either on
9630 * the whole region (if no permanent virtual memory
9631 * objects are embedded in the destination region) or
9632 * in individual map entries.
9633 *
9634 * To overwrite permanent virtual memory , it is necessary
9635 * to copy each page, as the external memory management
9636 * interface currently does not provide any optimizations.
9637 *
9638 * Unaligned memory also has to be copied. It is possible
9639 * to use 'vm_trickery' to copy the aligned data. This is
9640 * not done but not hard to implement.
9641 *
9642 * Once a page of permanent memory has been overwritten,
9643 * it is impossible to interrupt this function; otherwise,
9644 * the call would be neither atomic nor location-independent.
9645 * The kernel-state portion of a user thread must be
9646 * interruptible.
9647 *
9648 * It may be expensive to forward all requests that might
9649 * overwrite permanent memory (vm_write, vm_copy) to
9650 * uninterruptible kernel threads. This routine may be
9651 * called by interruptible threads; however, success is
9652 * not guaranteed -- if the request cannot be performed
9653 * atomically and interruptibly, an error indication is
9654 * returned.
9655 *
9656 * Callers of this function must call vm_map_copy_require on
9657 * previously created vm_map_copy_t or pass a newly created
9658 * one to ensure that it hasn't been forged.
9659 */
9660static kern_return_t
9661vm_map_copy_overwrite_nested(
9662 vm_map_t dst_map,
9663 vm_map_address_t dst_addr,
9664 vm_map_copy_t copy,
9665 boolean_t interruptible,
9666 pmap_t pmap,
9667 boolean_t discard_on_success)
9668{
9669 vm_map_offset_t dst_end;
9670 vm_map_entry_t tmp_entry;
9671 vm_map_entry_t entry;
9672 kern_return_t kr;
9673 boolean_t aligned = TRUE;
9674 boolean_t contains_permanent_objects = FALSE;
9675 boolean_t encountered_sub_map = FALSE;
9676 vm_map_offset_t base_addr;
9677 vm_map_size_t copy_size;
9678 vm_map_size_t total_size;
9679 uint16_t copy_page_shift;
9680
9681 vmlp_api_start(VM_MAP_COPY_OVERWRITE_NESTED);
9682
9683
9684 /*
9685 * Check for special kernel buffer allocated
9686 * by new_ipc_kmsg_copyin.
9687 */
9688
9689 if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
9690 kr = vm_map_copyout_kernel_buffer(
9691 dst_map, &dst_addr,
9692 copy, copy->size, TRUE,
9693 discard_on_success);
9694 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, kr);
9695 return kr;
9696 }
9697
9698 /*
9699 * Only works for entry lists at the moment. Will
9700 * support page lists later.
9701 */
9702
9703 assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
9704
9705 if (copy->size == 0) {
9706 if (discard_on_success) {
9707 vm_map_copy_discard(copy);
9708 }
9709 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_SUCCESS);
9710 return KERN_SUCCESS;
9711 }
9712
9713 copy_page_shift = copy->cpy_hdr.page_shift;
9714
9715 /*
9716 * Verify that the destination is all writeable
9717 * initially. We have to trunc the destination
9718 * address and round the copy size or we'll end up
9719 * splitting entries in strange ways.
9720 */
9721
9722 if (!VM_MAP_PAGE_ALIGNED(copy->size,
9723 VM_MAP_PAGE_MASK(dst_map)) ||
9724 !VM_MAP_PAGE_ALIGNED(copy->offset,
9725 VM_MAP_PAGE_MASK(dst_map)) ||
9726 !VM_MAP_PAGE_ALIGNED(dst_addr,
9727 VM_MAP_PAGE_MASK(dst_map)) ||
9728 copy_page_shift != VM_MAP_PAGE_SHIFT(dst_map)) {
9729 aligned = FALSE;
9730 dst_end = vm_map_round_page(dst_addr + copy->size,
9731 VM_MAP_PAGE_MASK(dst_map));
9732 } else {
9733 dst_end = dst_addr + copy->size;
9734 }
9735
9736 vm_map_lock(dst_map);
9737
9738 /* LP64todo - remove this check when vm_map_commpage64()
9739 * no longer has to stuff in a map_entry for the commpage
9740 * above the map's max_offset.
9741 */
9742 if (dst_addr >= dst_map->max_offset) {
9743 vm_map_unlock(dst_map);
9744 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9745 return KERN_INVALID_ADDRESS;
9746 }
9747
9748start_pass_1:
9749 if (!vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry)) {
9750 vm_map_unlock(dst_map);
9751 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9752 return KERN_INVALID_ADDRESS;
9753 }
9754 vm_map_clip_start(dst_map,
9755 tmp_entry,
9756 vm_map_trunc_page(dst_addr,
9757 VM_MAP_PAGE_MASK(dst_map)));
9758 for (entry = tmp_entry;;) {
9759 vm_map_entry_t next = entry->vme_next;
9760
9761 while (entry->is_sub_map) {
9762 vm_map_offset_t sub_start;
9763 vm_map_offset_t sub_end;
9764 vm_map_offset_t local_end;
9765
9766 if (entry->in_transition) {
9767 /*
9768 * Say that we are waiting, and wait for entry.
9769 */
9770 entry->needs_wakeup = TRUE;
9771 vm_map_entry_wait(dst_map, THREAD_UNINT);
9772
9773 goto start_pass_1;
9774 }
9775
9776 local_end = entry->vme_end;
9777 if (!(entry->needs_copy)) {
9778 vm_map_t sub_map = VM_MAP_NULL;
9779
9780 /* if needs_copy we are a COW submap */
9781 /* in such a case we just replace so */
9782 /* there is no need for the follow- */
9783 /* ing check. */
9784 encountered_sub_map = TRUE;
9785 sub_start = VME_OFFSET(entry);
9786
9787 if (entry->vme_end < dst_end) {
9788 sub_end = entry->vme_end;
9789 } else {
9790 sub_end = dst_end;
9791 }
9792 sub_end -= entry->vme_start;
9793 sub_end += VME_OFFSET(entry);
9794 sub_map = VME_SUBMAP(entry);
9795 vm_map_reference(sub_map);
9796 vm_map_unlock(dst_map);
9797
9798 kr = vm_map_overwrite_submap_recurse(
9799 sub_map,
9800 sub_start,
9801 sub_end - sub_start);
9802
9803 vm_map_deallocate(sub_map);
9804 sub_map = VM_MAP_NULL;
9805 if (kr != KERN_SUCCESS) {
9806 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, kr);
9807 return kr;
9808 }
9809 vm_map_lock(dst_map);
9810 }
9811
9812 if (dst_end <= entry->vme_end) {
9813 goto start_overwrite;
9814 }
9815 if (!vm_map_lookup_entry(dst_map, local_end,
9816 &entry)) {
9817 vm_map_unlock(dst_map);
9818 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9819 return KERN_INVALID_ADDRESS;
9820 }
9821 next = entry->vme_next;
9822 }
9823 assert(!entry->is_sub_map);
9824
9825 if (!(entry->protection & VM_PROT_WRITE)) {
9826 vm_map_unlock(dst_map);
9827 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_PROTECTION_FAILURE);
9828 return KERN_PROTECTION_FAILURE;
9829 }
9830
9831 if (!vm_map_entry_is_overwritable(dst_map, entry)) {
9832 vm_map_unlock(dst_map);
9833 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_PROTECTION_FAILURE);
9834 return KERN_PROTECTION_FAILURE;
9835 }
9836
9837 vmlp_range_event_entry(dst_map, entry);
9838
9839 /*
9840 * If the entry is in transition, we must wait
9841 * for it to exit that state. Anything could happen
9842 * when we unlock the map, so start over.
9843 */
9844 if (entry->in_transition) {
9845 /*
9846 * Say that we are waiting, and wait for entry.
9847 */
9848 entry->needs_wakeup = TRUE;
9849 vm_map_entry_wait(dst_map, THREAD_UNINT);
9850
9851 goto start_pass_1;
9852 }
9853
9854/*
9855 * our range is contained completely within this map entry
9856 */
9857 if (dst_end <= entry->vme_end) {
9858 break;
9859 }
9860/*
9861 * check that range specified is contiguous region
9862 */
9863 if ((next == vm_map_to_entry(dst_map)) ||
9864 (next->vme_start != entry->vme_end)) {
9865 vm_map_unlock(dst_map);
9866 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9867 return KERN_INVALID_ADDRESS;
9868 }
9869
9870
9871 /*
9872 * Check for permanent objects in the destination.
9873 */
9874 assert(!entry->is_sub_map);
9875 if ((VME_OBJECT(entry) != VM_OBJECT_NULL) &&
9876 ((!VME_OBJECT(entry)->internal) ||
9877 (VME_OBJECT(entry)->true_share))) {
9878 contains_permanent_objects = TRUE;
9879 }
9880
9881 entry = next;
9882 }/* for */
9883
9884start_overwrite:
9885 /*
9886 * If there are permanent objects in the destination, then
9887 * the copy cannot be interrupted.
9888 */
9889
9890 if (interruptible && contains_permanent_objects) {
9891 vm_map_unlock(dst_map);
9892 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_FAILURE);
9893 return KERN_FAILURE; /* XXX */
9894 }
9895
9896 /*
9897 *
9898 * Make a second pass, overwriting the data
9899 * At the beginning of each loop iteration,
9900 * the next entry to be overwritten is "tmp_entry"
9901 * (initially, the value returned from the lookup above),
9902 * and the starting address expected in that entry
9903 * is "start".
9904 */
9905
9906 total_size = copy->size;
9907 if (encountered_sub_map) {
9908 copy_size = 0;
9909 /* re-calculate tmp_entry since we've had the map */
9910 /* unlocked */
9911 if (!vm_map_lookup_entry( dst_map, dst_addr, &tmp_entry)) {
9912 vm_map_unlock(dst_map);
9913 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9914 return KERN_INVALID_ADDRESS;
9915 }
9916 } else {
9917 copy_size = copy->size;
9918 }
9919
9920 base_addr = dst_addr;
9921 while (TRUE) {
9922 /* deconstruct the copy object and do in parts */
9923 /* only in sub_map, interruptable case */
9924 vm_map_entry_t copy_entry;
9925 vm_map_entry_t previous_prev = VM_MAP_ENTRY_NULL;
9926 vm_map_entry_t next_copy = VM_MAP_ENTRY_NULL;
9927 int nentries;
9928 int remaining_entries = 0;
9929 vm_map_offset_t new_offset = 0;
9930
9931 for (entry = tmp_entry; copy_size == 0;) {
9932 vm_map_entry_t next;
9933
9934 next = entry->vme_next;
9935
9936 /* tmp_entry and base address are moved along */
9937 /* each time we encounter a sub-map. Otherwise */
9938 /* entry can outpase tmp_entry, and the copy_size */
9939 /* may reflect the distance between them */
9940 /* if the current entry is found to be in transition */
9941 /* we will start over at the beginning or the last */
9942 /* encounter of a submap as dictated by base_addr */
9943 /* we will zero copy_size accordingly. */
9944 if (entry->in_transition) {
9945 /*
9946 * Say that we are waiting, and wait for entry.
9947 */
9948 entry->needs_wakeup = TRUE;
9949 vm_map_entry_wait(dst_map, THREAD_UNINT);
9950
9951 if (!vm_map_lookup_entry(dst_map, base_addr,
9952 &tmp_entry)) {
9953 vm_map_unlock(dst_map);
9954 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
9955 return KERN_INVALID_ADDRESS;
9956 }
9957 copy_size = 0;
9958 entry = tmp_entry;
9959 continue;
9960 }
9961 if (entry->is_sub_map) {
9962 vm_map_offset_t sub_start;
9963 vm_map_offset_t sub_end;
9964 vm_map_offset_t local_end;
9965 vm_map_t sub_map = VM_MAP_NULL;
9966 bool use_pmap;
9967
9968 if (entry->needs_copy) {
9969 /* if this is a COW submap */
9970 /* just back the range with a */
9971 /* anonymous entry */
9972 assert(!entry->vme_permanent);
9973 if (entry->vme_end < dst_end) {
9974 sub_end = entry->vme_end;
9975 } else {
9976 sub_end = dst_end;
9977 }
9978 if (entry->vme_start < base_addr) {
9979 sub_start = base_addr;
9980 } else {
9981 sub_start = entry->vme_start;
9982 }
9983 vm_map_clip_end(
9984 dst_map, entry, sub_end);
9985 vm_map_clip_start(
9986 dst_map, entry, sub_start);
9987 assert(!entry->use_pmap);
9988 assert(!entry->iokit_acct);
9989 entry->use_pmap = TRUE;
9990 vm_map_deallocate(VME_SUBMAP(entry));
9991 assert(!entry->vme_permanent);
9992 VME_OBJECT_SET(entry, VM_OBJECT_NULL, false, 0);
9993 VME_OFFSET_SET(entry, 0);
9994 entry->is_shared = FALSE;
9995 entry->needs_copy = FALSE;
9996 entry->protection = VM_PROT_DEFAULT;
9997 entry->max_protection = VM_PROT_ALL;
9998 entry->wired_count = 0;
9999 entry->user_wired_count = 0;
10000 if (entry->inheritance
10001 == VM_INHERIT_SHARE) {
10002 entry->inheritance = VM_INHERIT_COPY;
10003 }
10004 continue;
10005 }
10006 /* first take care of any non-sub_map */
10007 /* entries to send */
10008 if (base_addr < entry->vme_start) {
10009 /* stuff to send */
10010 copy_size =
10011 entry->vme_start - base_addr;
10012 break;
10013 }
10014 sub_start = VME_OFFSET(entry);
10015
10016 if (entry->vme_end < dst_end) {
10017 sub_end = entry->vme_end;
10018 } else {
10019 sub_end = dst_end;
10020 }
10021 sub_end -= entry->vme_start;
10022 sub_end += VME_OFFSET(entry);
10023 local_end = entry->vme_end;
10024 use_pmap = entry->use_pmap;
10025 sub_map = VME_SUBMAP(entry);
10026 vm_map_reference(sub_map);
10027 vm_map_unlock(dst_map);
10028 copy_size = sub_end - sub_start;
10029
10030 /* adjust the copy object */
10031 if (total_size > copy_size) {
10032 vm_map_size_t local_size = 0;
10033 vm_map_size_t entry_size;
10034
10035 nentries = 1;
10036 new_offset = copy->offset;
10037 copy_entry = vm_map_copy_first_entry(copy);
10038 while (copy_entry !=
10039 vm_map_copy_to_entry(copy)) {
10040 entry_size = copy_entry->vme_end -
10041 copy_entry->vme_start;
10042 if ((local_size < copy_size) &&
10043 ((local_size + entry_size)
10044 >= copy_size)) {
10045 vm_map_copy_clip_end(copy,
10046 copy_entry,
10047 copy_entry->vme_start +
10048 (copy_size - local_size));
10049 entry_size = copy_entry->vme_end -
10050 copy_entry->vme_start;
10051 local_size += entry_size;
10052 new_offset += entry_size;
10053 }
10054 if (local_size >= copy_size) {
10055 next_copy = copy_entry->vme_next;
10056 copy_entry->vme_next =
10057 vm_map_copy_to_entry(copy);
10058 previous_prev = VMH_PREV(©->cpy_hdr);
10059 VMH_PREV_SET(©->cpy_hdr, copy_entry);
10060 copy->size = copy_size;
10061 remaining_entries =
10062 copy->cpy_hdr.nentries;
10063 remaining_entries -= nentries;
10064 copy->cpy_hdr.nentries = nentries;
10065 break;
10066 } else {
10067 local_size += entry_size;
10068 new_offset += entry_size;
10069 nentries++;
10070 }
10071 copy_entry = copy_entry->vme_next;
10072 }
10073 }
10074
10075 if ((use_pmap) && (pmap == NULL)) {
10076 kr = vm_map_copy_overwrite_nested(
10077 sub_map,
10078 sub_start,
10079 copy,
10080 interruptible,
10081 sub_map->pmap,
10082 TRUE);
10083 } else if (pmap != NULL) {
10084 kr = vm_map_copy_overwrite_nested(
10085 sub_map,
10086 sub_start,
10087 copy,
10088 interruptible, pmap,
10089 TRUE);
10090 } else {
10091 kr = vm_map_copy_overwrite_nested(
10092 sub_map,
10093 sub_start,
10094 copy,
10095 interruptible,
10096 dst_map->pmap,
10097 TRUE);
10098 }
10099
10100 vm_map_deallocate(sub_map);
10101 sub_map = VM_MAP_NULL;
10102
10103 if (kr != KERN_SUCCESS) {
10104 if (next_copy != NULL) {
10105 copy->cpy_hdr.nentries +=
10106 remaining_entries;
10107 VMH_PREV(©->cpy_hdr)->vme_next =
10108 next_copy;
10109 VMH_PREV_SET(©->cpy_hdr, previous_prev);
10110 copy->size = total_size;
10111 }
10112 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, kr);
10113 return kr;
10114 }
10115 if (dst_end <= local_end) {
10116 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_SUCCESS);
10117 return KERN_SUCCESS;
10118 }
10119 /* otherwise copy no longer exists, it was */
10120 /* destroyed after successful copy_overwrite */
10121 copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
10122 copy->offset = new_offset;
10123 copy->cpy_hdr.page_shift = copy_page_shift;
10124
10125 total_size -= copy_size;
10126 copy_size = 0;
10127 /* put back remainder of copy in container */
10128 if (next_copy != NULL) {
10129 copy->cpy_hdr.nentries = remaining_entries;
10130 copy->cpy_hdr.links.next = next_copy;
10131 VMH_PREV_SET(©->cpy_hdr, previous_prev);
10132 copy->size = total_size;
10133 VME_PREV_SET(next_copy, vm_map_copy_to_entry(copy));
10134 next_copy = NULL;
10135 }
10136 base_addr = local_end;
10137 vm_map_lock(dst_map);
10138 if (!vm_map_lookup_entry(dst_map,
10139 local_end, &tmp_entry)) {
10140 vm_map_unlock(dst_map);
10141 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
10142 return KERN_INVALID_ADDRESS;
10143 }
10144 entry = tmp_entry;
10145 continue;
10146 }
10147 assert(!entry->is_sub_map);
10148
10149 if (dst_end <= entry->vme_end) {
10150 copy_size = dst_end - base_addr;
10151 break;
10152 }
10153
10154 if ((next == vm_map_to_entry(dst_map)) ||
10155 (next->vme_start != entry->vme_end)) {
10156 vm_map_unlock(dst_map);
10157 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
10158 return KERN_INVALID_ADDRESS;
10159 }
10160
10161 entry = next;
10162 }/* for */
10163
10164 next_copy = NULL;
10165 nentries = 1;
10166
10167 /* adjust the copy object */
10168 if (total_size > copy_size) {
10169 vm_map_size_t local_size = 0;
10170 vm_map_size_t entry_size;
10171
10172 new_offset = copy->offset;
10173 copy_entry = vm_map_copy_first_entry(copy);
10174 while (copy_entry != vm_map_copy_to_entry(copy)) {
10175 entry_size = copy_entry->vme_end -
10176 copy_entry->vme_start;
10177 if ((local_size < copy_size) &&
10178 ((local_size + entry_size)
10179 >= copy_size)) {
10180 vm_map_copy_clip_end(copy, copy_entry,
10181 copy_entry->vme_start +
10182 (copy_size - local_size));
10183 entry_size = copy_entry->vme_end -
10184 copy_entry->vme_start;
10185 local_size += entry_size;
10186 new_offset += entry_size;
10187 }
10188 if (local_size >= copy_size) {
10189 next_copy = copy_entry->vme_next;
10190 copy_entry->vme_next =
10191 vm_map_copy_to_entry(copy);
10192 previous_prev = VMH_PREV(©->cpy_hdr);
10193 VMH_PREV_SET(©->cpy_hdr, copy_entry);
10194 copy->size = copy_size;
10195 remaining_entries =
10196 copy->cpy_hdr.nentries;
10197 remaining_entries -= nentries;
10198 copy->cpy_hdr.nentries = nentries;
10199 break;
10200 } else {
10201 local_size += entry_size;
10202 new_offset += entry_size;
10203 nentries++;
10204 }
10205 copy_entry = copy_entry->vme_next;
10206 }
10207 }
10208
10209 if (aligned) {
10210 pmap_t local_pmap;
10211
10212 if (pmap) {
10213 local_pmap = pmap;
10214 } else {
10215 local_pmap = dst_map->pmap;
10216 }
10217
10218 if ((kr = vm_map_copy_overwrite_aligned(
10219 dst_map, tmp_entry, copy,
10220 base_addr, local_pmap)) != KERN_SUCCESS) {
10221 if (next_copy != NULL) {
10222 copy->cpy_hdr.nentries +=
10223 remaining_entries;
10224 VMH_PREV(©->cpy_hdr)->vme_next =
10225 next_copy;
10226 VMH_PREV_SET(©->cpy_hdr, previous_prev);
10227 copy->size += copy_size;
10228 }
10229 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, kr);
10230 return kr;
10231 }
10232 vm_map_unlock(dst_map);
10233 } else {
10234 /*
10235 * Performance gain:
10236 *
10237 * if the copy and dst address are misaligned but the same
10238 * offset within the page we can copy_not_aligned the
10239 * misaligned parts and copy aligned the rest. If they are
10240 * aligned but len is unaligned we simply need to copy
10241 * the end bit unaligned. We'll need to split the misaligned
10242 * bits of the region in this case !
10243 */
10244 /* ALWAYS UNLOCKS THE dst_map MAP */
10245 kr = vm_map_copy_overwrite_unaligned(
10246 dst_map,
10247 tmp_entry,
10248 copy,
10249 base_addr,
10250 discard_on_success);
10251 if (kr != KERN_SUCCESS) {
10252 if (next_copy != NULL) {
10253 copy->cpy_hdr.nentries +=
10254 remaining_entries;
10255 VMH_PREV(©->cpy_hdr)->vme_next =
10256 next_copy;
10257 VMH_PREV_SET(©->cpy_hdr, previous_prev);
10258 copy->size += copy_size;
10259 }
10260 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, kr);
10261 return kr;
10262 }
10263 }
10264 total_size -= copy_size;
10265 if (total_size == 0) {
10266 break;
10267 }
10268 base_addr += copy_size;
10269 copy_size = 0;
10270 copy->offset = new_offset;
10271 if (next_copy != NULL) {
10272 copy->cpy_hdr.nentries = remaining_entries;
10273 copy->cpy_hdr.links.next = next_copy;
10274 VMH_PREV_SET(©->cpy_hdr, previous_prev);
10275 VME_PREV_SET(next_copy, vm_map_copy_to_entry(copy));
10276 copy->size = total_size;
10277 }
10278 vm_map_lock(dst_map);
10279 while (TRUE) {
10280 if (!vm_map_lookup_entry(dst_map,
10281 base_addr, &tmp_entry)) {
10282 vm_map_unlock(dst_map);
10283 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_INVALID_ADDRESS);
10284 return KERN_INVALID_ADDRESS;
10285 }
10286 if (tmp_entry->in_transition) {
10287 entry->needs_wakeup = TRUE;
10288 vm_map_entry_wait(dst_map, THREAD_UNINT);
10289 } else {
10290 break;
10291 }
10292 }
10293 vm_map_clip_start(dst_map,
10294 tmp_entry,
10295 vm_map_trunc_page(base_addr,
10296 VM_MAP_PAGE_MASK(dst_map)));
10297
10298 entry = tmp_entry;
10299 } /* while */
10300
10301 /*
10302 * Throw away the vm_map_copy object
10303 */
10304 if (discard_on_success) {
10305 vm_map_copy_discard(copy);
10306 }
10307
10308 vmlp_api_end(VM_MAP_COPY_OVERWRITE_NESTED, KERN_SUCCESS);
10309 return KERN_SUCCESS;
10310}/* vm_map_copy_overwrite */
10311
10312static __attribute__((always_inline, warn_unused_result))
10313kern_return_t
10314vm_map_copy_addr_size_sanitize(
10315 vm_map_t map,
10316 vm_map_offset_ut addr_u,
10317 vm_map_size_ut size_u,
10318 vm_sanitize_caller_t vm_sanitize_caller,
10319 vm_map_offset_t *addr,
10320 vm_map_offset_t *end,
10321 vm_map_size_t *size)
10322{
10323 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH |
10324 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES |
10325 VM_SANITIZE_FLAGS_CHECK_ADDR_RANGE;
10326
10327 return vm_sanitize_addr_size(addr_u, size_u,
10328 vm_sanitize_caller, map,
10329 flags,
10330 addr, end, size);
10331}
10332
10333kern_return_t
10334vm_map_copy_overwrite(
10335 vm_map_t dst_map,
10336 vm_map_offset_ut dst_addr_u,
10337 vm_map_copy_t copy,
10338 vm_map_size_ut copy_size_u,
10339 boolean_t interruptible)
10340{
10341 vm_map_offset_t dst_addr, dst_end;
10342 vm_map_size_t copy_size;
10343 vm_map_size_t head_size, tail_size;
10344 vm_map_copy_t head_copy, tail_copy;
10345 vm_map_offset_t head_addr, tail_addr;
10346 vm_map_entry_t entry;
10347 kern_return_t kr;
10348 vm_map_offset_t effective_page_mask, effective_page_size;
10349 uint16_t copy_page_shift;
10350
10351 vmlp_api_start(VM_MAP_COPY_OVERWRITE);
10352
10353 head_size = 0;
10354 tail_size = 0;
10355 head_copy = NULL;
10356 tail_copy = NULL;
10357 head_addr = 0;
10358 tail_addr = 0;
10359
10360 /*
10361 * Check for null copy object.
10362 */
10363 if (copy == VM_MAP_COPY_NULL) {
10364 vmlp_api_end(VM_MAP_COPY_OVERWRITE, KERN_SUCCESS);
10365 return KERN_SUCCESS;
10366 }
10367
10368 /*
10369 * Sanitize any input parameters that are addr/size/prot/inherit
10370 */
10371 kr = vm_map_copy_addr_size_sanitize(
10372 dst_map,
10373 dst_addr_u,
10374 copy_size_u,
10375 VM_SANITIZE_CALLER_VM_MAP_COPY_OVERWRITE,
10376 &dst_addr,
10377 &dst_end,
10378 ©_size);
10379 if (__improbable(kr != KERN_SUCCESS)) {
10380 kern_return_t ret = vm_sanitize_get_kr(kr);
10381 vmlp_api_end(VM_MAP_COPY_OVERWRITE, ret);
10382 return ret;
10383 }
10384
10385 vmlp_range_event(dst_map, dst_addr, copy_size);
10386
10387 /*
10388 * Assert that the vm_map_copy is coming from the right
10389 * zone and hasn't been forged
10390 */
10391 vm_map_copy_require(copy);
10392
10393 if (interruptible ||
10394 copy->type != VM_MAP_COPY_ENTRY_LIST) {
10395 /*
10396 * We can't split the "copy" map if we're interruptible
10397 * or if we don't have a "copy" map...
10398 */
10399blunt_copy:
10400 kr = vm_map_copy_overwrite_nested(dst_map,
10401 dst_addr,
10402 copy,
10403 interruptible,
10404 (pmap_t) NULL,
10405 TRUE);
10406 if (kr) {
10407 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOVERWRITE_FULL_NESTED_ERROR), kr /* arg */);
10408 }
10409 vmlp_api_end(VM_MAP_COPY_OVERWRITE, kr);
10410 return kr;
10411 }
10412
10413 copy_page_shift = VM_MAP_COPY_PAGE_SHIFT(copy);
10414 if (copy_page_shift < PAGE_SHIFT ||
10415 VM_MAP_PAGE_SHIFT(dst_map) < PAGE_SHIFT) {
10416 goto blunt_copy;
10417 }
10418
10419 if (VM_MAP_PAGE_SHIFT(dst_map) < PAGE_SHIFT) {
10420 effective_page_mask = VM_MAP_PAGE_MASK(dst_map);
10421 } else {
10422 effective_page_mask = MAX(VM_MAP_PAGE_MASK(dst_map), PAGE_MASK);
10423 effective_page_mask = MAX(VM_MAP_COPY_PAGE_MASK(copy),
10424 effective_page_mask);
10425 }
10426 effective_page_size = effective_page_mask + 1;
10427
10428 if (copy_size < VM_MAP_COPY_OVERWRITE_OPTIMIZATION_THRESHOLD_PAGES * effective_page_size) {
10429 /*
10430 * Too small to bother with optimizing...
10431 */
10432 goto blunt_copy;
10433 }
10434
10435 if ((dst_addr & effective_page_mask) !=
10436 (copy->offset & effective_page_mask)) {
10437 /*
10438 * Incompatible mis-alignment of source and destination...
10439 */
10440 goto blunt_copy;
10441 }
10442
10443 /*
10444 * Proper alignment or identical mis-alignment at the beginning.
10445 * Let's try and do a small unaligned copy first (if needed)
10446 * and then an aligned copy for the rest.
10447 */
10448 if (!vm_map_page_aligned(dst_addr, effective_page_mask)) {
10449 head_addr = dst_addr;
10450 head_size = (effective_page_size -
10451 (copy->offset & effective_page_mask));
10452 head_size = MIN(head_size, copy_size);
10453 }
10454 if (!vm_map_page_aligned(copy->offset + copy_size,
10455 effective_page_mask)) {
10456 /*
10457 * Mis-alignment at the end.
10458 * Do an aligned copy up to the last page and
10459 * then an unaligned copy for the remaining bytes.
10460 */
10461 tail_size = ((copy->offset + copy_size) &
10462 effective_page_mask);
10463 tail_size = MIN(tail_size, copy_size);
10464 tail_addr = dst_addr + copy_size - tail_size;
10465 assert(tail_addr >= head_addr + head_size);
10466 }
10467 assert(head_size + tail_size <= copy_size);
10468
10469 if (head_size + tail_size == copy_size) {
10470 /*
10471 * It's all unaligned, no optimization possible...
10472 */
10473 goto blunt_copy;
10474 }
10475
10476 /*
10477 * Can't optimize if there are any submaps in the
10478 * destination due to the way we free the "copy" map
10479 * progressively in vm_map_copy_overwrite_nested()
10480 * in that case.
10481 */
10482 vm_map_lock_read(dst_map);
10483 if (!vm_map_lookup_entry(dst_map, dst_addr, &entry)) {
10484 vm_map_unlock_read(dst_map);
10485 goto blunt_copy;
10486 }
10487 for (;
10488 (entry != vm_map_to_entry(dst_map) &&
10489 entry->vme_start < dst_addr + copy_size);
10490 entry = entry->vme_next) {
10491 if (entry->is_sub_map) {
10492 vm_map_unlock_read(dst_map);
10493 goto blunt_copy;
10494 }
10495 }
10496 vm_map_unlock_read(dst_map);
10497
10498 if (head_size) {
10499 /*
10500 * Unaligned copy of the first "head_size" bytes, to reach
10501 * a page boundary.
10502 */
10503
10504 /*
10505 * Extract "head_copy" out of "copy".
10506 */
10507 head_copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
10508 head_copy->cpy_hdr.entries_pageable =
10509 copy->cpy_hdr.entries_pageable;
10510 head_copy->cpy_hdr.page_shift = copy_page_shift;
10511
10512 entry = vm_map_copy_first_entry(copy);
10513 if (entry->vme_end < copy->offset + head_size) {
10514 head_size = entry->vme_end - copy->offset;
10515 }
10516
10517 head_copy->offset = copy->offset;
10518 head_copy->size = head_size;
10519 copy->offset += head_size;
10520 copy->size -= head_size;
10521 copy_size -= head_size;
10522 assert(copy_size > 0);
10523
10524 vm_map_copy_clip_end(copy, entry, copy->offset);
10525 vm_map_copy_entry_unlink(copy, entry);
10526 vm_map_copy_entry_link(head_copy,
10527 vm_map_copy_to_entry(head_copy),
10528 entry);
10529
10530 /*
10531 * Do the unaligned copy.
10532 */
10533 kr = vm_map_copy_overwrite_nested(dst_map,
10534 head_addr,
10535 head_copy,
10536 interruptible,
10537 (pmap_t) NULL,
10538 FALSE);
10539 if (kr != KERN_SUCCESS) {
10540 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_HEAD_NESTED_ERROR), kr /* arg */);
10541 goto done;
10542 }
10543 }
10544
10545 if (tail_size) {
10546 /*
10547 * Extract "tail_copy" out of "copy".
10548 */
10549 tail_copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
10550 tail_copy->cpy_hdr.entries_pageable =
10551 copy->cpy_hdr.entries_pageable;
10552 tail_copy->cpy_hdr.page_shift = copy_page_shift;
10553
10554 tail_copy->offset = copy->offset + copy_size - tail_size;
10555 tail_copy->size = tail_size;
10556
10557 copy->size -= tail_size;
10558 copy_size -= tail_size;
10559 assert(copy_size > 0);
10560
10561 entry = vm_map_copy_last_entry(copy);
10562 vm_map_copy_clip_start(copy, entry, tail_copy->offset);
10563 entry = vm_map_copy_last_entry(copy);
10564 vm_map_copy_entry_unlink(copy, entry);
10565 vm_map_copy_entry_link(tail_copy,
10566 vm_map_copy_last_entry(tail_copy),
10567 entry);
10568 }
10569
10570 /*
10571 * If we are here from ipc_kmsg_copyout_ool_descriptor(),
10572 * we want to avoid TOCTOU issues w.r.t copy->size but
10573 * we don't need to change vm_map_copy_overwrite_nested()
10574 * and all other vm_map_copy_overwrite variants.
10575 *
10576 * So we assign the original copy_size that was passed into
10577 * this routine back to copy.
10578 *
10579 * This use of local 'copy_size' passed into this routine is
10580 * to try and protect against TOCTOU attacks where the kernel
10581 * has been exploited. We don't expect this to be an issue
10582 * during normal system operation.
10583 */
10584 assertf(copy->size == copy_size,
10585 "Mismatch of copy sizes. Expected 0x%llx, Got 0x%llx\n", (uint64_t) copy_size, (uint64_t) copy->size);
10586 copy->size = copy_size;
10587
10588 /*
10589 * Copy most (or possibly all) of the data.
10590 */
10591 kr = vm_map_copy_overwrite_nested(dst_map,
10592 dst_addr + head_size,
10593 copy,
10594 interruptible,
10595 (pmap_t) NULL,
10596 FALSE);
10597 if (kr != KERN_SUCCESS) {
10598 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_NESTED_ERROR), kr /* arg */);
10599 goto done;
10600 }
10601
10602 if (tail_size) {
10603 kr = vm_map_copy_overwrite_nested(dst_map,
10604 tail_addr,
10605 tail_copy,
10606 interruptible,
10607 (pmap_t) NULL,
10608 FALSE);
10609 if (kr) {
10610 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOVERWRITE_PARTIAL_TAIL_NESTED_ERROR), kr /* arg */);
10611 }
10612 }
10613
10614done:
10615 assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
10616 if (kr == KERN_SUCCESS) {
10617 /*
10618 * Discard all the copy maps.
10619 */
10620 if (head_copy) {
10621 vm_map_copy_discard(head_copy);
10622 head_copy = NULL;
10623 }
10624 vm_map_copy_discard(copy);
10625 if (tail_copy) {
10626 vm_map_copy_discard(tail_copy);
10627 tail_copy = NULL;
10628 }
10629 } else {
10630 /*
10631 * Re-assemble the original copy map.
10632 */
10633 if (head_copy) {
10634 entry = vm_map_copy_first_entry(head_copy);
10635 vm_map_copy_entry_unlink(head_copy, entry);
10636 vm_map_copy_entry_link(copy,
10637 vm_map_copy_to_entry(copy),
10638 entry);
10639 copy->offset -= head_size;
10640 copy->size += head_size;
10641 vm_map_copy_discard(head_copy);
10642 head_copy = NULL;
10643 }
10644 if (tail_copy) {
10645 entry = vm_map_copy_last_entry(tail_copy);
10646 vm_map_copy_entry_unlink(tail_copy, entry);
10647 vm_map_copy_entry_link(copy,
10648 vm_map_copy_last_entry(copy),
10649 entry);
10650 copy->size += tail_size;
10651 vm_map_copy_discard(tail_copy);
10652 tail_copy = NULL;
10653 }
10654 }
10655 vmlp_api_end(VM_MAP_COPY_OVERWRITE, kr);
10656 return kr;
10657}
10658
10659
10660/*
10661 * Routine: vm_map_copy_overwrite_unaligned [internal use only]
10662 *
10663 * Decription:
10664 * Physically copy unaligned data
10665 *
10666 * Implementation:
10667 * Unaligned parts of pages have to be physically copied. We use
10668 * a modified form of vm_fault_copy (which understands none-aligned
10669 * page offsets and sizes) to do the copy. We attempt to copy as
10670 * much memory in one go as possibly, however vm_fault_copy copies
10671 * within 1 memory object so we have to find the smaller of "amount left"
10672 * "source object data size" and "target object data size". With
10673 * unaligned data we don't need to split regions, therefore the source
10674 * (copy) object should be one map entry, the target range may be split
10675 * over multiple map entries however. In any event we are pessimistic
10676 * about these assumptions.
10677 *
10678 * Callers of this function must call vm_map_copy_require on
10679 * previously created vm_map_copy_t or pass a newly created
10680 * one to ensure that it hasn't been forged.
10681 *
10682 * Assumptions:
10683 * dst_map is locked on entry and is return locked on success,
10684 * unlocked on error.
10685 */
10686
10687static kern_return_t
10688vm_map_copy_overwrite_unaligned(
10689 vm_map_t dst_map,
10690 vm_map_entry_t entry,
10691 vm_map_copy_t copy,
10692 vm_map_offset_t start,
10693 boolean_t discard_on_success)
10694{
10695 vm_map_entry_t copy_entry;
10696 vm_map_entry_t copy_entry_next;
10697 vm_map_version_t version;
10698 vm_object_t dst_object;
10699 vm_object_offset_t dst_offset;
10700 vm_object_offset_t src_offset;
10701 vm_object_offset_t entry_offset;
10702 vm_map_offset_t entry_end;
10703 vm_map_size_t src_size,
10704 dst_size,
10705 copy_size,
10706 amount_left;
10707 kern_return_t kr = KERN_SUCCESS;
10708
10709 vmlp_api_start(VM_MAP_COPY_OVERWRITE_UNALIGNED);
10710
10711 copy_entry = vm_map_copy_first_entry(copy);
10712
10713 vm_map_lock_write_to_read(dst_map);
10714
10715 src_offset = copy->offset - trunc_page_mask_64(copy->offset, VM_MAP_COPY_PAGE_MASK(copy));
10716 amount_left = copy->size;
10717/*
10718 * unaligned so we never clipped this entry, we need the offset into
10719 * the vm_object not just the data.
10720 */
10721 while (amount_left > 0) {
10722 if (entry == vm_map_to_entry(dst_map)) {
10723 vm_map_unlock_read(dst_map);
10724 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_INVALID_ADDRESS);
10725 return KERN_INVALID_ADDRESS;
10726 }
10727
10728 /* "start" must be within the current map entry */
10729 assert((start >= entry->vme_start) && (start < entry->vme_end));
10730
10731 /*
10732 * Check protection again
10733 */
10734 if (!(entry->protection & VM_PROT_WRITE)) {
10735 vm_map_unlock_read(dst_map);
10736 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_PROTECTION_FAILURE);
10737 return KERN_PROTECTION_FAILURE;
10738 }
10739 if (entry->is_sub_map) {
10740 /* not implemented... */
10741 vm_map_unlock_read(dst_map);
10742 return KERN_INVALID_ARGUMENT;
10743 }
10744 if (!vm_map_entry_is_overwritable(dst_map, entry)) {
10745 vm_map_unlock_read(dst_map);
10746 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_PROTECTION_FAILURE);
10747 return KERN_PROTECTION_FAILURE;
10748 }
10749 /*
10750 * If the entry is in transition, we must wait
10751 * for it to exit that state. Anything could happen
10752 * when we unlock the map, so start over.
10753 */
10754 if (entry->in_transition) {
10755 /*
10756 * Say that we are waiting, and wait for entry.
10757 */
10758 entry->needs_wakeup = TRUE;
10759 vm_map_entry_wait(dst_map, THREAD_UNINT);
10760
10761 goto RetryLookup;
10762 }
10763
10764 vmlp_range_event_entry(dst_map, entry);
10765
10766 dst_offset = start - entry->vme_start;
10767
10768 dst_size = entry->vme_end - start;
10769
10770 src_size = copy_entry->vme_end -
10771 (copy_entry->vme_start + src_offset);
10772
10773 if (dst_size < src_size) {
10774/*
10775 * we can only copy dst_size bytes before
10776 * we have to get the next destination entry
10777 */
10778 copy_size = dst_size;
10779 } else {
10780/*
10781 * we can only copy src_size bytes before
10782 * we have to get the next source copy entry
10783 */
10784 copy_size = src_size;
10785 }
10786
10787 if (copy_size > amount_left) {
10788 copy_size = amount_left;
10789 }
10790/*
10791 * Entry needs copy, create a shadow shadow object for
10792 * Copy on write region.
10793 */
10794 assert(!entry->is_sub_map);
10795 if (entry->needs_copy) {
10796 if (vm_map_lock_read_to_write(dst_map)) {
10797 vm_map_lock_read(dst_map);
10798 goto RetryLookup;
10799 }
10800 VME_OBJECT_SHADOW(entry,
10801 (vm_map_size_t)(entry->vme_end
10802 - entry->vme_start),
10803 vm_map_always_shadow(dst_map));
10804 entry->needs_copy = FALSE;
10805 vm_map_lock_write_to_read(dst_map);
10806 }
10807 dst_object = VME_OBJECT(entry);
10808/*
10809 * unlike with the virtual (aligned) copy we're going
10810 * to fault on it therefore we need a target object.
10811 */
10812 if (dst_object == VM_OBJECT_NULL) {
10813 if (vm_map_lock_read_to_write(dst_map)) {
10814 vm_map_lock_read(dst_map);
10815 goto RetryLookup;
10816 }
10817 dst_object = vm_object_allocate((vm_map_size_t)
10818 entry->vme_end - entry->vme_start,
10819 dst_map->serial_id);
10820 VME_OBJECT_SET(entry, dst_object, false, 0);
10821 VME_OFFSET_SET(entry, 0);
10822 assert(entry->use_pmap);
10823 vm_map_lock_write_to_read(dst_map);
10824 }
10825/*
10826 * Take an object reference and unlock map. The "entry" may
10827 * disappear or change when the map is unlocked.
10828 */
10829 vm_object_reference(dst_object);
10830 version.main_timestamp = dst_map->timestamp;
10831 entry_offset = VME_OFFSET(entry);
10832 entry_end = entry->vme_end;
10833 vm_map_unlock_read(dst_map);
10834/*
10835 * Copy as much as possible in one pass
10836 */
10837 kr = vm_fault_copy(
10838 VME_OBJECT(copy_entry),
10839 VME_OFFSET(copy_entry) + src_offset,
10840 ©_size,
10841 dst_object,
10842 entry_offset + dst_offset,
10843 dst_map,
10844 &version,
10845 THREAD_UNINT );
10846
10847 start += copy_size;
10848 src_offset += copy_size;
10849 amount_left -= copy_size;
10850/*
10851 * Release the object reference
10852 */
10853 vm_object_deallocate(dst_object);
10854/*
10855 * If a hard error occurred, return it now
10856 */
10857 if (kr != KERN_SUCCESS) {
10858 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, kr);
10859 return kr;
10860 }
10861
10862 if ((copy_entry->vme_start + src_offset) == copy_entry->vme_end
10863 || amount_left == 0) {
10864/*
10865 * all done with this copy entry, dispose.
10866 */
10867 copy_entry_next = copy_entry->vme_next;
10868
10869 if (discard_on_success) {
10870 vm_map_copy_entry_unlink(copy, copy_entry);
10871 assert(!copy_entry->is_sub_map);
10872 vm_object_deallocate(VME_OBJECT(copy_entry));
10873 vm_map_copy_entry_dispose(copy_entry);
10874 }
10875
10876 if (copy_entry_next == vm_map_copy_to_entry(copy) &&
10877 amount_left) {
10878/*
10879 * not finished copying but run out of source
10880 */
10881 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_INVALID_ADDRESS);
10882 return KERN_INVALID_ADDRESS;
10883 }
10884
10885 copy_entry = copy_entry_next;
10886
10887 src_offset = 0;
10888 }
10889
10890 if (amount_left == 0) {
10891 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_SUCCESS);
10892 return KERN_SUCCESS;
10893 }
10894
10895 vm_map_lock_read(dst_map);
10896 if (version.main_timestamp == dst_map->timestamp) {
10897 if (start == entry_end) {
10898/*
10899 * destination region is split. Use the version
10900 * information to avoid a lookup in the normal
10901 * case.
10902 */
10903 entry = entry->vme_next;
10904/*
10905 * should be contiguous. Fail if we encounter
10906 * a hole in the destination.
10907 */
10908 if (start != entry->vme_start) {
10909 vm_map_unlock_read(dst_map);
10910 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_INVALID_ADDRESS);
10911 return KERN_INVALID_ADDRESS;
10912 }
10913 }
10914 } else {
10915/*
10916 * Map version check failed.
10917 * we must lookup the entry because somebody
10918 * might have changed the map behind our backs.
10919 */
10920RetryLookup:
10921 if (!vm_map_lookup_entry(dst_map, start, &entry)) {
10922 vm_map_unlock_read(dst_map);
10923 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_INVALID_ADDRESS);
10924 return KERN_INVALID_ADDRESS;
10925 }
10926 }
10927 }/* while */
10928
10929 vmlp_api_end(VM_MAP_COPY_OVERWRITE_UNALIGNED, KERN_SUCCESS);
10930 return KERN_SUCCESS;
10931}/* vm_map_copy_overwrite_unaligned */
10932
10933/*
10934 * Routine: vm_map_copy_overwrite_aligned [internal use only]
10935 *
10936 * Description:
10937 * Does all the vm_trickery possible for whole pages.
10938 *
10939 * Implementation:
10940 *
10941 * If there are no permanent objects in the destination,
10942 * and the source and destination map entry zones match,
10943 * and the destination map entry is not shared,
10944 * then the map entries can be deleted and replaced
10945 * with those from the copy. The following code is the
10946 * basic idea of what to do, but there are lots of annoying
10947 * little details about getting protection and inheritance
10948 * right. Should add protection, inheritance, and sharing checks
10949 * to the above pass and make sure that no wiring is involved.
10950 *
10951 * Callers of this function must call vm_map_copy_require on
10952 * previously created vm_map_copy_t or pass a newly created
10953 * one to ensure that it hasn't been forged.
10954 */
10955
10956int vm_map_copy_overwrite_aligned_src_not_internal = 0;
10957int vm_map_copy_overwrite_aligned_src_not_symmetric = 0;
10958int vm_map_copy_overwrite_aligned_src_large = 0;
10959
10960static kern_return_t
10961vm_map_copy_overwrite_aligned(
10962 vm_map_t dst_map,
10963 vm_map_entry_t tmp_entry,
10964 vm_map_copy_t copy,
10965 vm_map_offset_t start,
10966 __unused pmap_t pmap)
10967{
10968 vm_object_t object;
10969 vm_map_entry_t copy_entry;
10970 vm_map_size_t copy_size;
10971 vm_map_size_t size;
10972 vm_map_entry_t entry;
10973
10974 vmlp_api_start(VM_MAP_COPY_OVERWRITE_ALIGNED);
10975
10976 while ((copy_entry = vm_map_copy_first_entry(copy))
10977 != vm_map_copy_to_entry(copy)) {
10978 copy_size = (copy_entry->vme_end - copy_entry->vme_start);
10979
10980 entry = tmp_entry;
10981
10982 if (entry->is_sub_map) {
10983 /* unnested when clipped earlier */
10984 assert(!entry->use_pmap);
10985 }
10986 if (entry == vm_map_to_entry(dst_map)) {
10987 vm_map_unlock(dst_map);
10988 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_INVALID_ADDRESS);
10989 return KERN_INVALID_ADDRESS;
10990 }
10991 size = (entry->vme_end - entry->vme_start);
10992 /*
10993 * Make sure that no holes popped up in the
10994 * address map, and that the protection is
10995 * still valid, in case the map was unlocked
10996 * earlier.
10997 */
10998
10999 if ((entry->vme_start != start) || ((entry->is_sub_map)
11000 && !entry->needs_copy)) {
11001 vm_map_unlock(dst_map);
11002 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_INVALID_ADDRESS);
11003 return KERN_INVALID_ADDRESS;
11004 }
11005 assert(entry != vm_map_to_entry(dst_map));
11006
11007 /*
11008 * Check protection again
11009 */
11010
11011 if (!(entry->protection & VM_PROT_WRITE)) {
11012 vm_map_unlock(dst_map);
11013 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_PROTECTION_FAILURE);
11014 return KERN_PROTECTION_FAILURE;
11015 }
11016
11017 if (entry->is_sub_map) {
11018 /* not properly implemented */
11019 vm_map_unlock(dst_map);
11020 return KERN_PROTECTION_FAILURE;
11021 }
11022
11023 if (!vm_map_entry_is_overwritable(dst_map, entry)) {
11024 vm_map_unlock(dst_map);
11025 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_PROTECTION_FAILURE);
11026 return KERN_PROTECTION_FAILURE;
11027 }
11028
11029 /*
11030 * If the entry is in transition, we must wait
11031 * for it to exit that state. Anything could happen
11032 * when we unlock the map, so start over.
11033 */
11034 if (entry->in_transition) {
11035 /*
11036 * Say that we are waiting, and wait for entry.
11037 */
11038 entry->needs_wakeup = TRUE;
11039 vm_map_entry_wait(dst_map, THREAD_UNINT);
11040
11041 goto RetryLookup;
11042 }
11043
11044 /*
11045 * Adjust to source size first
11046 */
11047
11048 if (copy_size < size) {
11049 vm_map_clip_end(dst_map, entry, entry->vme_start + copy_size);
11050 size = copy_size;
11051 }
11052
11053 /*
11054 * Adjust to destination size
11055 */
11056
11057 if (size < copy_size) {
11058 vm_map_copy_clip_end(copy, copy_entry,
11059 copy_entry->vme_start + size);
11060 copy_size = size;
11061 }
11062
11063 assert((entry->vme_end - entry->vme_start) == size);
11064 assert((tmp_entry->vme_end - tmp_entry->vme_start) == size);
11065 assert((copy_entry->vme_end - copy_entry->vme_start) == size);
11066
11067 vmlp_range_event_entry(dst_map, tmp_entry);
11068
11069 /*
11070 * If the destination contains temporary unshared memory,
11071 * we can perform the copy by throwing it away and
11072 * installing the source data.
11073 *
11074 * Exceptions for mappings with special semantics:
11075 * + "permanent" entries,
11076 * + JIT regions,
11077 * + TPRO regions,
11078 * + pmap-specific protection policies,
11079 * + VM objects with COPY_NONE copy strategy.
11080 */
11081
11082 object = VME_OBJECT(entry);
11083 if ((!entry->is_shared &&
11084 !entry->vme_permanent &&
11085 !entry->used_for_jit &&
11086#if __arm64e__
11087 !entry->used_for_tpro &&
11088#endif /* __arm64e__ */
11089 !(entry->protection & VM_PROT_EXECUTE) &&
11090 !pmap_has_prot_policy(dst_map->pmap, entry->translated_allow_execute, entry->protection) &&
11091 ((object == VM_OBJECT_NULL) ||
11092 (object->internal &&
11093 !object->true_share &&
11094 object->copy_strategy != MEMORY_OBJECT_COPY_NONE))) ||
11095 entry->needs_copy) {
11096 vm_object_t old_object = VME_OBJECT(entry);
11097 vm_object_offset_t old_offset = VME_OFFSET(entry);
11098 vm_object_offset_t offset;
11099
11100 assert(!entry->is_sub_map);
11101 /*
11102 * Ensure that the source and destination aren't
11103 * identical
11104 */
11105 if (old_object == VME_OBJECT(copy_entry) &&
11106 old_offset == VME_OFFSET(copy_entry)) {
11107 vm_map_copy_entry_unlink(copy, copy_entry);
11108 vm_map_copy_entry_dispose(copy_entry);
11109
11110 if (old_object != VM_OBJECT_NULL) {
11111 vm_object_deallocate(old_object);
11112 }
11113
11114 start = tmp_entry->vme_end;
11115 tmp_entry = tmp_entry->vme_next;
11116 continue;
11117 }
11118
11119#if XNU_TARGET_OS_OSX
11120#define __TRADEOFF1_OBJ_SIZE (64 * 1024 * 1024) /* 64 MB */
11121#define __TRADEOFF1_COPY_SIZE (128 * 1024) /* 128 KB */
11122 if (VME_OBJECT(copy_entry) != VM_OBJECT_NULL &&
11123 VME_OBJECT(copy_entry)->vo_size >= __TRADEOFF1_OBJ_SIZE &&
11124 copy_size <= __TRADEOFF1_COPY_SIZE) {
11125 /*
11126 * Virtual vs. Physical copy tradeoff #1.
11127 *
11128 * Copying only a few pages out of a large
11129 * object: do a physical copy instead of
11130 * a virtual copy, to avoid possibly keeping
11131 * the entire large object alive because of
11132 * those few copy-on-write pages.
11133 */
11134 vm_map_copy_overwrite_aligned_src_large++;
11135 goto slow_copy;
11136 }
11137#endif /* XNU_TARGET_OS_OSX */
11138
11139 if ((dst_map->pmap != kernel_pmap) &&
11140 (VME_ALIAS(entry) >= VM_MEMORY_MALLOC) &&
11141 (VME_ALIAS(entry) <= VM_MEMORY_MALLOC_MEDIUM)) {
11142 vm_object_t new_object, new_shadow;
11143
11144 /*
11145 * We're about to map something over a mapping
11146 * established by malloc()...
11147 */
11148 new_object = VME_OBJECT(copy_entry);
11149 if (new_object != VM_OBJECT_NULL) {
11150 vm_object_lock_shared(new_object);
11151 }
11152 while (new_object != VM_OBJECT_NULL &&
11153#if XNU_TARGET_OS_OSX
11154 !new_object->true_share &&
11155 new_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC &&
11156#endif /* XNU_TARGET_OS_OSX */
11157 new_object->internal) {
11158 new_shadow = new_object->shadow;
11159 if (new_shadow == VM_OBJECT_NULL) {
11160 break;
11161 }
11162 vm_object_lock_shared(new_shadow);
11163 vm_object_unlock(new_object);
11164 new_object = new_shadow;
11165 }
11166 if (new_object != VM_OBJECT_NULL) {
11167 if (!new_object->internal) {
11168 /*
11169 * The new mapping is backed
11170 * by an external object. We
11171 * don't want malloc'ed memory
11172 * to be replaced with such a
11173 * non-anonymous mapping, so
11174 * let's go off the optimized
11175 * path...
11176 */
11177 vm_map_copy_overwrite_aligned_src_not_internal++;
11178 vm_object_unlock(new_object);
11179 goto slow_copy;
11180 }
11181#if XNU_TARGET_OS_OSX
11182 if (new_object->true_share ||
11183 new_object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) {
11184 /*
11185 * Same if there's a "true_share"
11186 * object in the shadow chain, or
11187 * an object with a non-default
11188 * (SYMMETRIC) copy strategy.
11189 */
11190 vm_map_copy_overwrite_aligned_src_not_symmetric++;
11191 vm_object_unlock(new_object);
11192 goto slow_copy;
11193 }
11194#endif /* XNU_TARGET_OS_OSX */
11195 vm_object_unlock(new_object);
11196 }
11197 /*
11198 * The new mapping is still backed by
11199 * anonymous (internal) memory, so it's
11200 * OK to substitute it for the original
11201 * malloc() mapping.
11202 */
11203 }
11204
11205 if (old_object != VM_OBJECT_NULL) {
11206 assert(!entry->vme_permanent);
11207 if (entry->is_sub_map) {
11208 if (entry->use_pmap) {
11209#ifndef NO_NESTED_PMAP
11210 pmap_unnest(dst_map->pmap,
11211 (addr64_t)entry->vme_start,
11212 entry->vme_end - entry->vme_start);
11213#endif /* NO_NESTED_PMAP */
11214 if (dst_map->mapped_in_other_pmaps) {
11215 /* clean up parent */
11216 /* map/maps */
11217 vm_map_submap_pmap_clean(
11218 dst_map, entry->vme_start,
11219 entry->vme_end,
11220 VME_SUBMAP(entry),
11221 VME_OFFSET(entry));
11222 }
11223 } else {
11224 vm_map_submap_pmap_clean(
11225 dst_map, entry->vme_start,
11226 entry->vme_end,
11227 VME_SUBMAP(entry),
11228 VME_OFFSET(entry));
11229 }
11230 vm_map_deallocate(VME_SUBMAP(entry));
11231 } else {
11232 if (dst_map->mapped_in_other_pmaps) {
11233 vm_object_pmap_protect_options(
11234 VME_OBJECT(entry),
11235 VME_OFFSET(entry),
11236 entry->vme_end
11237 - entry->vme_start,
11238 PMAP_NULL,
11239 PAGE_SIZE,
11240 entry->vme_start,
11241 VM_PROT_NONE,
11242 PMAP_OPTIONS_REMOVE);
11243 } else {
11244 pmap_remove_options(
11245 dst_map->pmap,
11246 (addr64_t)(entry->vme_start),
11247 (addr64_t)(entry->vme_end),
11248 PMAP_OPTIONS_REMOVE);
11249 }
11250 vm_object_deallocate(old_object);
11251 }
11252 }
11253
11254 if (entry->iokit_acct) {
11255 /* keep using iokit accounting */
11256 entry->use_pmap = FALSE;
11257 } else {
11258 /* use pmap accounting */
11259 entry->use_pmap = TRUE;
11260 }
11261 assert(!entry->vme_permanent);
11262 VME_OBJECT_SET(entry, VME_OBJECT(copy_entry), false, 0);
11263 object = VME_OBJECT(entry);
11264 entry->needs_copy = copy_entry->needs_copy;
11265 entry->wired_count = 0;
11266 entry->user_wired_count = 0;
11267 offset = VME_OFFSET(copy_entry);
11268 VME_OFFSET_SET(entry, offset);
11269
11270 vm_map_copy_entry_unlink(copy, copy_entry);
11271 vm_map_copy_entry_dispose(copy_entry);
11272
11273 /*
11274 * we could try to push pages into the pmap at this point, BUT
11275 * this optimization only saved on average 2 us per page if ALL
11276 * the pages in the source were currently mapped
11277 * and ALL the pages in the dest were touched, if there were fewer
11278 * than 2/3 of the pages touched, this optimization actually cost more cycles
11279 * it also puts a lot of pressure on the pmap layer w/r to mapping structures
11280 */
11281
11282 /*
11283 * Set up for the next iteration. The map
11284 * has not been unlocked, so the next
11285 * address should be at the end of this
11286 * entry, and the next map entry should be
11287 * the one following it.
11288 */
11289
11290 start = tmp_entry->vme_end;
11291 tmp_entry = tmp_entry->vme_next;
11292 } else {
11293 vm_map_version_t version;
11294 vm_object_t dst_object;
11295 vm_object_offset_t dst_offset;
11296 kern_return_t r;
11297
11298slow_copy:
11299 if (entry->needs_copy) {
11300 VME_OBJECT_SHADOW(entry,
11301 (entry->vme_end -
11302 entry->vme_start),
11303 vm_map_always_shadow(dst_map));
11304 entry->needs_copy = FALSE;
11305 }
11306
11307 dst_object = VME_OBJECT(entry);
11308 dst_offset = VME_OFFSET(entry);
11309
11310 /*
11311 * Take an object reference, and record
11312 * the map version information so that the
11313 * map can be safely unlocked.
11314 */
11315
11316 if (dst_object == VM_OBJECT_NULL) {
11317 /*
11318 * We would usually have just taken the
11319 * optimized path above if the destination
11320 * object has not been allocated yet. But we
11321 * now disable that optimization if the copy
11322 * entry's object is not backed by anonymous
11323 * memory to avoid replacing malloc'ed
11324 * (i.e. re-usable) anonymous memory with a
11325 * not-so-anonymous mapping.
11326 * So we have to handle this case here and
11327 * allocate a new VM object for this map entry.
11328 */
11329 dst_object = vm_object_allocate(
11330 entry->vme_end - entry->vme_start,
11331 dst_map->serial_id
11332 );
11333 dst_offset = 0;
11334 VME_OBJECT_SET(entry, dst_object, false, 0);
11335 VME_OFFSET_SET(entry, dst_offset);
11336 assert(entry->use_pmap);
11337 }
11338
11339 vm_object_reference(dst_object);
11340
11341 /* account for unlock bumping up timestamp */
11342 version.main_timestamp = dst_map->timestamp + 1;
11343
11344 vm_map_unlock(dst_map);
11345
11346 /*
11347 * Copy as much as possible in one pass
11348 */
11349
11350 copy_size = size;
11351 r = vm_fault_copy(
11352 VME_OBJECT(copy_entry),
11353 VME_OFFSET(copy_entry),
11354 ©_size,
11355 dst_object,
11356 dst_offset,
11357 dst_map,
11358 &version,
11359 THREAD_UNINT );
11360
11361 /*
11362 * Release the object reference
11363 */
11364
11365 vm_object_deallocate(dst_object);
11366
11367 /*
11368 * If a hard error occurred, return it now
11369 */
11370
11371 if (r != KERN_SUCCESS) {
11372 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, r);
11373 return r;
11374 }
11375
11376 if (copy_size != 0) {
11377 /*
11378 * Dispose of the copied region
11379 */
11380
11381 vm_map_copy_clip_end(copy, copy_entry,
11382 copy_entry->vme_start + copy_size);
11383 vm_map_copy_entry_unlink(copy, copy_entry);
11384 vm_object_deallocate(VME_OBJECT(copy_entry));
11385 vm_map_copy_entry_dispose(copy_entry);
11386 }
11387
11388 /*
11389 * Pick up in the destination map where we left off.
11390 *
11391 * Use the version information to avoid a lookup
11392 * in the normal case.
11393 */
11394
11395 start += copy_size;
11396 vm_map_lock(dst_map);
11397 if (version.main_timestamp == dst_map->timestamp &&
11398 copy_size != 0) {
11399 /* We can safely use saved tmp_entry value */
11400 vm_map_clip_end(dst_map, tmp_entry, start);
11401 tmp_entry = tmp_entry->vme_next;
11402 } else {
11403 /* Must do lookup of tmp_entry */
11404
11405RetryLookup:
11406 if (!vm_map_lookup_entry(dst_map, start, &tmp_entry)) {
11407 vm_map_unlock(dst_map);
11408 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_INVALID_ADDRESS);
11409 return KERN_INVALID_ADDRESS;
11410 }
11411 vm_map_clip_start(dst_map, tmp_entry, start);
11412 }
11413 }
11414 }/* while */
11415
11416 vmlp_api_end(VM_MAP_COPY_OVERWRITE_ALIGNED, KERN_SUCCESS);
11417 return KERN_SUCCESS;
11418}/* vm_map_copy_overwrite_aligned */
11419
11420/*
11421 * Routine: vm_map_copyin_kernel_buffer [internal use only]
11422 *
11423 * Description:
11424 * Copy in data to a kernel buffer from space in the
11425 * source map. The original space may be optionally
11426 * deallocated.
11427 *
11428 * If successful, returns a new copy object.
11429 */
11430static kern_return_t
11431vm_map_copyin_kernel_buffer(
11432 vm_map_t src_map,
11433 vm_map_offset_t src_addr,
11434 vm_map_size_t len,
11435 vm_map_copyin_strategy strategy,
11436 boolean_t src_destroy,
11437 vm_map_copy_t *copy_result)
11438{
11439 kern_return_t kr;
11440 vm_map_copy_t copy;
11441 void *kdata;
11442
11443 if (len > msg_ool_size_small) {
11444#pragma unused(strategy)
11445 return KERN_INVALID_ARGUMENT;
11446 }
11447
11448 kdata = kalloc_data(len, Z_WAITOK);
11449 if (kdata == NULL) {
11450 return KERN_RESOURCE_SHORTAGE;
11451 }
11452 kr = copyinmap(src_map, src_addr, kdata, (vm_size_t)len);
11453 if (kr != KERN_SUCCESS) {
11454 kfree_data(kdata, len);
11455 return kr;
11456 }
11457
11458 copy = vm_map_copy_allocate(VM_MAP_COPY_KERNEL_BUFFER);
11459 copy->cpy_kdata = kdata;
11460 copy->size = len;
11461 copy->offset = 0;
11462
11463 if (src_destroy) {
11464 vmr_flags_t flags = VM_MAP_REMOVE_INTERRUPTIBLE;
11465
11466 if (src_map == kernel_map) {
11467 flags |= VM_MAP_REMOVE_KUNWIRE;
11468 }
11469
11470 (void)vm_map_remove_guard(src_map,
11471 vm_map_trunc_page(src_addr, VM_MAP_PAGE_MASK(src_map)),
11472 vm_map_round_page(src_addr + len, VM_MAP_PAGE_MASK(src_map)),
11473 flags, KMEM_GUARD_NONE);
11474 }
11475
11476 *copy_result = copy;
11477 return KERN_SUCCESS;
11478}
11479
11480/*
11481 * Routine: vm_map_copyout_kernel_buffer [internal use only]
11482 *
11483 * Description:
11484 * Copy out data from a kernel buffer into space in the
11485 * destination map. The space may be otpionally dynamically
11486 * allocated.
11487 *
11488 * If successful, consumes the copy object.
11489 * Otherwise, the caller is responsible for it.
11490 *
11491 * Callers of this function must call vm_map_copy_require on
11492 * previously created vm_map_copy_t or pass a newly created
11493 * one to ensure that it hasn't been forged.
11494 */
11495static int vm_map_copyout_kernel_buffer_failures = 0;
11496static kern_return_t
11497vm_map_copyout_kernel_buffer(
11498 vm_map_t map,
11499 vm_map_address_t *addr, /* IN/OUT */
11500 vm_map_copy_t copy,
11501 vm_map_size_t copy_size,
11502 boolean_t overwrite,
11503 boolean_t consume_on_success)
11504{
11505 kern_return_t kr = KERN_SUCCESS;
11506 thread_t thread = current_thread();
11507
11508 assert(copy->size == copy_size);
11509
11510 /*
11511 * check for corrupted vm_map_copy structure
11512 */
11513 bool is_corrupt_vm_map_copy_detected = copy->offset != 0;
11514 if (copy_size > msg_ool_size_small) {
11515 is_corrupt_vm_map_copy_detected = true;
11516 }
11517 if (is_corrupt_vm_map_copy_detected) {
11518 panic("Invalid vm_map_copy_t sz:%lld, ofst:%lld",
11519 (long long)copy->size, (long long)copy->offset);
11520 }
11521
11522 if (!overwrite) {
11523 /*
11524 * Allocate space in the target map for the data
11525 */
11526 vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_ANYWHERE();
11527
11528 if (map == kernel_map) {
11529 vmk_flags.vmkf_range_id = kmem_needs_data_share_range() ?
11530 KMEM_RANGE_ID_DATA_SHARED : KMEM_RANGE_ID_DATA;
11531 }
11532
11533 *addr = 0;
11534 kr = vm_map_enter(map,
11535 addr,
11536 vm_map_round_page(copy_size,
11537 VM_MAP_PAGE_MASK(map)),
11538 (vm_map_offset_t) 0,
11539 vmk_flags,
11540 VM_OBJECT_NULL,
11541 (vm_object_offset_t) 0,
11542 FALSE,
11543 VM_PROT_DEFAULT,
11544 VM_PROT_ALL,
11545 VM_INHERIT_DEFAULT);
11546 if (kr != KERN_SUCCESS) {
11547 return kr;
11548 }
11549#if KASAN
11550 if (map->pmap == kernel_pmap) {
11551 kasan_notify_address(*addr, copy->size);
11552 }
11553#endif
11554 }
11555
11556 /*
11557 * Copyout the data from the kernel buffer to the target map.
11558 */
11559 if (thread->map == map) {
11560 /*
11561 * If the target map is the current map, just do
11562 * the copy.
11563 */
11564 assert((vm_size_t)copy_size == copy_size);
11565 if (copyout(copy->cpy_kdata, *addr, (vm_size_t)copy_size)) {
11566 kr = KERN_INVALID_ADDRESS;
11567 }
11568 } else {
11569 vm_map_switch_context_t switch_ctx;
11570
11571 /*
11572 * If the target map is another map, assume the
11573 * target's address space identity for the duration
11574 * of the copy.
11575 */
11576 vm_map_reference(map);
11577 switch_ctx = vm_map_switch_to(map);
11578
11579 assert((vm_size_t)copy_size == copy_size);
11580 if (copyout(copy->cpy_kdata, *addr, (vm_size_t)copy_size)) {
11581 vm_map_copyout_kernel_buffer_failures++;
11582 kr = KERN_INVALID_ADDRESS;
11583 }
11584
11585 vm_map_switch_back(switch_ctx);
11586 vm_map_deallocate(map);
11587 }
11588
11589 if (kr != KERN_SUCCESS) {
11590 /* the copy failed, clean up */
11591 if (!overwrite) {
11592 /*
11593 * Deallocate the space we allocated in the target map.
11594 */
11595 (void) vm_map_remove(map,
11596 vm_map_trunc_page(*addr,
11597 VM_MAP_PAGE_MASK(map)),
11598 vm_map_round_page((*addr +
11599 vm_map_round_page(copy_size,
11600 VM_MAP_PAGE_MASK(map))),
11601 VM_MAP_PAGE_MASK(map)));
11602 *addr = 0;
11603 }
11604 } else {
11605 /* copy was successful, dicard the copy structure */
11606 if (consume_on_success) {
11607 kfree_data(copy->cpy_kdata, copy_size);
11608 zfree_id(ZONE_ID_VM_MAP_COPY, copy);
11609 }
11610 }
11611
11612 return kr;
11613}
11614
11615/*
11616 * Routine: vm_map_copy_insert [internal use only]
11617 *
11618 * Description:
11619 * Link a copy chain ("copy") into a map at the
11620 * specified location (after "where").
11621 *
11622 * Callers of this function must call vm_map_copy_require on
11623 * previously created vm_map_copy_t or pass a newly created
11624 * one to ensure that it hasn't been forged.
11625 * Side effects:
11626 * The copy chain is destroyed.
11627 */
11628static void
11629vm_map_copy_insert(
11630 vm_map_t map,
11631 vm_map_entry_t after_where,
11632 vm_map_copy_t copy)
11633{
11634 vm_map_entry_t entry;
11635
11636 while (vm_map_copy_first_entry(copy) != vm_map_copy_to_entry(copy)) {
11637 entry = vm_map_copy_first_entry(copy);
11638 vm_map_copy_entry_unlink(copy, entry);
11639 vm_map_store_entry_link(map, after_where, entry,
11640 VM_MAP_KERNEL_FLAGS_NONE);
11641 vmlp_range_event_entry(map, entry);
11642 after_where = entry;
11643 }
11644 zfree_id(ZONE_ID_VM_MAP_COPY, copy);
11645}
11646
11647/*
11648 * Callers of this function must call vm_map_copy_require on
11649 * previously created vm_map_copy_t or pass a newly created
11650 * one to ensure that it hasn't been forged.
11651 */
11652void
11653vm_map_copy_remap(
11654 vm_map_t map,
11655 vm_map_entry_t where,
11656 vm_map_copy_t copy,
11657 vm_map_offset_t adjustment,
11658 vm_prot_t cur_prot,
11659 vm_prot_t max_prot,
11660 vm_inherit_t inheritance)
11661{
11662 vm_map_entry_t copy_entry, new_entry;
11663
11664 for (copy_entry = vm_map_copy_first_entry(copy);
11665 copy_entry != vm_map_copy_to_entry(copy);
11666 copy_entry = copy_entry->vme_next) {
11667 /* get a new VM map entry for the map */
11668 new_entry = vm_map_entry_create(map);
11669 /* copy the "copy entry" to the new entry */
11670 vm_map_entry_copy(map, new_entry, copy_entry);
11671 /* adjust "start" and "end" */
11672 new_entry->vme_start += adjustment;
11673 new_entry->vme_end += adjustment;
11674 /* clear some attributes */
11675 new_entry->inheritance = inheritance;
11676 new_entry->protection = cur_prot;
11677 new_entry->max_protection = max_prot;
11678 new_entry->behavior = VM_BEHAVIOR_DEFAULT;
11679 /* take an extra reference on the entry's "object" */
11680 if (new_entry->is_sub_map) {
11681 assert(!new_entry->use_pmap); /* not nested */
11682 vm_map_reference(VME_SUBMAP(new_entry));
11683 } else {
11684 vm_object_reference(VME_OBJECT(new_entry));
11685 }
11686 /* insert the new entry in the map */
11687 vm_map_store_entry_link(map, where, new_entry,
11688 VM_MAP_KERNEL_FLAGS_NONE);
11689 vmlp_range_event_entry(map, new_entry);
11690 /* continue inserting the "copy entries" after the new entry */
11691 where = new_entry;
11692 }
11693}
11694
11695
11696/*
11697 * Returns true if *size matches (or is in the range of) copy->size.
11698 * Upon returning true, the *size field is updated with the actual size of the
11699 * copy object (may be different for VM_MAP_COPY_ENTRY_LIST types)
11700 */
11701boolean_t
11702vm_map_copy_validate_size(
11703 vm_map_t dst_map,
11704 vm_map_copy_t copy,
11705 vm_map_size_t *size)
11706{
11707 if (copy == VM_MAP_COPY_NULL) {
11708 return FALSE;
11709 }
11710
11711 /*
11712 * Assert that the vm_map_copy is coming from the right
11713 * zone and hasn't been forged
11714 */
11715 vm_map_copy_require(copy);
11716
11717 vm_map_size_t copy_sz = copy->size;
11718 vm_map_size_t sz = *size;
11719 switch (copy->type) {
11720 case VM_MAP_COPY_KERNEL_BUFFER:
11721 if (sz == copy_sz) {
11722 return TRUE;
11723 }
11724 break;
11725 case VM_MAP_COPY_ENTRY_LIST:
11726 /*
11727 * potential page-size rounding prevents us from exactly
11728 * validating this flavor of vm_map_copy, but we can at least
11729 * assert that it's within a range.
11730 */
11731 if (copy_sz >= sz &&
11732 copy_sz <= vm_map_round_page(sz, VM_MAP_PAGE_MASK(dst_map))) {
11733 *size = copy_sz;
11734 return TRUE;
11735 }
11736 break;
11737 default:
11738 break;
11739 }
11740 return FALSE;
11741}
11742
11743static kern_return_t
11744vm_map_copyout_internal(
11745 vm_map_t dst_map,
11746 vm_map_address_t *dst_addr, /* OUT */
11747 vm_map_copy_t copy,
11748 vm_map_size_ut copy_size_u,
11749 boolean_t consume_on_success,
11750 vm_prot_t cur_protection,
11751 vm_prot_t max_protection,
11752 vm_inherit_t inheritance)
11753{
11754 vm_map_size_t size, copy_size;
11755 vm_map_size_t adjustment;
11756 vm_map_offset_t start;
11757 vm_object_offset_t vm_copy_start;
11758 vm_map_entry_t last;
11759 vm_map_entry_t entry;
11760 vm_map_copy_t original_copy;
11761 kern_return_t kr;
11762 vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_ANYWHERE();
11763
11764 vmlp_api_start(VM_MAP_COPYOUT_INTERNAL);
11765
11766 /*
11767 * Check for null copy object.
11768 */
11769
11770 if (copy == VM_MAP_COPY_NULL) {
11771 *dst_addr = 0;
11772 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, KERN_SUCCESS);
11773 return KERN_SUCCESS;
11774 }
11775
11776 /*
11777 * Assert that the vm_map_copy is coming from the right
11778 * zone and hasn't been forged
11779 */
11780 vm_map_copy_require(copy);
11781
11782 if (!VM_SANITIZE_UNSAFE_IS_EQUAL(copy_size_u, copy->size)) {
11783 *dst_addr = 0;
11784 ktriage_record(thread_tid(current_thread()),
11785 KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM,
11786 KDBG_TRIAGE_RESERVED,
11787 KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SIZE_ERROR),
11788 KERN_FAILURE /* arg */);
11789 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, KERN_FAILURE);
11790 return KERN_FAILURE;
11791 }
11792 copy_size = copy->size;
11793
11794 /*
11795 * Check for special kernel buffer allocated
11796 * by new_ipc_kmsg_copyin.
11797 */
11798
11799 if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
11800 kr = vm_map_copyout_kernel_buffer(dst_map, dst_addr,
11801 copy, copy_size, FALSE,
11802 consume_on_success);
11803 if (kr) {
11804 ktriage_record(thread_tid(current_thread()),
11805 KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM,
11806 KDBG_TRIAGE_RESERVED,
11807 KDBG_TRIAGE_VM_COPYOUT_KERNEL_BUFFER_ERROR), kr /* arg */);
11808 }
11809 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, kr);
11810 return kr;
11811 }
11812
11813
11814 original_copy = copy;
11815 if (copy->cpy_hdr.page_shift != VM_MAP_PAGE_SHIFT(dst_map)) {
11816 vm_map_copy_t target_copy;
11817 vm_map_offset_t overmap_start, overmap_end, trimmed_start;
11818
11819 target_copy = VM_MAP_COPY_NULL;
11820 DEBUG4K_ADJUST("adjusting...\n");
11821 kr = vm_map_copy_adjust_to_target(
11822 copy,
11823 0, /* offset */
11824 copy->size, /* size */
11825 dst_map,
11826 TRUE, /* copy */
11827 &target_copy,
11828 &overmap_start,
11829 &overmap_end,
11830 &trimmed_start);
11831 if (kr != KERN_SUCCESS) {
11832 DEBUG4K_COPY("adjust failed 0x%x\n", kr);
11833 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOUT_INTERNAL_ADJUSTING_ERROR), kr /* arg */);
11834 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, kr);
11835 return kr;
11836 }
11837 DEBUG4K_COPY("copy %p (%d 0x%llx 0x%llx) dst_map %p (%d) target_copy %p (%d 0x%llx 0x%llx) overmap_start 0x%llx overmap_end 0x%llx trimmed_start 0x%llx\n", copy, copy->cpy_hdr.page_shift, copy->offset, (uint64_t)copy->size, dst_map, VM_MAP_PAGE_SHIFT(dst_map), target_copy, target_copy->cpy_hdr.page_shift, target_copy->offset, (uint64_t)target_copy->size, (uint64_t)overmap_start, (uint64_t)overmap_end, (uint64_t)trimmed_start);
11838 if (target_copy != copy) {
11839 copy = target_copy;
11840 }
11841 copy_size = copy->size;
11842 }
11843
11844 /*
11845 * Find space for the data
11846 */
11847
11848 vm_copy_start = vm_map_trunc_page((vm_map_size_t)copy->offset,
11849 VM_MAP_COPY_PAGE_MASK(copy));
11850 size = vm_map_round_page((vm_map_size_t)copy->offset + copy_size,
11851 VM_MAP_COPY_PAGE_MASK(copy))
11852 - vm_copy_start;
11853
11854 vm_map_kernel_flags_update_range_id(&vmk_flags, dst_map, size);
11855
11856 vm_map_lock(dst_map);
11857 kr = vm_map_locate_space_anywhere(dst_map, size, 0, vmk_flags,
11858 &start, &last);
11859 if (kr != KERN_SUCCESS) {
11860 vm_map_unlock(dst_map);
11861 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_COPYOUT_INTERNAL_SPACE_ERROR), kr /* arg */);
11862 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, kr);
11863 return kr;
11864 }
11865
11866 adjustment = start - vm_copy_start;
11867 if (!consume_on_success) {
11868 /*
11869 * We're not allowed to consume "copy", so we'll have to
11870 * copy its map entries into the destination map below.
11871 * No need to re-allocate map entries from the correct
11872 * (pageable or not) zone, since we'll get new map entries
11873 * during the transfer.
11874 * We'll also adjust the map entries's "start" and "end"
11875 * during the transfer, to keep "copy"'s entries consistent
11876 * with its "offset".
11877 */
11878 goto after_adjustments;
11879 }
11880
11881 /*
11882 * Since we're going to just drop the map
11883 * entries from the copy into the destination
11884 * map, they must come from the same pool.
11885 */
11886
11887 if (copy->cpy_hdr.entries_pageable != dst_map->hdr.entries_pageable) {
11888 /*
11889 * Mismatches occur when dealing with the default
11890 * pager.
11891 */
11892 vm_map_entry_t next, new;
11893
11894 /*
11895 * Find the zone that the copies were allocated from
11896 */
11897
11898 entry = vm_map_copy_first_entry(copy);
11899
11900 /*
11901 * Reinitialize the copy so that vm_map_copy_entry_link
11902 * will work.
11903 */
11904 vm_map_store_copy_reset(copy, entry);
11905 copy->cpy_hdr.entries_pageable = dst_map->hdr.entries_pageable;
11906
11907 /*
11908 * Copy each entry.
11909 */
11910 while (entry != vm_map_copy_to_entry(copy)) {
11911 new = vm_map_copy_entry_create(copy);
11912 vm_map_entry_copy_full(new, entry);
11913 new->vme_no_copy_on_read = FALSE;
11914 assert(!new->iokit_acct);
11915 if (new->is_sub_map) {
11916 /* clr address space specifics */
11917 new->use_pmap = FALSE;
11918 }
11919 vm_map_copy_entry_link(copy,
11920 vm_map_copy_last_entry(copy),
11921 new);
11922 next = entry->vme_next;
11923 vm_map_entry_dispose(entry);
11924 entry = next;
11925 }
11926 }
11927
11928 /*
11929 * Adjust the addresses in the copy chain, and
11930 * reset the region attributes.
11931 */
11932
11933 for (entry = vm_map_copy_first_entry(copy);
11934 entry != vm_map_copy_to_entry(copy);
11935 entry = entry->vme_next) {
11936 entry->vme_start += adjustment;
11937 entry->vme_end += adjustment;
11938
11939 assert(VM_MAP_PAGE_ALIGNED(entry->vme_start,
11940 VM_MAP_PAGE_MASK(dst_map)));
11941 assert(VM_MAP_PAGE_ALIGNED(entry->vme_end,
11942 VM_MAP_PAGE_MASK(dst_map)));
11943
11944 entry->inheritance = VM_INHERIT_DEFAULT;
11945 entry->protection = VM_PROT_DEFAULT;
11946 entry->max_protection = VM_PROT_ALL;
11947 entry->behavior = VM_BEHAVIOR_DEFAULT;
11948
11949 /*
11950 * If the entry is now wired,
11951 * map the pages into the destination map.
11952 */
11953 if (entry->wired_count != 0) {
11954 vm_map_offset_t va;
11955 vm_object_offset_t offset;
11956 vm_object_t object;
11957 vm_prot_t prot;
11958 int type_of_fault;
11959 uint8_t object_lock_type = OBJECT_LOCK_EXCLUSIVE;
11960
11961 /* TODO4K would need to use actual page size */
11962 assert(VM_MAP_PAGE_SHIFT(dst_map) == PAGE_SHIFT);
11963
11964 object = VME_OBJECT(entry);
11965 offset = VME_OFFSET(entry);
11966 va = entry->vme_start;
11967
11968 pmap_pageable(dst_map->pmap,
11969 entry->vme_start,
11970 entry->vme_end,
11971 TRUE);
11972
11973 while (va < entry->vme_end) {
11974 vm_page_t m;
11975 struct vm_object_fault_info fault_info = {
11976 .interruptible = THREAD_UNINT,
11977 };
11978
11979 /*
11980 * Look up the page in the object.
11981 * Assert that the page will be found in the
11982 * top object:
11983 * either
11984 * the object was newly created by
11985 * vm_object_copy_slowly, and has
11986 * copies of all of the pages from
11987 * the source object
11988 * or
11989 * the object was moved from the old
11990 * map entry; because the old map
11991 * entry was wired, all of the pages
11992 * were in the top-level object.
11993 * (XXX not true if we wire pages for
11994 * reading)
11995 */
11996 vm_object_lock(object);
11997
11998 m = vm_page_lookup(object, offset);
11999 if (m == VM_PAGE_NULL || !VM_PAGE_WIRED(m) ||
12000 m->vmp_absent) {
12001 panic("vm_map_copyout: wiring %p", m);
12002 }
12003
12004 prot = entry->protection;
12005
12006 if (override_nx(dst_map, VME_ALIAS(entry)) &&
12007 prot) {
12008 prot |= VM_PROT_EXECUTE;
12009 }
12010
12011 type_of_fault = DBG_CACHE_HIT_FAULT;
12012
12013 fault_info.user_tag = VME_ALIAS(entry);
12014 fault_info.pmap_options = 0;
12015 if (entry->iokit_acct ||
12016 (!entry->is_sub_map && !entry->use_pmap)) {
12017 fault_info.pmap_options |= PMAP_OPTIONS_ALT_ACCT;
12018 }
12019 if (entry->vme_xnu_user_debug &&
12020 !VM_PAGE_OBJECT(m)->code_signed) {
12021 /*
12022 * Modified code-signed executable
12023 * region: this page does not belong
12024 * to a code-signed VM object, so it
12025 * must have been copied and should
12026 * therefore be typed XNU_USER_DEBUG
12027 * rather than XNU_USER_EXEC.
12028 */
12029 fault_info.pmap_options |= PMAP_OPTIONS_XNU_USER_DEBUG;
12030 }
12031
12032 bool page_sleep_needed = false;
12033 vm_fault_enter(m,
12034 dst_map->pmap,
12035 va,
12036 PAGE_SIZE, 0,
12037 prot,
12038 prot,
12039 VM_PAGE_WIRED(m),
12040 VM_KERN_MEMORY_NONE, /* tag - not wiring */
12041 &fault_info,
12042 NULL, /* need_retry */
12043 &type_of_fault,
12044 &object_lock_type, /*Exclusive mode lock. Will remain unchanged.*/
12045 &page_sleep_needed);
12046
12047 vm_object_unlock(object);
12048 assert(!page_sleep_needed);
12049
12050 offset += PAGE_SIZE_64;
12051 va += PAGE_SIZE;
12052 }
12053 }
12054 }
12055
12056after_adjustments:
12057
12058 /*
12059 * Correct the page alignment for the result
12060 */
12061
12062 *dst_addr = start + (copy->offset - vm_copy_start);
12063
12064#if KASAN
12065 kasan_notify_address(*dst_addr, size);
12066#endif
12067
12068 /*
12069 * Update the hints and the map size
12070 */
12071
12072 if (consume_on_success) {
12073 SAVE_HINT_MAP_WRITE(dst_map, vm_map_copy_last_entry(copy));
12074 } else {
12075 SAVE_HINT_MAP_WRITE(dst_map, last);
12076 }
12077
12078 dst_map->size += size;
12079
12080 /*
12081 * Link in the copy
12082 */
12083
12084 if (consume_on_success) {
12085 vm_map_copy_insert(dst_map, last, copy);
12086 if (copy != original_copy) {
12087 vm_map_copy_discard(original_copy);
12088 original_copy = VM_MAP_COPY_NULL;
12089 }
12090 } else {
12091 vm_map_copy_remap(dst_map, last, copy, adjustment,
12092 cur_protection, max_protection,
12093 inheritance);
12094 if (copy != original_copy && original_copy != VM_MAP_COPY_NULL) {
12095 vm_map_copy_discard(copy);
12096 copy = original_copy;
12097 }
12098 }
12099
12100
12101 vm_map_unlock(dst_map);
12102
12103 /*
12104 * XXX If wiring_required, call vm_map_pageable
12105 */
12106
12107 vmlp_api_end(VM_MAP_COPYOUT_INTERNAL, KERN_SUCCESS);
12108 return KERN_SUCCESS;
12109}
12110
12111/*
12112 * Routine: vm_map_copyout_size
12113 *
12114 * Description:
12115 * Copy out a copy chain ("copy") into newly-allocated
12116 * space in the destination map. Uses a prevalidated
12117 * size for the copy object (vm_map_copy_validate_size).
12118 *
12119 * If successful, consumes the copy object.
12120 * Otherwise, the caller is responsible for it.
12121 */
12122kern_return_t
12123vm_map_copyout_size(
12124 vm_map_t dst_map,
12125 vm_map_address_t *dst_addr, /* OUT */
12126 vm_map_copy_t copy,
12127 vm_map_size_ut copy_size)
12128{
12129 return vm_map_copyout_internal(dst_map, dst_addr, copy, copy_size,
12130 TRUE, /* consume_on_success */
12131 VM_PROT_DEFAULT,
12132 VM_PROT_ALL,
12133 VM_INHERIT_DEFAULT);
12134}
12135
12136/*
12137 * Routine: vm_map_copyout
12138 *
12139 * Description:
12140 * Copy out a copy chain ("copy") into newly-allocated
12141 * space in the destination map.
12142 *
12143 * If successful, consumes the copy object.
12144 * Otherwise, the caller is responsible for it.
12145 */
12146kern_return_t
12147vm_map_copyout(
12148 vm_map_t dst_map,
12149 vm_map_address_t *dst_addr, /* OUT */
12150 vm_map_copy_t copy)
12151{
12152 return vm_map_copyout_internal(dst_map, dst_addr, copy, copy ? copy->size : 0,
12153 TRUE, /* consume_on_success */
12154 VM_PROT_DEFAULT,
12155 VM_PROT_ALL,
12156 VM_INHERIT_DEFAULT);
12157}
12158
12159/*
12160 * Routine: vm_map_copyin
12161 *
12162 * Description:
12163 * see vm_map_copyin_common. Exported via Unsupported.exports.
12164 *
12165 */
12166kern_return_t
12167vm_map_copyin(
12168 vm_map_t src_map,
12169 vm_map_address_ut src_addr,
12170 vm_map_size_ut len,
12171 boolean_t src_destroy,
12172 vm_map_copy_t *copy_result) /* OUT */
12173{
12174 return vm_map_copyin_common(src_map, src_addr, len, src_destroy,
12175 FALSE, copy_result, FALSE);
12176}
12177
12178/*
12179 * Routine: vm_map_copyin_common
12180 *
12181 * Description:
12182 * Copy the specified region (src_addr, len) from the
12183 * source address space (src_map), possibly removing
12184 * the region from the source address space (src_destroy).
12185 *
12186 * Returns:
12187 * A vm_map_copy_t object (copy_result), suitable for
12188 * insertion into another address space (using vm_map_copyout),
12189 * copying over another address space region (using
12190 * vm_map_copy_overwrite). If the copy is unused, it
12191 * should be destroyed (using vm_map_copy_discard).
12192 *
12193 * In/out conditions:
12194 * The source map should not be locked on entry.
12195 */
12196
12197typedef struct submap_map {
12198 vm_map_t parent_map;
12199 vm_map_offset_t base_start;
12200 vm_map_offset_t base_end;
12201 vm_map_size_t base_len;
12202 struct submap_map *next;
12203} submap_map_t;
12204
12205kern_return_t
12206vm_map_copyin_common(
12207 vm_map_t src_map,
12208 vm_map_address_ut src_addr,
12209 vm_map_size_ut len,
12210 boolean_t src_destroy,
12211 __unused boolean_t src_volatile,
12212 vm_map_copy_t *copy_result, /* OUT */
12213 boolean_t use_maxprot)
12214{
12215 int flags;
12216
12217 flags = 0;
12218 if (src_destroy) {
12219 flags |= VM_MAP_COPYIN_SRC_DESTROY;
12220 }
12221 if (use_maxprot) {
12222 flags |= VM_MAP_COPYIN_USE_MAXPROT;
12223 }
12224 return vm_map_copyin_internal(src_map,
12225 src_addr,
12226 len,
12227 flags,
12228 copy_result);
12229}
12230
12231static __attribute__((always_inline, warn_unused_result))
12232kern_return_t
12233vm_map_copyin_sanitize(
12234 vm_map_t src_map,
12235 vm_map_address_ut src_addr_u,
12236 vm_map_size_ut len_u,
12237 vm_map_offset_t *src_start,
12238 vm_map_offset_t *src_end,
12239 vm_map_size_t *len,
12240 vm_map_offset_t *src_addr_unaligned)
12241{
12242 kern_return_t kr;
12243 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS |
12244 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES |
12245 VM_SANITIZE_FLAGS_CHECK_ADDR_RANGE;
12246
12247#if KASAN_TBI
12248 if (vm_kernel_map_is_kernel(src_map)) {
12249 flags |= VM_SANITIZE_FLAGS_CANONICALIZE;
12250 }
12251#endif /* KASAN_TBI */
12252
12253 kr = vm_sanitize_addr_size(src_addr_u, len_u,
12254 VM_SANITIZE_CALLER_VM_MAP_COPYIN,
12255 src_map,
12256 flags,
12257 src_start, src_end, len);
12258 if (__improbable(kr != KERN_SUCCESS)) {
12259 return kr;
12260 }
12261
12262 /*
12263 * Compute (page aligned) start and end of region
12264 */
12265 *src_addr_unaligned = *src_start; /* remember unaligned value */
12266 *src_start = vm_map_trunc_page(*src_addr_unaligned,
12267 VM_MAP_PAGE_MASK(src_map));
12268 *src_end = vm_map_round_page(*src_end, VM_MAP_PAGE_MASK(src_map));
12269
12270
12271 return KERN_SUCCESS;
12272}
12273
12274
12275static vm_map_copyin_strategy
12276_vm_map_copyin_select_strategy(
12277 vm_map_t src_map,
12278 vm_map_size_t len,
12279 vm_map_offset_t src_start,
12280 vm_map_offset_t src_end,
12281 boolean_t use_maxprot,
12282 boolean_t preserve_purgeable,
12283 int flags
12284 )
12285{
12286 /*
12287 * If the copy is sufficiently small, use a kernel buffer instead
12288 * of making a virtual copy. The theory being that the cost of
12289 * setting up VM (and taking C-O-W faults) dominates the copy costs
12290 * for small regions.
12291 */
12292 if ((len <= msg_ool_size_small) &&
12293 !use_maxprot &&
12294 !preserve_purgeable &&
12295 !(flags & VM_MAP_COPYIN_ENTRY_LIST) &&
12296 /*
12297 * Since the "msg_ool_size_small" threshold was increased and
12298 * vm_map_copyin_kernel_buffer() doesn't handle accesses beyond the
12299 * address space limits, we revert to doing a virtual copy if the
12300 * copied range goes beyond those limits. Otherwise, mach_vm_read()
12301 * of the commpage would now fail when it used to work.
12302 */
12303 (src_start >= vm_map_min(src_map) &&
12304 src_start < vm_map_max(src_map) &&
12305 src_end >= vm_map_min(src_map) &&
12306 src_end < vm_map_max(src_map))) {
12307 return VM_MAP_COPYIN_STRATEGY_KERNEL_BUFFER;
12308 }
12309
12310 return VM_MAP_COPYIN_STRATEGY_VIRTUAL_COPY;
12311}
12312
12313kern_return_t
12314vm_map_copyin_internal(
12315 vm_map_t src_map,
12316 vm_map_address_ut src_addr_u,
12317 vm_map_size_ut len_u,
12318 int flags,
12319 vm_map_copy_t *copy_result) /* OUT */
12320{
12321 vm_map_entry_t tmp_entry; /* Result of last map lookup --
12322 * in multi-level lookup, this
12323 * entry contains the actual
12324 * vm_object/offset.
12325 */
12326 vm_map_entry_t new_entry = VM_MAP_ENTRY_NULL; /* Map entry for copy */
12327
12328 vm_map_offset_t src_start; /* Start of current entry --
12329 * where copy is taking place now
12330 */
12331 vm_map_offset_t src_end; /* End of entire region to be
12332 * copied */
12333 vm_map_offset_t src_addr_unaligned;
12334 vm_map_offset_t src_base;
12335 vm_map_size_t len;
12336 vm_map_t base_map = src_map;
12337 boolean_t map_share = FALSE;
12338 submap_map_t *parent_maps = NULL;
12339
12340 vm_map_copy_t copy; /* Resulting copy */
12341 vm_map_address_t copy_addr;
12342 vm_map_size_t copy_size;
12343 boolean_t src_destroy;
12344 boolean_t use_maxprot;
12345 boolean_t preserve_purgeable;
12346 boolean_t entry_was_shared;
12347 vm_map_entry_t saved_src_entry;
12348 kern_return_t kr;
12349
12350 vmlp_api_start(VM_MAP_COPYIN_INTERNAL);
12351
12352 if (flags & ~VM_MAP_COPYIN_ALL_FLAGS) {
12353 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, KERN_INVALID_ARGUMENT);
12354 return KERN_INVALID_ARGUMENT;
12355 }
12356
12357 /*
12358 * Check for copies of zero bytes.
12359 */
12360 if (VM_SANITIZE_UNSAFE_IS_ZERO(len_u)) {
12361 *copy_result = VM_MAP_COPY_NULL;
12362 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, KERN_SUCCESS);
12363 return KERN_SUCCESS;
12364 }
12365
12366 /*
12367 * Sanitize any input parameters that are addr/size/prot/inherit
12368 */
12369 kr = vm_map_copyin_sanitize(
12370 src_map,
12371 src_addr_u,
12372 len_u,
12373 &src_start,
12374 &src_end,
12375 &len,
12376 &src_addr_unaligned);
12377 if (__improbable(kr != KERN_SUCCESS)) {
12378 kr = vm_sanitize_get_kr(kr);
12379 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, kr);
12380 return kr;
12381 }
12382 vmlp_range_event(src_map, src_start, len);
12383
12384 src_destroy = (flags & VM_MAP_COPYIN_SRC_DESTROY) ? TRUE : FALSE;
12385 use_maxprot = (flags & VM_MAP_COPYIN_USE_MAXPROT) ? TRUE : FALSE;
12386 preserve_purgeable =
12387 (flags & VM_MAP_COPYIN_PRESERVE_PURGEABLE) ? TRUE : FALSE;
12388
12389 vm_map_copyin_strategy strategy = _vm_map_copyin_select_strategy(
12390 src_map,
12391 len,
12392 src_start,
12393 src_end,
12394 use_maxprot,
12395 preserve_purgeable,
12396 flags);
12397 if (strategy == VM_MAP_COPYIN_STRATEGY_INVALID_ARGUMENT) {
12398 return KERN_INVALID_ADDRESS;
12399 } else if (
12400 strategy == VM_MAP_COPYIN_STRATEGY_KERNEL_BUFFER) {
12401 kr = vm_map_copyin_kernel_buffer(src_map, src_addr_unaligned, len, strategy,
12402 src_destroy, copy_result);
12403 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, kr);
12404 return kr;
12405 }
12406
12407 /* Ensure we don't forget about a newly defined type */
12408 assert(strategy == VM_MAP_COPYIN_STRATEGY_VIRTUAL_COPY);
12409
12410 /*
12411 * Allocate a header element for the list.
12412 *
12413 * Use the start and end in the header to
12414 * remember the endpoints prior to rounding.
12415 */
12416
12417 copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
12418 copy->cpy_hdr.entries_pageable = TRUE;
12419 copy->cpy_hdr.page_shift = (uint16_t)VM_MAP_PAGE_SHIFT(src_map);
12420 copy->offset = src_addr_unaligned;
12421 copy->size = len;
12422
12423 new_entry = vm_map_copy_entry_create(copy);
12424
12425#define RETURN(x) \
12426 MACRO_BEGIN \
12427 if (vm_map_is_sealed(src_map)) { \
12428 vm_map_unlock_read(src_map); \
12429 } else { \
12430 vm_map_unlock(src_map); \
12431 } \
12432 if(src_map != base_map) \
12433 vm_map_deallocate(src_map); \
12434 if (new_entry != VM_MAP_ENTRY_NULL) \
12435 vm_map_copy_entry_dispose(new_entry); \
12436 vm_map_copy_discard(copy); \
12437 { \
12438 submap_map_t *_ptr; \
12439 \
12440 for(_ptr = parent_maps; _ptr != NULL; _ptr = parent_maps) { \
12441 parent_maps=parent_maps->next; \
12442 if (_ptr->parent_map != base_map) \
12443 vm_map_deallocate(_ptr->parent_map); \
12444 kfree_type(submap_map_t, _ptr); \
12445 } \
12446 } \
12447 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, x); \
12448 MACRO_RETURN(x); \
12449 MACRO_END
12450
12451 /*
12452 * Find the beginning of the region.
12453 */
12454
12455 vm_map_lock(src_map);
12456
12457 /*
12458 * Lookup the original "src_addr_unaligned" rather than the truncated
12459 * "src_start", in case "src_start" falls in a non-map-aligned
12460 * map entry *before* the map entry that contains "src_addr_unaligned"...
12461 */
12462 if (!vm_map_lookup_entry(src_map, src_addr_unaligned, &tmp_entry)) {
12463 RETURN(KERN_INVALID_ADDRESS);
12464 }
12465 if (!tmp_entry->is_sub_map) {
12466 /*
12467 * ... but clip to the map-rounded "src_start" rather than
12468 * "src_addr_unaligned" to preserve map-alignment. We'll adjust the
12469 * first copy entry at the end, if needed.
12470 */
12471 vm_map_clip_start(src_map, tmp_entry, src_start);
12472 }
12473 if (src_start < tmp_entry->vme_start) {
12474 /*
12475 * Move "src_start" up to the start of the
12476 * first map entry to copy.
12477 */
12478 src_start = tmp_entry->vme_start;
12479 }
12480 /* set for later submap fix-up */
12481 copy_addr = src_start;
12482
12483 /*
12484 * Go through entries until we get to the end.
12485 */
12486
12487 while (TRUE) {
12488 vm_map_entry_t src_entry = tmp_entry; /* Top-level entry */
12489 vm_map_size_t src_size; /* Size of source
12490 * map entry (in both
12491 * maps)
12492 */
12493
12494 vm_object_t src_object; /* Object to copy */
12495 vm_object_offset_t src_offset;
12496
12497 vm_object_t new_copy_object;/* vm_object_copy_* result */
12498
12499 boolean_t src_needs_copy; /* Should source map
12500 * be made read-only
12501 * for copy-on-write?
12502 */
12503
12504 boolean_t new_entry_needs_copy; /* Will new entry be COW? */
12505
12506 boolean_t was_wired; /* Was source wired? */
12507 boolean_t saved_used_for_jit; /* Saved used_for_jit. */
12508 vm_map_version_t version; /* Version before locks
12509 * dropped to make copy
12510 */
12511 kern_return_t result; /* Return value from
12512 * copy_strategically.
12513 */
12514 while (tmp_entry->is_sub_map) {
12515 vm_map_size_t submap_len;
12516 submap_map_t *ptr;
12517
12518 ptr = kalloc_type(submap_map_t, Z_WAITOK);
12519 ptr->next = parent_maps;
12520 parent_maps = ptr;
12521 ptr->parent_map = src_map;
12522 ptr->base_start = src_start;
12523 ptr->base_end = src_end;
12524 submap_len = tmp_entry->vme_end - src_start;
12525 if (submap_len > (src_end - src_start)) {
12526 submap_len = src_end - src_start;
12527 }
12528 ptr->base_len = submap_len;
12529
12530 src_start -= tmp_entry->vme_start;
12531 src_start += VME_OFFSET(tmp_entry);
12532 src_end = src_start + submap_len;
12533 src_map = VME_SUBMAP(tmp_entry);
12534 if (vm_map_is_sealed(src_map)) {
12535 vm_map_lock_read(src_map);
12536 } else {
12537 vm_map_lock(src_map);
12538 }
12539 /* keep an outstanding reference for all maps in */
12540 /* the parents tree except the base map */
12541 vm_map_reference(src_map);
12542 vm_map_unlock(ptr->parent_map);
12543 if (!vm_map_lookup_entry(
12544 src_map, src_start, &tmp_entry)) {
12545 RETURN(KERN_INVALID_ADDRESS);
12546 }
12547 map_share = TRUE;
12548 if (vm_map_is_sealed(src_map)) {
12549 assert(!tmp_entry->is_sub_map);
12550 /* no clipping (to "src_start") in sealed map */
12551 } else if (!tmp_entry->is_sub_map) {
12552 vm_map_clip_start(src_map, tmp_entry, src_start);
12553 }
12554 src_entry = tmp_entry;
12555 }
12556 /* we are now in the lowest level submap... */
12557
12558 if ((VME_OBJECT(tmp_entry) != VM_OBJECT_NULL) &&
12559 (VME_OBJECT(tmp_entry)->phys_contiguous)) {
12560 /* This is not, supported for now.In future */
12561 /* we will need to detect the phys_contig */
12562 /* condition and then upgrade copy_slowly */
12563 /* to do physical copy from the device mem */
12564 /* based object. We can piggy-back off of */
12565 /* the was wired boolean to set-up the */
12566 /* proper handling */
12567 RETURN(KERN_PROTECTION_FAILURE);
12568 }
12569 /*
12570 * Create a new address map entry to hold the result.
12571 * Fill in the fields from the appropriate source entries.
12572 * We must unlock the source map to do this if we need
12573 * to allocate a map entry.
12574 */
12575 if (new_entry == VM_MAP_ENTRY_NULL) {
12576 version.main_timestamp = src_map->timestamp;
12577 if (vm_map_is_sealed(src_map)) {
12578 version.main_timestamp--; /* no increment expected */
12579 vm_map_unlock_read(src_map);
12580 } else {
12581 vm_map_unlock(src_map);
12582 }
12583
12584 new_entry = vm_map_copy_entry_create(copy);
12585
12586 if (vm_map_is_sealed(src_map)) {
12587 vm_map_lock_read(src_map);
12588 } else {
12589 vm_map_lock(src_map);
12590 }
12591 if ((version.main_timestamp + 1) != src_map->timestamp) {
12592 assert(!vm_map_is_sealed(src_map));
12593 if (!vm_map_lookup_entry(src_map, src_start,
12594 &tmp_entry)) {
12595 RETURN(KERN_INVALID_ADDRESS);
12596 }
12597 if (!tmp_entry->is_sub_map) {
12598 vm_map_clip_start(src_map, tmp_entry, src_start);
12599 }
12600 continue; /* restart w/ new tmp_entry */
12601 }
12602 }
12603
12604 /*
12605 * Verify that the region can be read.
12606 */
12607 if (((src_entry->protection & VM_PROT_READ) == VM_PROT_NONE &&
12608 !use_maxprot) ||
12609 (src_entry->max_protection & VM_PROT_READ) == 0) {
12610 RETURN(KERN_PROTECTION_FAILURE);
12611 }
12612
12613 src_object = VME_OBJECT(src_entry);
12614
12615
12616 src_offset = VME_OFFSET(src_entry);
12617 src_object = VME_OBJECT(src_entry);
12618 was_wired = (src_entry->wired_count != 0);
12619
12620 /*
12621 * Clip against the endpoints of the entire region.
12622 */
12623 if (vm_map_is_sealed(src_map)) {
12624 /* no clipping in a sealed map: adjust manually */
12625 src_size = src_entry->vme_end - src_entry->vme_start;
12626 if (src_start > src_entry->vme_start) {
12627 assert(src_size > src_start - src_entry->vme_start);
12628 src_size -= src_start - src_entry->vme_start;
12629 src_offset += src_start - src_entry->vme_start;
12630 }
12631 if (src_end < src_entry->vme_end) {
12632 assert(src_size > src_entry->vme_end - src_end);
12633 src_size -= src_entry->vme_end - src_end;
12634 }
12635 } else {
12636 vm_map_clip_end(src_map, src_entry, src_end);
12637 src_size = src_entry->vme_end - src_start;
12638 }
12639
12640 vm_map_entry_copy(src_map, new_entry, src_entry);
12641
12642 if (vm_map_is_sealed(src_map)) {
12643 /* we did not clip src_entry: "clip" new_entry */
12644 new_entry->vme_start = src_start;
12645 new_entry->vme_end = src_start + src_size;
12646 VME_OFFSET_SET(new_entry, src_offset);
12647 }
12648
12649 if (new_entry->is_sub_map) {
12650 assert(!vm_map_is_sealed(src_map));
12651 /* clr address space specifics */
12652 new_entry->use_pmap = FALSE;
12653 } else {
12654 /*
12655 * We're dealing with a copy-on-write operation,
12656 * so the resulting mapping should not inherit the
12657 * original mapping's accounting settings.
12658 * "iokit_acct" should have been cleared in
12659 * vm_map_entry_copy().
12660 * "use_pmap" should be reset to its default (TRUE)
12661 * so that the new mapping gets accounted for in
12662 * the task's memory footprint.
12663 */
12664 assert(!new_entry->iokit_acct);
12665 new_entry->use_pmap = TRUE;
12666 }
12667
12668 /*
12669 * Attempt non-blocking copy-on-write optimizations.
12670 */
12671
12672 /*
12673 * If we are destroying the source, and the object
12674 * is internal, we could move the object reference
12675 * from the source to the copy. The copy is
12676 * copy-on-write only if the source is.
12677 * We make another reference to the object, because
12678 * destroying the source entry will deallocate it.
12679 *
12680 * This memory transfer has to be atomic, (to prevent
12681 * the VM object from being shared or copied while
12682 * it's being moved here), so we could only do this
12683 * if we won't have to unlock the VM map until the
12684 * original mapping has been fully removed.
12685 */
12686
12687RestartCopy:
12688 if ((src_object == VM_OBJECT_NULL ||
12689 (!was_wired && !map_share && !tmp_entry->is_shared
12690 && !(debug4k_no_cow_copyin && VM_MAP_PAGE_SHIFT(src_map) < PAGE_SHIFT))) &&
12691 vm_object_copy_quickly(
12692 VME_OBJECT(new_entry),
12693 src_offset,
12694 src_size,
12695 &src_needs_copy,
12696 &new_entry_needs_copy)) {
12697 new_entry->needs_copy = new_entry_needs_copy;
12698
12699 /*
12700 * Handle copy-on-write obligations
12701 */
12702
12703 if (src_needs_copy && !tmp_entry->needs_copy) {
12704 vm_prot_t prot;
12705
12706 assert(!vm_map_is_sealed(src_map));
12707
12708 prot = src_entry->protection & ~VM_PROT_WRITE;
12709
12710 if (override_nx(src_map, VME_ALIAS(src_entry))
12711 && prot) {
12712 prot |= VM_PROT_EXECUTE;
12713 }
12714
12715 vm_object_pmap_protect(
12716 src_object,
12717 src_offset,
12718 src_size,
12719 (src_entry->is_shared ?
12720 PMAP_NULL
12721 : src_map->pmap),
12722 VM_MAP_PAGE_SIZE(src_map),
12723 src_entry->vme_start,
12724 prot);
12725
12726 assert(tmp_entry->wired_count == 0);
12727 tmp_entry->needs_copy = TRUE;
12728 }
12729
12730 /*
12731 * The map has never been unlocked, so it's safe
12732 * to move to the next entry rather than doing
12733 * another lookup.
12734 */
12735
12736 goto CopySuccessful;
12737 }
12738
12739 entry_was_shared = tmp_entry->is_shared;
12740
12741 /*
12742 * Take an object reference, so that we may
12743 * release the map lock(s).
12744 */
12745
12746 assert(src_object != VM_OBJECT_NULL);
12747 vm_object_reference(src_object);
12748
12749 /*
12750 * Record the timestamp for later verification.
12751 * Unlock the map.
12752 */
12753
12754 version.main_timestamp = src_map->timestamp;
12755 if (vm_map_is_sealed(src_map)) {
12756 version.main_timestamp--; /* no expecting an increment */
12757 vm_map_unlock_read(src_map);
12758 } else {
12759 vm_map_unlock(src_map); /* Increments timestamp once! */
12760 }
12761 saved_src_entry = src_entry;
12762 tmp_entry = VM_MAP_ENTRY_NULL;
12763 src_entry = VM_MAP_ENTRY_NULL;
12764
12765 /*
12766 * Perform the copy
12767 */
12768
12769 if (was_wired ||
12770 (src_object->copy_strategy == MEMORY_OBJECT_COPY_DELAY_FORK &&
12771 !(flags & VM_MAP_COPYIN_FORK)) ||
12772 (debug4k_no_cow_copyin &&
12773 VM_MAP_PAGE_SHIFT(src_map) < PAGE_SHIFT)) {
12774CopySlowly:
12775 vm_object_lock(src_object);
12776 result = vm_object_copy_slowly(
12777 src_object,
12778 src_offset,
12779 src_size,
12780 THREAD_UNINT,
12781 &new_copy_object);
12782 /* VME_OBJECT_SET will reset used_for_jit|tpro, so preserve it. */
12783 saved_used_for_jit = new_entry->used_for_jit;
12784 VME_OBJECT_SET(new_entry, new_copy_object, false, 0);
12785 new_entry->used_for_jit = saved_used_for_jit;
12786 VME_OFFSET_SET(new_entry,
12787 src_offset - vm_object_trunc_page(src_offset));
12788 new_entry->needs_copy = FALSE;
12789 } else if (src_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC &&
12790 (entry_was_shared || map_share)) {
12791 vm_object_t new_object;
12792
12793 assert(!vm_map_is_sealed(src_map));
12794 vm_object_lock_shared(src_object);
12795 new_object = vm_object_copy_delayed(
12796 src_object,
12797 src_offset,
12798 src_size,
12799 TRUE);
12800 if (new_object == VM_OBJECT_NULL) {
12801 goto CopySlowly;
12802 }
12803
12804 VME_OBJECT_SET(new_entry, new_object, false, 0);
12805 assert(new_entry->wired_count == 0);
12806 new_entry->needs_copy = TRUE;
12807 assert(!new_entry->iokit_acct);
12808 assert(new_object->purgable == VM_PURGABLE_DENY);
12809 assertf(new_entry->use_pmap, "src_map %p new_entry %p\n", src_map, new_entry);
12810 result = KERN_SUCCESS;
12811 } else {
12812 vm_object_offset_t new_offset;
12813 new_offset = VME_OFFSET(new_entry);
12814 result = vm_object_copy_strategically(src_object,
12815 src_offset,
12816 src_size,
12817 (flags & VM_MAP_COPYIN_FORK),
12818 &new_copy_object,
12819 &new_offset,
12820 &new_entry_needs_copy);
12821 /* VME_OBJECT_SET will reset used_for_jit, so preserve it. */
12822 saved_used_for_jit = new_entry->used_for_jit;
12823 VME_OBJECT_SET(new_entry, new_copy_object, false, 0);
12824 new_entry->used_for_jit = saved_used_for_jit;
12825 if (new_offset != VME_OFFSET(new_entry)) {
12826 VME_OFFSET_SET(new_entry, new_offset);
12827 }
12828
12829 new_entry->needs_copy = new_entry_needs_copy;
12830 }
12831
12832 if (result == KERN_SUCCESS &&
12833 ((preserve_purgeable &&
12834 src_object->purgable != VM_PURGABLE_DENY) ||
12835 new_entry->used_for_jit)) {
12836 /*
12837 * Purgeable objects should be COPY_NONE, true share;
12838 * this should be propogated to the copy.
12839 *
12840 * Also force mappings the pmap specially protects to
12841 * be COPY_NONE; trying to COW these mappings would
12842 * change the effective protections, which could have
12843 * side effects if the pmap layer relies on the
12844 * specified protections.
12845 */
12846
12847 vm_object_t new_object;
12848
12849 new_object = VME_OBJECT(new_entry);
12850 assert(new_object != src_object);
12851 vm_object_lock(new_object);
12852 assert(os_ref_get_count_raw(&new_object->ref_count) == 1);
12853 assert(new_object->shadow == VM_OBJECT_NULL);
12854 assert(new_object->vo_copy == VM_OBJECT_NULL);
12855 assert(new_object->vo_owner == NULL);
12856
12857 new_object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
12858
12859 if (preserve_purgeable &&
12860 src_object->purgable != VM_PURGABLE_DENY) {
12861 VM_OBJECT_SET_TRUE_SHARE(new_object, TRUE);
12862
12863 /* start as non-volatile with no owner... */
12864 VM_OBJECT_SET_PURGABLE(new_object, VM_PURGABLE_NONVOLATILE);
12865 vm_purgeable_nonvolatile_enqueue(new_object, NULL);
12866 /* ... and move to src_object's purgeable state */
12867 if (src_object->purgable != VM_PURGABLE_NONVOLATILE) {
12868 int state;
12869 state = src_object->purgable;
12870 vm_object_purgable_control(
12871 new_object,
12872 VM_PURGABLE_SET_STATE_FROM_KERNEL,
12873 &state);
12874 }
12875 /* no pmap accounting for purgeable objects */
12876 new_entry->use_pmap = FALSE;
12877 }
12878
12879 vm_object_unlock(new_object);
12880 new_object = VM_OBJECT_NULL;
12881 }
12882
12883 /*
12884 * Throw away the extra reference
12885 */
12886
12887 vm_object_deallocate(src_object);
12888
12889 if (result != KERN_SUCCESS &&
12890 result != KERN_MEMORY_RESTART_COPY) {
12891 if (vm_map_is_sealed(src_map)) {
12892 vm_map_lock_read(src_map);
12893 } else {
12894 vm_map_lock(src_map);
12895 }
12896 RETURN(result);
12897 }
12898
12899 /*
12900 * Verify that the map has not substantially
12901 * changed while the copy was being made.
12902 */
12903
12904 if (vm_map_is_sealed(src_map)) {
12905 vm_map_lock_read(src_map);
12906 } else {
12907 vm_map_lock(src_map);
12908 }
12909
12910 if ((version.main_timestamp + 1) == src_map->timestamp) {
12911 /* src_map hasn't changed: src_entry is still valid */
12912 src_entry = saved_src_entry;
12913 goto VerificationSuccessful;
12914 }
12915
12916 assert(!vm_map_is_sealed(src_map));
12917
12918 /*
12919 * Simple version comparison failed.
12920 *
12921 * Retry the lookup and verify that the
12922 * same object/offset are still present.
12923 *
12924 * [Note: a memory manager that colludes with
12925 * the calling task can detect that we have
12926 * cheated. While the map was unlocked, the
12927 * mapping could have been changed and restored.]
12928 */
12929
12930 if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry)) {
12931 if (result != KERN_MEMORY_RESTART_COPY) {
12932 vm_object_deallocate(VME_OBJECT(new_entry));
12933 VME_OBJECT_SET(new_entry, VM_OBJECT_NULL, false, 0);
12934 /* reset accounting state */
12935 new_entry->iokit_acct = FALSE;
12936 new_entry->use_pmap = TRUE;
12937 }
12938 RETURN(KERN_INVALID_ADDRESS);
12939 }
12940
12941 src_entry = tmp_entry;
12942 vm_map_clip_start(src_map, src_entry, src_start);
12943
12944 if ((((src_entry->protection & VM_PROT_READ) == VM_PROT_NONE) &&
12945 !use_maxprot) ||
12946 ((src_entry->max_protection & VM_PROT_READ) == 0)) {
12947 goto VerificationFailed;
12948 }
12949
12950 if (src_entry->vme_end < new_entry->vme_end) {
12951 /*
12952 * This entry might have been shortened
12953 * (vm_map_clip_end) or been replaced with
12954 * an entry that ends closer to "src_start"
12955 * than before.
12956 * Adjust "new_entry" accordingly; copying
12957 * less memory would be correct but we also
12958 * redo the copy (see below) if the new entry
12959 * no longer points at the same object/offset.
12960 */
12961 assert(VM_MAP_PAGE_ALIGNED(src_entry->vme_end,
12962 VM_MAP_COPY_PAGE_MASK(copy)));
12963 new_entry->vme_end = src_entry->vme_end;
12964 src_size = new_entry->vme_end - src_start;
12965 } else if (src_entry->vme_end > new_entry->vme_end) {
12966 /*
12967 * This entry might have been extended
12968 * (vm_map_entry_simplify() or coalesce)
12969 * or been replaced with an entry that ends farther
12970 * from "src_start" than before.
12971 *
12972 * We've called vm_object_copy_*() only on
12973 * the previous <start:end> range, so we can't
12974 * just extend new_entry. We have to re-do
12975 * the copy based on the new entry as if it was
12976 * pointing at a different object/offset (see
12977 * "Verification failed" below).
12978 */
12979 }
12980
12981 if ((VME_OBJECT(src_entry) != src_object) ||
12982 (VME_OFFSET(src_entry) != src_offset) ||
12983 (src_entry->vme_end > new_entry->vme_end)) {
12984 /*
12985 * Verification failed.
12986 *
12987 * Start over with this top-level entry.
12988 */
12989
12990VerificationFailed: ;
12991
12992 vm_object_deallocate(VME_OBJECT(new_entry));
12993 tmp_entry = src_entry;
12994 continue;
12995 }
12996
12997 /*
12998 * Verification succeeded.
12999 */
13000
13001VerificationSuccessful:;
13002
13003 if (result == KERN_MEMORY_RESTART_COPY) {
13004 goto RestartCopy;
13005 }
13006
13007 /*
13008 * Copy succeeded.
13009 */
13010
13011CopySuccessful: ;
13012
13013 /*
13014 * Link in the new copy entry.
13015 */
13016
13017 vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy),
13018 new_entry);
13019
13020 /*
13021 * Determine whether the entire region
13022 * has been copied.
13023 */
13024 src_base = src_start;
13025 src_start = new_entry->vme_end;
13026 new_entry = VM_MAP_ENTRY_NULL;
13027 while ((src_start >= src_end) && (src_end != 0)) {
13028 submap_map_t *ptr;
13029
13030 if (src_map == base_map) {
13031 /* back to the top */
13032 break;
13033 }
13034
13035 ptr = parent_maps;
13036 assert(ptr != NULL);
13037 parent_maps = parent_maps->next;
13038
13039 if (vm_map_is_sealed(src_map)) {
13040 /* no clipping -> no damage */
13041 vm_map_unlock_read(src_map);
13042 } else {
13043 /* fix up the damage we did in that submap */
13044 vm_map_simplify_range(src_map,
13045 src_base,
13046 src_end);
13047 vm_map_unlock(src_map);
13048 }
13049
13050 vm_map_deallocate(src_map);
13051 vm_map_lock(ptr->parent_map);
13052 src_map = ptr->parent_map;
13053 src_base = ptr->base_start;
13054 src_start = ptr->base_start + ptr->base_len;
13055 src_end = ptr->base_end;
13056 if (!vm_map_lookup_entry(src_map,
13057 src_start,
13058 &tmp_entry) &&
13059 (src_end > src_start)) {
13060 RETURN(KERN_INVALID_ADDRESS);
13061 }
13062 kfree_type(submap_map_t, ptr);
13063 if (parent_maps == NULL) {
13064 map_share = FALSE;
13065 }
13066 src_entry = VME_PREV(tmp_entry);
13067 }
13068
13069 if ((VM_MAP_PAGE_SHIFT(src_map) != PAGE_SHIFT) &&
13070 (src_start >= src_addr_unaligned + len) &&
13071 (src_addr_unaligned + len != 0)) {
13072 /*
13073 * Stop copying now, even though we haven't reached
13074 * "src_end". We'll adjust the end of the last copy
13075 * entry at the end, if needed.
13076 *
13077 * If src_map's aligment is different from the
13078 * system's page-alignment, there could be
13079 * extra non-map-aligned map entries between
13080 * the original (non-rounded) "src_addr_unaligned + len"
13081 * and the rounded "src_end".
13082 * We do not want to copy those map entries since
13083 * they're not part of the copied range.
13084 */
13085 break;
13086 }
13087
13088 if ((src_start >= src_end) && (src_end != 0)) {
13089 break;
13090 }
13091
13092 /*
13093 * Verify that there are no gaps in the region
13094 */
13095
13096 tmp_entry = src_entry->vme_next;
13097 if ((tmp_entry->vme_start != src_start) ||
13098 (tmp_entry == vm_map_to_entry(src_map))) {
13099 RETURN(KERN_INVALID_ADDRESS);
13100 }
13101 }
13102
13103 /*
13104 * If the source should be destroyed, do it now, since the
13105 * copy was successful.
13106 */
13107 if (src_destroy) {
13108 vmr_flags_t remove_flags = VM_MAP_REMOVE_NO_FLAGS;
13109
13110 assert(!vm_map_is_sealed(src_map));
13111 if (src_map == kernel_map) {
13112 remove_flags |= VM_MAP_REMOVE_KUNWIRE;
13113 }
13114 (void)vm_map_remove_and_unlock(src_map,
13115 vm_map_trunc_page(src_addr_unaligned, VM_MAP_PAGE_MASK(src_map)),
13116 src_end,
13117 remove_flags,
13118 KMEM_GUARD_NONE);
13119 } else if (vm_map_is_sealed(src_map)) {
13120 /* no clipping -> no damage */
13121 vm_map_unlock_read(src_map);
13122 } else {
13123 /* fix up the damage we did in the base map */
13124 vm_map_simplify_range(
13125 src_map,
13126 vm_map_trunc_page(src_addr_unaligned,
13127 VM_MAP_PAGE_MASK(src_map)),
13128 vm_map_round_page(src_end,
13129 VM_MAP_PAGE_MASK(src_map)));
13130 vm_map_unlock(src_map);
13131 }
13132
13133 tmp_entry = VM_MAP_ENTRY_NULL;
13134
13135 if (VM_MAP_PAGE_SHIFT(src_map) > PAGE_SHIFT &&
13136 VM_MAP_PAGE_SHIFT(src_map) != VM_MAP_COPY_PAGE_SHIFT(copy)) {
13137 vm_map_offset_t original_start, original_offset, original_end;
13138
13139 assert(VM_MAP_COPY_PAGE_MASK(copy) == PAGE_MASK);
13140
13141 /* adjust alignment of first copy_entry's "vme_start" */
13142 tmp_entry = vm_map_copy_first_entry(copy);
13143 if (tmp_entry != vm_map_copy_to_entry(copy)) {
13144 vm_map_offset_t adjustment;
13145
13146 original_start = tmp_entry->vme_start;
13147 original_offset = VME_OFFSET(tmp_entry);
13148
13149 /* map-align the start of the first copy entry... */
13150 adjustment = (tmp_entry->vme_start -
13151 vm_map_trunc_page(
13152 tmp_entry->vme_start,
13153 VM_MAP_PAGE_MASK(src_map)));
13154 tmp_entry->vme_start -= adjustment;
13155 VME_OFFSET_SET(tmp_entry,
13156 VME_OFFSET(tmp_entry) - adjustment);
13157 copy_addr -= adjustment;
13158 assert(tmp_entry->vme_start < tmp_entry->vme_end);
13159 /* ... adjust for mis-aligned start of copy range */
13160 adjustment =
13161 (vm_map_trunc_page(copy->offset,
13162 PAGE_MASK) -
13163 vm_map_trunc_page(copy->offset,
13164 VM_MAP_PAGE_MASK(src_map)));
13165 if (adjustment) {
13166 assert(page_aligned(adjustment));
13167 assert(adjustment < VM_MAP_PAGE_SIZE(src_map));
13168 tmp_entry->vme_start += adjustment;
13169 VME_OFFSET_SET(tmp_entry,
13170 (VME_OFFSET(tmp_entry) +
13171 adjustment));
13172 copy_addr += adjustment;
13173 assert(tmp_entry->vme_start < tmp_entry->vme_end);
13174 }
13175
13176 /*
13177 * Assert that the adjustments haven't exposed
13178 * more than was originally copied...
13179 */
13180 assert(tmp_entry->vme_start >= original_start);
13181 assert(VME_OFFSET(tmp_entry) >= original_offset);
13182 /*
13183 * ... and that it did not adjust outside of a
13184 * a single 16K page.
13185 */
13186 assert(vm_map_trunc_page(tmp_entry->vme_start,
13187 VM_MAP_PAGE_MASK(src_map)) ==
13188 vm_map_trunc_page(original_start,
13189 VM_MAP_PAGE_MASK(src_map)));
13190 }
13191
13192 /* adjust alignment of last copy_entry's "vme_end" */
13193 tmp_entry = vm_map_copy_last_entry(copy);
13194 if (tmp_entry != vm_map_copy_to_entry(copy)) {
13195 vm_map_offset_t adjustment;
13196
13197 original_end = tmp_entry->vme_end;
13198
13199 /* map-align the end of the last copy entry... */
13200 tmp_entry->vme_end =
13201 vm_map_round_page(tmp_entry->vme_end,
13202 VM_MAP_PAGE_MASK(src_map));
13203 /* ... adjust for mis-aligned end of copy range */
13204 adjustment =
13205 (vm_map_round_page((copy->offset +
13206 copy->size),
13207 VM_MAP_PAGE_MASK(src_map)) -
13208 vm_map_round_page((copy->offset +
13209 copy->size),
13210 PAGE_MASK));
13211 if (adjustment) {
13212 assert(page_aligned(adjustment));
13213 assert(adjustment < VM_MAP_PAGE_SIZE(src_map));
13214 tmp_entry->vme_end -= adjustment;
13215 assert(tmp_entry->vme_start < tmp_entry->vme_end);
13216 }
13217
13218 /*
13219 * Assert that the adjustments haven't exposed
13220 * more than was originally copied...
13221 */
13222 assert(tmp_entry->vme_end <= original_end);
13223 /*
13224 * ... and that it did not adjust outside of a
13225 * a single 16K page.
13226 */
13227 assert(vm_map_round_page(tmp_entry->vme_end,
13228 VM_MAP_PAGE_MASK(src_map)) ==
13229 vm_map_round_page(original_end,
13230 VM_MAP_PAGE_MASK(src_map)));
13231 }
13232 }
13233
13234 /* Fix-up start and end points in copy. This is necessary */
13235 /* when the various entries in the copy object were picked */
13236 /* up from different sub-maps */
13237
13238 tmp_entry = vm_map_copy_first_entry(copy);
13239 copy_size = 0; /* compute actual size */
13240 while (tmp_entry != vm_map_copy_to_entry(copy)) {
13241 assert(VM_MAP_PAGE_ALIGNED(
13242 copy_addr + (tmp_entry->vme_end -
13243 tmp_entry->vme_start),
13244 MIN(VM_MAP_COPY_PAGE_MASK(copy), PAGE_MASK)));
13245 assert(VM_MAP_PAGE_ALIGNED(
13246 copy_addr,
13247 MIN(VM_MAP_COPY_PAGE_MASK(copy), PAGE_MASK)));
13248
13249 tmp_entry->vme_end = copy_addr +
13250 (tmp_entry->vme_end - tmp_entry->vme_start);
13251 tmp_entry->vme_start = copy_addr;
13252 assert(tmp_entry->vme_start < tmp_entry->vme_end);
13253 copy_addr += tmp_entry->vme_end - tmp_entry->vme_start;
13254 copy_size += tmp_entry->vme_end - tmp_entry->vme_start;
13255 tmp_entry = (struct vm_map_entry *)tmp_entry->vme_next;
13256 }
13257
13258 if (VM_MAP_PAGE_SHIFT(src_map) != PAGE_SHIFT &&
13259 copy_size < copy->size) {
13260 /*
13261 * The actual size of the VM map copy is smaller than what
13262 * was requested by the caller. This must be because some
13263 * PAGE_SIZE-sized pages are missing at the end of the last
13264 * VM_MAP_PAGE_SIZE(src_map)-sized chunk of the range.
13265 * The caller might not have been aware of those missing
13266 * pages and might not want to be aware of it, which is
13267 * fine as long as they don't try to access (and crash on)
13268 * those missing pages.
13269 * Let's adjust the size of the "copy", to avoid failing
13270 * in vm_map_copyout() or vm_map_copy_overwrite().
13271 */
13272 assert(vm_map_round_page(copy_size,
13273 VM_MAP_PAGE_MASK(src_map)) ==
13274 vm_map_round_page(copy->size,
13275 VM_MAP_PAGE_MASK(src_map)));
13276 copy->size = copy_size;
13277 }
13278
13279 *copy_result = copy;
13280 vmlp_api_end(VM_MAP_COPYIN_INTERNAL, KERN_SUCCESS);
13281 return KERN_SUCCESS;
13282
13283#undef RETURN
13284}
13285
13286kern_return_t
13287vm_map_copy_extract(
13288 vm_map_t src_map,
13289 vm_map_address_t src_addr,
13290 vm_map_size_t len,
13291 boolean_t do_copy,
13292 vm_map_copy_t *copy_result, /* OUT */
13293 vm_prot_t *cur_prot, /* IN/OUT */
13294 vm_prot_t *max_prot, /* IN/OUT */
13295 vm_inherit_t inheritance,
13296 vm_map_kernel_flags_t vmk_flags)
13297{
13298 vm_map_copy_t copy;
13299 kern_return_t kr;
13300 vm_prot_t required_cur_prot, required_max_prot;
13301
13302 /*
13303 * Check for copies of zero bytes.
13304 */
13305
13306 if (len == 0) {
13307 *copy_result = VM_MAP_COPY_NULL;
13308 return KERN_SUCCESS;
13309 }
13310
13311 /*
13312 * Check that the end address doesn't overflow
13313 */
13314 if (src_addr + len < src_addr) {
13315 return KERN_INVALID_ADDRESS;
13316 }
13317 if (__improbable(vm_map_range_overflows(src_map, src_addr, len))) {
13318 return KERN_INVALID_ADDRESS;
13319 }
13320
13321 if (VM_MAP_PAGE_SIZE(src_map) < PAGE_SIZE) {
13322 DEBUG4K_SHARE("src_map %p src_addr 0x%llx src_end 0x%llx\n", src_map, (uint64_t)src_addr, (uint64_t)(src_addr + len));
13323 }
13324
13325 required_cur_prot = *cur_prot;
13326 required_max_prot = *max_prot;
13327
13328 /*
13329 * Allocate a header element for the list.
13330 *
13331 * Use the start and end in the header to
13332 * remember the endpoints prior to rounding.
13333 */
13334
13335 copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
13336 copy->cpy_hdr.entries_pageable = vmk_flags.vmkf_copy_pageable;
13337 copy->offset = 0;
13338 copy->size = len;
13339
13340 kr = vm_map_remap_extract(src_map,
13341 src_addr,
13342 len,
13343 do_copy, /* copy */
13344 copy,
13345 cur_prot, /* IN/OUT */
13346 max_prot, /* IN/OUT */
13347 inheritance,
13348 vmk_flags);
13349 if (kr != KERN_SUCCESS) {
13350 vm_map_copy_discard(copy);
13351 if ((kr == KERN_INVALID_ADDRESS ||
13352 kr == KERN_INVALID_ARGUMENT) &&
13353 src_map->terminated) {
13354 /* tell the caller that this address space is gone */
13355 kr = KERN_TERMINATED;
13356 }
13357 return kr;
13358 }
13359 if (required_cur_prot != VM_PROT_NONE) {
13360 assert((*cur_prot & required_cur_prot) == required_cur_prot);
13361 assert((*max_prot & required_max_prot) == required_max_prot);
13362 }
13363
13364 *copy_result = copy;
13365 return KERN_SUCCESS;
13366}
13367
13368static void
13369vm_map_fork_share(
13370 vm_map_t old_map,
13371 vm_map_entry_t old_entry,
13372 vm_map_t new_map)
13373{
13374 vm_object_t object;
13375 vm_map_entry_t new_entry;
13376
13377 /*
13378 * New sharing code. New map entry
13379 * references original object. Internal
13380 * objects use asynchronous copy algorithm for
13381 * future copies. First make sure we have
13382 * the right object. If we need a shadow,
13383 * or someone else already has one, then
13384 * make a new shadow and share it.
13385 */
13386
13387 if (!old_entry->is_sub_map) {
13388 object = VME_OBJECT(old_entry);
13389 }
13390
13391 if (old_entry->is_sub_map) {
13392 assert(old_entry->wired_count == 0);
13393#ifndef NO_NESTED_PMAP
13394 if (old_entry->use_pmap) {
13395 kern_return_t result;
13396
13397 result = pmap_nest(new_map->pmap,
13398 (VME_SUBMAP(old_entry))->pmap,
13399 (addr64_t)old_entry->vme_start,
13400 (uint64_t)(old_entry->vme_end - old_entry->vme_start));
13401 if (result) {
13402 panic("vm_map_fork_share: pmap_nest failed!");
13403 }
13404 }
13405#endif /* NO_NESTED_PMAP */
13406 } else if (object == VM_OBJECT_NULL) {
13407 object = vm_object_allocate((vm_map_size_t)(old_entry->vme_end -
13408 old_entry->vme_start), old_map->serial_id);
13409 VME_OFFSET_SET(old_entry, 0);
13410 VME_OBJECT_SET(old_entry, object, false, 0);
13411 old_entry->use_pmap = TRUE;
13412// assert(!old_entry->needs_copy);
13413 } else if (object->copy_strategy !=
13414 MEMORY_OBJECT_COPY_SYMMETRIC) {
13415 /*
13416 * We are already using an asymmetric
13417 * copy, and therefore we already have
13418 * the right object.
13419 */
13420
13421 assert(!old_entry->needs_copy);
13422 } else if (old_entry->needs_copy || /* case 1 */
13423 object->shadowed || /* case 2 */
13424 (!object->true_share && /* case 3 */
13425 !old_entry->is_shared &&
13426 (object->vo_size >
13427 (vm_map_size_t)(old_entry->vme_end -
13428 old_entry->vme_start)))) {
13429 bool is_writable;
13430
13431 /*
13432 * We need to create a shadow.
13433 * There are three cases here.
13434 * In the first case, we need to
13435 * complete a deferred symmetrical
13436 * copy that we participated in.
13437 * In the second and third cases,
13438 * we need to create the shadow so
13439 * that changes that we make to the
13440 * object do not interfere with
13441 * any symmetrical copies which
13442 * have occured (case 2) or which
13443 * might occur (case 3).
13444 *
13445 * The first case is when we had
13446 * deferred shadow object creation
13447 * via the entry->needs_copy mechanism.
13448 * This mechanism only works when
13449 * only one entry points to the source
13450 * object, and we are about to create
13451 * a second entry pointing to the
13452 * same object. The problem is that
13453 * there is no way of mapping from
13454 * an object to the entries pointing
13455 * to it. (Deferred shadow creation
13456 * works with one entry because occurs
13457 * at fault time, and we walk from the
13458 * entry to the object when handling
13459 * the fault.)
13460 *
13461 * The second case is when the object
13462 * to be shared has already been copied
13463 * with a symmetric copy, but we point
13464 * directly to the object without
13465 * needs_copy set in our entry. (This
13466 * can happen because different ranges
13467 * of an object can be pointed to by
13468 * different entries. In particular,
13469 * a single entry pointing to an object
13470 * can be split by a call to vm_inherit,
13471 * which, combined with task_create, can
13472 * result in the different entries
13473 * having different needs_copy values.)
13474 * The shadowed flag in the object allows
13475 * us to detect this case. The problem
13476 * with this case is that if this object
13477 * has or will have shadows, then we
13478 * must not perform an asymmetric copy
13479 * of this object, since such a copy
13480 * allows the object to be changed, which
13481 * will break the previous symmetrical
13482 * copies (which rely upon the object
13483 * not changing). In a sense, the shadowed
13484 * flag says "don't change this object".
13485 * We fix this by creating a shadow
13486 * object for this object, and sharing
13487 * that. This works because we are free
13488 * to change the shadow object (and thus
13489 * to use an asymmetric copy strategy);
13490 * this is also semantically correct,
13491 * since this object is temporary, and
13492 * therefore a copy of the object is
13493 * as good as the object itself. (This
13494 * is not true for permanent objects,
13495 * since the pager needs to see changes,
13496 * which won't happen if the changes
13497 * are made to a copy.)
13498 *
13499 * The third case is when the object
13500 * to be shared has parts sticking
13501 * outside of the entry we're working
13502 * with, and thus may in the future
13503 * be subject to a symmetrical copy.
13504 * (This is a preemptive version of
13505 * case 2.)
13506 */
13507 VME_OBJECT_SHADOW(old_entry,
13508 (vm_map_size_t) (old_entry->vme_end -
13509 old_entry->vme_start),
13510 vm_map_always_shadow(old_map));
13511
13512 /*
13513 * If we're making a shadow for other than
13514 * copy on write reasons, then we have
13515 * to remove write permission.
13516 */
13517
13518 is_writable = false;
13519 if (old_entry->protection & VM_PROT_WRITE) {
13520 is_writable = true;
13521#if __arm64e__
13522 } else if (old_entry->used_for_tpro) {
13523 is_writable = true;
13524#endif /* __arm64e__ */
13525 }
13526 if (!old_entry->needs_copy && is_writable) {
13527 vm_prot_t prot;
13528
13529 if (pmap_has_prot_policy(old_map->pmap, old_entry->translated_allow_execute, old_entry->protection)) {
13530 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
13531 __FUNCTION__, old_map, old_map->pmap,
13532 old_entry,
13533 (uint64_t)old_entry->vme_start,
13534 (uint64_t)old_entry->vme_end,
13535 old_entry->protection);
13536 }
13537
13538 prot = old_entry->protection & ~VM_PROT_WRITE;
13539
13540 if (pmap_has_prot_policy(old_map->pmap, old_entry->translated_allow_execute, prot)) {
13541 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
13542 __FUNCTION__, old_map, old_map->pmap,
13543 old_entry,
13544 (uint64_t)old_entry->vme_start,
13545 (uint64_t)old_entry->vme_end,
13546 prot);
13547 }
13548
13549 if (override_nx(old_map, VME_ALIAS(old_entry)) && prot) {
13550 prot |= VM_PROT_EXECUTE;
13551 }
13552
13553
13554 if (old_map->mapped_in_other_pmaps) {
13555 vm_object_pmap_protect(
13556 VME_OBJECT(old_entry),
13557 VME_OFFSET(old_entry),
13558 (old_entry->vme_end -
13559 old_entry->vme_start),
13560 PMAP_NULL,
13561 PAGE_SIZE,
13562 old_entry->vme_start,
13563 prot);
13564 } else {
13565 pmap_protect(old_map->pmap,
13566 old_entry->vme_start,
13567 old_entry->vme_end,
13568 prot);
13569 }
13570 }
13571
13572 old_entry->needs_copy = FALSE;
13573 object = VME_OBJECT(old_entry);
13574 }
13575
13576
13577 /*
13578 * If object was using a symmetric copy strategy,
13579 * change its copy strategy to the default
13580 * asymmetric copy strategy, which is copy_delay
13581 * in the non-norma case and copy_call in the
13582 * norma case. Bump the reference count for the
13583 * new entry.
13584 */
13585
13586 if (old_entry->is_sub_map) {
13587 vm_map_reference(VME_SUBMAP(old_entry));
13588 } else {
13589 vm_object_lock(object);
13590 vm_object_reference_locked(object);
13591 if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
13592 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
13593 }
13594 vm_object_unlock(object);
13595 }
13596
13597 /*
13598 * Clone the entry, using object ref from above.
13599 * Mark both entries as shared.
13600 */
13601
13602 new_entry = vm_map_entry_create(new_map); /* Never the kernel map or descendants */
13603 vm_map_entry_copy(old_map, new_entry, old_entry);
13604 old_entry->is_shared = TRUE;
13605 new_entry->is_shared = TRUE;
13606
13607 /*
13608 * We're dealing with a shared mapping, so the resulting mapping
13609 * should inherit some of the original mapping's accounting settings.
13610 * "iokit_acct" should have been cleared in vm_map_entry_copy().
13611 * "use_pmap" should stay the same as before (if it hasn't been reset
13612 * to TRUE when we cleared "iokit_acct").
13613 */
13614 assert(!new_entry->iokit_acct);
13615
13616 /*
13617 * If old entry's inheritence is VM_INHERIT_NONE,
13618 * the new entry is for corpse fork, remove the
13619 * write permission from the new entry.
13620 */
13621 if (old_entry->inheritance == VM_INHERIT_NONE) {
13622 new_entry->protection &= ~VM_PROT_WRITE;
13623 new_entry->max_protection &= ~VM_PROT_WRITE;
13624 }
13625
13626 /*
13627 * Insert the entry into the new map -- we
13628 * know we're inserting at the end of the new
13629 * map.
13630 */
13631
13632 vm_map_store_entry_link(new_map, vm_map_last_entry(new_map), new_entry,
13633 VM_MAP_KERNEL_FLAGS_NONE);
13634
13635 /*
13636 * Update the physical map
13637 */
13638
13639 if (old_entry->is_sub_map) {
13640 /* Bill Angell pmap support goes here */
13641 } else {
13642 pmap_copy(new_map->pmap, old_map->pmap, new_entry->vme_start,
13643 old_entry->vme_end - old_entry->vme_start,
13644 old_entry->vme_start);
13645 }
13646}
13647
13648static boolean_t
13649vm_map_fork_copy(
13650 vm_map_t old_map,
13651 vm_map_entry_t *old_entry_p,
13652 vm_map_t new_map,
13653 int vm_map_copyin_flags)
13654{
13655 vm_map_entry_t old_entry = *old_entry_p;
13656 vm_map_size_t entry_size = old_entry->vme_end - old_entry->vme_start;
13657 vm_map_offset_t start = old_entry->vme_start;
13658 vm_map_copy_t copy;
13659 vm_map_entry_t last = vm_map_last_entry(new_map);
13660
13661 vmlp_api_start(VM_MAP_FORK_COPY);
13662 vmlp_range_event_entry(old_map, old_entry); /* new_map is covered by call to vm_map_copy_insert */
13663
13664 vm_map_unlock(old_map);
13665 /*
13666 * Use maxprot version of copyin because we
13667 * care about whether this memory can ever
13668 * be accessed, not just whether it's accessible
13669 * right now.
13670 */
13671 vm_map_copyin_flags |= VM_MAP_COPYIN_USE_MAXPROT;
13672 if (vm_map_copyin_internal(old_map, start, entry_size,
13673 vm_map_copyin_flags, ©)
13674 != KERN_SUCCESS) {
13675 /*
13676 * The map might have changed while it
13677 * was unlocked, check it again. Skip
13678 * any blank space or permanently
13679 * unreadable region.
13680 */
13681 vm_map_lock(old_map);
13682 if (!vm_map_lookup_entry(old_map, start, &last) ||
13683 (last->max_protection & VM_PROT_READ) == VM_PROT_NONE) {
13684 last = last->vme_next;
13685 }
13686 *old_entry_p = last;
13687
13688 /*
13689 * XXX For some error returns, want to
13690 * XXX skip to the next element. Note
13691 * that INVALID_ADDRESS and
13692 * PROTECTION_FAILURE are handled above.
13693 */
13694
13695 vmlp_api_end(VM_MAP_FORK_COPY, FALSE);
13696 return FALSE;
13697 }
13698
13699 /*
13700 * Assert that the vm_map_copy is coming from the right
13701 * zone and hasn't been forged
13702 */
13703 vm_map_copy_require(copy);
13704
13705 /*
13706 * Insert the copy into the new map
13707 */
13708 vm_map_copy_insert(new_map, last, copy);
13709
13710 /*
13711 * Pick up the traversal at the end of
13712 * the copied region.
13713 */
13714
13715 vm_map_lock(old_map);
13716 start += entry_size;
13717 if (!vm_map_lookup_entry(old_map, start, &last)) {
13718 last = last->vme_next;
13719 } else {
13720 if (last->vme_start == start) {
13721 /*
13722 * No need to clip here and we don't
13723 * want to cause any unnecessary
13724 * unnesting...
13725 */
13726 } else {
13727 vm_map_clip_start(old_map, last, start);
13728 }
13729 }
13730 *old_entry_p = last;
13731
13732 vmlp_api_end(VM_MAP_FORK_COPY, TRUE);
13733 return TRUE;
13734}
13735
13736void
13737vm_map_inherit_limits(vm_map_t new_map, const struct _vm_map *old_map)
13738{
13739 new_map->size_limit = old_map->size_limit;
13740 new_map->data_limit = old_map->data_limit;
13741 new_map->user_wire_limit = old_map->user_wire_limit;
13742 new_map->reserved_regions = old_map->reserved_regions;
13743}
13744
13745/*
13746 * vm_map_fork:
13747 *
13748 * Create and return a new map based on the old
13749 * map, according to the inheritance values on the
13750 * regions in that map and the options.
13751 *
13752 * The source map must not be locked.
13753 */
13754vm_map_t
13755vm_map_fork(
13756 ledger_t ledger,
13757 vm_map_t old_map,
13758 int options)
13759{
13760 pmap_t new_pmap;
13761 vm_map_t new_map;
13762 vm_map_entry_t old_entry;
13763 vm_map_size_t new_size = 0, entry_size;
13764 vm_map_entry_t new_entry;
13765 boolean_t src_needs_copy;
13766 boolean_t new_entry_needs_copy;
13767 boolean_t pmap_is64bit;
13768 int vm_map_copyin_flags;
13769 vm_inherit_t old_entry_inheritance;
13770 int map_create_options;
13771 kern_return_t footprint_collect_kr;
13772
13773 vmlp_api_start(VM_MAP_FORK);
13774
13775 if (options & ~(VM_MAP_FORK_SHARE_IF_INHERIT_NONE |
13776 VM_MAP_FORK_PRESERVE_PURGEABLE |
13777 VM_MAP_FORK_CORPSE_FOOTPRINT |
13778 VM_MAP_FORK_SHARE_IF_OWNED)) {
13779 /* unsupported option */
13780 vmlp_api_end(VM_MAP_FORK, -1);
13781 return VM_MAP_NULL;
13782 }
13783
13784 pmap_is64bit =
13785#if defined(__i386__) || defined(__x86_64__)
13786 old_map->pmap->pm_task_map != TASK_MAP_32BIT;
13787#elif defined(__arm64__)
13788 old_map->pmap->is_64bit;
13789#else
13790#error Unknown architecture.
13791#endif
13792
13793 unsigned int pmap_flags = 0;
13794 pmap_flags |= pmap_is64bit ? PMAP_CREATE_64BIT : 0;
13795#if defined(HAS_APPLE_PAC)
13796 pmap_flags |= old_map->pmap->disable_jop ? PMAP_CREATE_DISABLE_JOP : 0;
13797#endif
13798#if CONFIG_ROSETTA
13799 pmap_flags |= old_map->pmap->is_rosetta ? PMAP_CREATE_ROSETTA : 0;
13800#endif
13801#if PMAP_CREATE_FORCE_4K_PAGES
13802 if (VM_MAP_PAGE_SIZE(old_map) == FOURK_PAGE_SIZE &&
13803 PAGE_SIZE != FOURK_PAGE_SIZE) {
13804 pmap_flags |= PMAP_CREATE_FORCE_4K_PAGES;
13805 }
13806#endif /* PMAP_CREATE_FORCE_4K_PAGES */
13807 new_pmap = pmap_create_options(ledger, (vm_map_size_t) 0, pmap_flags);
13808 if (new_pmap == NULL) {
13809 vmlp_api_end(VM_MAP_FORK, -1);
13810 return VM_MAP_NULL;
13811 }
13812
13813 vm_map_reference(old_map);
13814 vm_map_lock(old_map);
13815
13816 /* Note that we're creating a map out of fork() */
13817 map_create_options = VM_MAP_CREATE_VIA_FORK;
13818 if (old_map->hdr.entries_pageable) {
13819 map_create_options |= VM_MAP_CREATE_PAGEABLE;
13820 }
13821 if (options & VM_MAP_FORK_CORPSE_FOOTPRINT) {
13822 map_create_options |= VM_MAP_CREATE_CORPSE_FOOTPRINT;
13823 footprint_collect_kr = KERN_SUCCESS;
13824 }
13825 new_map = vm_map_create_options(new_pmap,
13826 old_map->min_offset,
13827 old_map->max_offset,
13828 map_create_options);
13829
13830 /* Inherit our parent's ID. */
13831 vm_map_assign_serial(new_map, old_map->serial_id);
13832
13833 /* inherit cs_enforcement */
13834 vm_map_cs_enforcement_set(new_map, old_map->cs_enforcement);
13835
13836 vm_map_lock(new_map);
13837 vm_commit_pagezero_status(new_map);
13838 /* inherit the parent map's page size */
13839 vm_map_set_page_shift(new_map, VM_MAP_PAGE_SHIFT(old_map));
13840
13841 /* inherit the parent rlimits */
13842 vm_map_inherit_limits(new_map, old_map);
13843
13844#if CONFIG_MAP_RANGES
13845 /* inherit the parent map's VM ranges */
13846 vm_map_range_fork(new_map, old_map);
13847#endif
13848
13849#if CODE_SIGNING_MONITOR
13850 /* Prepare the monitor for the fork */
13851 csm_fork_prepare(old_map->pmap, new_pmap);
13852#endif
13853
13854 /*
13855 * Pre-nest the shared region's pmap.
13856 */
13857 pmap_fork_nest(old_map->pmap, new_pmap);
13858
13859 for (old_entry = vm_map_first_entry(old_map); old_entry != vm_map_to_entry(old_map);) {
13860 vmlp_range_event_entry(old_map, old_entry);
13861 /*
13862 * Abort any corpse collection if the system is shutting down.
13863 */
13864 if ((options & VM_MAP_FORK_CORPSE_FOOTPRINT) &&
13865 get_system_inshutdown()) {
13866 vm_map_corpse_footprint_collect_done(new_map);
13867 vm_map_unlock(new_map);
13868 vm_map_unlock(old_map);
13869 vm_map_deallocate(new_map);
13870 vm_map_deallocate(old_map);
13871 printf("Aborting corpse map due to system shutdown\n");
13872 vmlp_api_end(VM_MAP_FORK, -1);
13873 return VM_MAP_NULL;
13874 }
13875
13876 entry_size = old_entry->vme_end - old_entry->vme_start;
13877
13878 old_entry_inheritance = old_entry->inheritance;
13879
13880 /*
13881 * If caller used the VM_MAP_FORK_SHARE_IF_INHERIT_NONE option
13882 * share VM_INHERIT_NONE entries that are not backed by a
13883 * device pager.
13884 */
13885 if (old_entry_inheritance == VM_INHERIT_NONE &&
13886 (options & VM_MAP_FORK_SHARE_IF_INHERIT_NONE) &&
13887 (old_entry->protection & VM_PROT_READ) &&
13888 !(!old_entry->is_sub_map &&
13889 VME_OBJECT(old_entry) != NULL &&
13890 VME_OBJECT(old_entry)->pager != NULL &&
13891 is_device_pager_ops(
13892 VME_OBJECT(old_entry)->pager->mo_pager_ops))) {
13893 old_entry_inheritance = VM_INHERIT_SHARE;
13894 }
13895 if (old_entry_inheritance == VM_INHERIT_COPY &&
13896 (options & VM_MAP_FORK_SHARE_IF_OWNED) &&
13897 !old_entry->is_sub_map &&
13898 VME_OBJECT(old_entry) != VM_OBJECT_NULL) {
13899 vm_object_t object;
13900 task_t owner;
13901 object = VME_OBJECT(old_entry);
13902 owner = VM_OBJECT_OWNER(object);
13903 if (owner != TASK_NULL &&
13904 owner->map == old_map) {
13905 /*
13906 * This mapping points at a VM object owned
13907 * by the task being forked.
13908 * Some tools reporting memory accounting
13909 * info rely on the object ID, so share this
13910 * mapping instead of copying, to make the
13911 * corpse look exactly like the original
13912 * task in that respect.
13913 */
13914 assert(object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC);
13915 old_entry_inheritance = VM_INHERIT_SHARE;
13916 }
13917 }
13918
13919 if (old_entry_inheritance != VM_INHERIT_NONE &&
13920 (options & VM_MAP_FORK_CORPSE_FOOTPRINT) &&
13921 footprint_collect_kr == KERN_SUCCESS) {
13922 /*
13923 * The corpse won't have old_map->pmap to query
13924 * footprint information, so collect that data now
13925 * and store it in new_map->vmmap_corpse_footprint
13926 * for later autopsy.
13927 */
13928 footprint_collect_kr =
13929 vm_map_corpse_footprint_collect(old_map,
13930 old_entry,
13931 new_map);
13932 }
13933
13934 switch (old_entry_inheritance) {
13935 case VM_INHERIT_NONE:
13936 break;
13937
13938 case VM_INHERIT_SHARE:
13939 vm_map_fork_share(old_map, old_entry, new_map);
13940 new_size += entry_size;
13941 break;
13942
13943 case VM_INHERIT_COPY:
13944
13945 /*
13946 * Inline the copy_quickly case;
13947 * upon failure, fall back on call
13948 * to vm_map_fork_copy.
13949 */
13950
13951 if (old_entry->is_sub_map) {
13952 break;
13953 }
13954 if ((old_entry->wired_count != 0) ||
13955 ((VME_OBJECT(old_entry) != NULL) &&
13956 (VME_OBJECT(old_entry)->true_share))) {
13957 goto slow_vm_map_fork_copy;
13958 }
13959
13960 new_entry = vm_map_entry_create(new_map); /* never the kernel map or descendants */
13961 vm_map_entry_copy(old_map, new_entry, old_entry);
13962 if (old_entry->vme_permanent) {
13963 /* inherit "permanent" on fork() */
13964 new_entry->vme_permanent = TRUE;
13965 }
13966
13967 if (new_entry->used_for_jit == TRUE && new_map->jit_entry_exists == FALSE) {
13968 new_map->jit_entry_exists = TRUE;
13969 }
13970
13971 if (new_entry->is_sub_map) {
13972 /* clear address space specifics */
13973 new_entry->use_pmap = FALSE;
13974 } else {
13975 /*
13976 * We're dealing with a copy-on-write operation,
13977 * so the resulting mapping should not inherit
13978 * the original mapping's accounting settings.
13979 * "iokit_acct" should have been cleared in
13980 * vm_map_entry_copy().
13981 * "use_pmap" should be reset to its default
13982 * (TRUE) so that the new mapping gets
13983 * accounted for in the task's memory footprint.
13984 */
13985 assert(!new_entry->iokit_acct);
13986 new_entry->use_pmap = TRUE;
13987 }
13988
13989 if (!vm_object_copy_quickly(
13990 VME_OBJECT(new_entry),
13991 VME_OFFSET(old_entry),
13992 (old_entry->vme_end -
13993 old_entry->vme_start),
13994 &src_needs_copy,
13995 &new_entry_needs_copy)) {
13996 vm_map_entry_dispose(new_entry);
13997 goto slow_vm_map_fork_copy;
13998 }
13999
14000 /*
14001 * Handle copy-on-write obligations
14002 */
14003
14004 if (src_needs_copy && !old_entry->needs_copy) {
14005 vm_prot_t prot;
14006
14007 if (pmap_has_prot_policy(old_map->pmap, old_entry->translated_allow_execute, old_entry->protection)) {
14008 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
14009 __FUNCTION__,
14010 old_map, old_map->pmap, old_entry,
14011 (uint64_t)old_entry->vme_start,
14012 (uint64_t)old_entry->vme_end,
14013 old_entry->protection);
14014 }
14015
14016 prot = old_entry->protection & ~VM_PROT_WRITE;
14017
14018 if (override_nx(old_map, VME_ALIAS(old_entry))
14019 && prot) {
14020 prot |= VM_PROT_EXECUTE;
14021 }
14022
14023 if (pmap_has_prot_policy(old_map->pmap, old_entry->translated_allow_execute, prot)) {
14024 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
14025 __FUNCTION__,
14026 old_map, old_map->pmap, old_entry,
14027 (uint64_t)old_entry->vme_start,
14028 (uint64_t)old_entry->vme_end,
14029 prot);
14030 }
14031
14032 vm_object_pmap_protect(
14033 VME_OBJECT(old_entry),
14034 VME_OFFSET(old_entry),
14035 (old_entry->vme_end -
14036 old_entry->vme_start),
14037 ((old_entry->is_shared
14038 || old_map->mapped_in_other_pmaps)
14039 ? PMAP_NULL :
14040 old_map->pmap),
14041 VM_MAP_PAGE_SIZE(old_map),
14042 old_entry->vme_start,
14043 prot);
14044
14045 assert(old_entry->wired_count == 0);
14046 old_entry->needs_copy = TRUE;
14047 }
14048 new_entry->needs_copy = new_entry_needs_copy;
14049
14050 /*
14051 * Insert the entry at the end
14052 * of the map.
14053 */
14054
14055 vm_map_store_entry_link(new_map,
14056 vm_map_last_entry(new_map),
14057 new_entry,
14058 VM_MAP_KERNEL_FLAGS_NONE);
14059 new_size += entry_size;
14060 vmlp_range_event_entry(new_map, new_entry);
14061 break;
14062
14063slow_vm_map_fork_copy:
14064 vm_map_copyin_flags = VM_MAP_COPYIN_FORK;
14065 if (options & VM_MAP_FORK_PRESERVE_PURGEABLE) {
14066 vm_map_copyin_flags |=
14067 VM_MAP_COPYIN_PRESERVE_PURGEABLE;
14068 }
14069 if (vm_map_fork_copy(old_map,
14070 &old_entry,
14071 new_map,
14072 vm_map_copyin_flags)) {
14073 new_size += entry_size;
14074 }
14075 continue;
14076 }
14077 old_entry = old_entry->vme_next;
14078 }
14079
14080#if defined(__arm64__)
14081 pmap_insert_commpage(new_map->pmap);
14082#endif /* __arm64__ */
14083
14084 new_map->size = new_size;
14085
14086 if (options & VM_MAP_FORK_CORPSE_FOOTPRINT) {
14087 vm_map_corpse_footprint_collect_done(new_map);
14088 }
14089
14090 /* Propagate JIT entitlement for the pmap layer. */
14091 if (pmap_get_jit_entitled(old_map->pmap)) {
14092 /* Tell the pmap that it supports JIT. */
14093 pmap_set_jit_entitled(new_map->pmap);
14094 }
14095
14096 /* Propagate TPRO settings for the pmap layer */
14097 if (pmap_get_tpro(old_map->pmap)) {
14098 /* Tell the pmap that it supports TPRO */
14099 pmap_set_tpro(new_map->pmap);
14100 }
14101
14102
14103 vm_map_unlock(new_map);
14104 vm_map_unlock(old_map);
14105 vm_map_deallocate(old_map);
14106
14107 vmlp_api_end(VM_MAP_FORK, 0);
14108 return new_map;
14109}
14110
14111/*
14112 * vm_map_exec:
14113 *
14114 * Setup the "new_map" with the proper execution environment according
14115 * to the type of executable (platform, 64bit, chroot environment).
14116 * Map the comm page and shared region, etc...
14117 */
14118kern_return_t
14119vm_map_exec(
14120 vm_map_t new_map,
14121 task_t task,
14122 boolean_t is64bit,
14123 void *fsroot,
14124 cpu_type_t cpu,
14125 cpu_subtype_t cpu_subtype,
14126 boolean_t reslide,
14127 boolean_t is_driverkit,
14128 uint32_t rsr_version)
14129{
14130 SHARED_REGION_TRACE_DEBUG(
14131 ("shared_region: task %p: vm_map_exec(%p,%p,%p,0x%x,0x%x): ->\n",
14132 (void *)VM_KERNEL_ADDRPERM(current_task()),
14133 (void *)VM_KERNEL_ADDRPERM(new_map),
14134 (void *)VM_KERNEL_ADDRPERM(task),
14135 (void *)VM_KERNEL_ADDRPERM(fsroot),
14136 cpu,
14137 cpu_subtype));
14138 (void) vm_commpage_enter(new_map, task, is64bit);
14139
14140 (void) vm_shared_region_enter(new_map, task, is64bit, fsroot, cpu, cpu_subtype, reslide, is_driverkit, rsr_version);
14141
14142 SHARED_REGION_TRACE_DEBUG(
14143 ("shared_region: task %p: vm_map_exec(%p,%p,%p,0x%x,0x%x): <-\n",
14144 (void *)VM_KERNEL_ADDRPERM(current_task()),
14145 (void *)VM_KERNEL_ADDRPERM(new_map),
14146 (void *)VM_KERNEL_ADDRPERM(task),
14147 (void *)VM_KERNEL_ADDRPERM(fsroot),
14148 cpu,
14149 cpu_subtype));
14150
14151 /*
14152 * Some devices have region(s) of memory that shouldn't get allocated by
14153 * user processes. The following code creates dummy vm_map_entry_t's for each
14154 * of the regions that needs to be reserved to prevent any allocations in
14155 * those regions.
14156 */
14157 kern_return_t kr = KERN_FAILURE;
14158 vm_map_kernel_flags_t vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED_PERMANENT();
14159 vmk_flags.vmkf_beyond_max = true;
14160
14161 const struct vm_reserved_region *regions = NULL;
14162 size_t num_regions = ml_get_vm_reserved_regions(is64bit, ®ions);
14163 assert((num_regions == 0) || (num_regions > 0 && regions != NULL));
14164
14165 for (size_t i = 0; i < num_regions; ++i) {
14166 vm_map_offset_t address = regions[i].vmrr_addr;
14167
14168 kr = vm_map_enter(
14169 new_map,
14170 &address,
14171 regions[i].vmrr_size,
14172 (vm_map_offset_t)0,
14173 vmk_flags,
14174 VM_OBJECT_NULL,
14175 (vm_object_offset_t)0,
14176 FALSE,
14177 VM_PROT_NONE,
14178 VM_PROT_NONE,
14179 VM_INHERIT_COPY);
14180
14181 if (kr != KERN_SUCCESS) {
14182 os_log_error(OS_LOG_DEFAULT, "Failed to reserve %s region in user map %p %d", regions[i].vmrr_name, new_map, kr);
14183 return KERN_FAILURE;
14184 }
14185 }
14186
14187 new_map->reserved_regions = (num_regions ? TRUE : FALSE);
14188
14189 return KERN_SUCCESS;
14190}
14191
14192uint64_t vm_map_lookup_and_lock_object_copy_slowly_count = 0;
14193uint64_t vm_map_lookup_and_lock_object_copy_slowly_size = 0;
14194uint64_t vm_map_lookup_and_lock_object_copy_slowly_max = 0;
14195uint64_t vm_map_lookup_and_lock_object_copy_slowly_restart = 0;
14196uint64_t vm_map_lookup_and_lock_object_copy_slowly_error = 0;
14197uint64_t vm_map_lookup_and_lock_object_copy_strategically_count = 0;
14198uint64_t vm_map_lookup_and_lock_object_copy_strategically_size = 0;
14199uint64_t vm_map_lookup_and_lock_object_copy_strategically_max = 0;
14200uint64_t vm_map_lookup_and_lock_object_copy_strategically_restart = 0;
14201uint64_t vm_map_lookup_and_lock_object_copy_strategically_error = 0;
14202uint64_t vm_map_lookup_and_lock_object_copy_shadow_count = 0;
14203uint64_t vm_map_lookup_and_lock_object_copy_shadow_size = 0;
14204uint64_t vm_map_lookup_and_lock_object_copy_shadow_max = 0;
14205/*
14206 * vm_map_lookup_and_lock_object:
14207 *
14208 * Finds the VM object, offset, and
14209 * protection for a given virtual address in the
14210 * specified map, assuming a page fault of the
14211 * type specified.
14212 *
14213 * Returns the (object, offset, protection) for
14214 * this address, whether it is wired down, and whether
14215 * this map has the only reference to the data in question.
14216 * In order to later verify this lookup, a "version"
14217 * is returned.
14218 * If contended != NULL, *contended will be set to
14219 * true iff the thread had to spin or block to acquire
14220 * an exclusive lock.
14221 *
14222 * The map MUST be locked by the caller and WILL be
14223 * locked on exit. In order to guarantee the
14224 * existence of the returned object, it is returned
14225 * locked.
14226 *
14227 * If a lookup is requested with "write protection"
14228 * specified, the map may be changed to perform virtual
14229 * copying operations, although the data referenced will
14230 * remain the same.
14231 *
14232 * If fault_info is provided, then the information is
14233 * initialized according to the properties of the map entry
14234 * NB: only properties of the entry are initialized,
14235 * namely:
14236 * - user_tag
14237 * - pmap_options
14238 * - iokit_acct
14239 * - behavior
14240 * - lo_offset
14241 * - hi_offset
14242 * - no_cache
14243 * - cs_bypass
14244 * - csm_associated
14245 * - resilient_media
14246 * - vme_xnu_user_debug
14247 * - vme_no_copy_on_read
14248 * - used_for_tpro
14249 */
14250kern_return_t
14251vm_map_lookup_and_lock_object(
14252 vm_map_t *var_map, /* IN/OUT */
14253 vm_map_offset_t vaddr,
14254 vm_prot_t fault_type,
14255 int object_lock_type,
14256 vm_map_version_t *out_version, /* OUT */
14257 vm_object_t *object, /* OUT */
14258 vm_object_offset_t *offset, /* OUT */
14259 vm_prot_t *out_prot, /* OUT */
14260 boolean_t *wired, /* OUT */
14261 vm_object_fault_info_t fault_info, /* OUT */
14262 vm_map_t *real_map, /* OUT */
14263 bool *contended) /* OUT */
14264{
14265 vm_map_entry_t entry;
14266 vm_map_t map = *var_map;
14267 vm_map_t old_map = *var_map;
14268 vm_map_t cow_sub_map_parent = VM_MAP_NULL;
14269 vm_map_offset_t cow_parent_vaddr = 0;
14270 vm_map_offset_t old_start = 0;
14271 vm_map_offset_t old_end = 0;
14272 vm_prot_t prot;
14273 boolean_t mask_protections;
14274 boolean_t force_copy;
14275 boolean_t no_force_copy_if_executable;
14276 boolean_t submap_needed_copy;
14277 vm_prot_t original_fault_type;
14278 vm_map_size_t fault_page_mask;
14279
14280 vmlp_api_start(VM_MAP_LOOKUP_AND_LOCK_OBJECT);
14281
14282 /*
14283 * VM_PROT_MASK means that the caller wants us to use "fault_type"
14284 * as a mask against the mapping's actual protections, not as an
14285 * absolute value.
14286 */
14287 mask_protections = (fault_type & VM_PROT_IS_MASK) ? TRUE : FALSE;
14288 force_copy = (fault_type & VM_PROT_COPY) ? TRUE : FALSE;
14289 no_force_copy_if_executable = (fault_type & VM_PROT_COPY_FAIL_IF_EXECUTABLE) ? TRUE : FALSE;
14290 fault_type &= VM_PROT_ALL;
14291 original_fault_type = fault_type;
14292 if (contended) {
14293 *contended = false;
14294 }
14295
14296 *real_map = map;
14297
14298 fault_page_mask = MIN(VM_MAP_PAGE_MASK(map), PAGE_MASK);
14299 vaddr = VM_MAP_TRUNC_PAGE(vaddr, fault_page_mask);
14300
14301RetryLookup:
14302 fault_type = original_fault_type;
14303
14304 /*
14305 * If the map has an interesting hint, try it before calling
14306 * full blown lookup routine.
14307 */
14308 entry = map->hint;
14309
14310 if ((entry == vm_map_to_entry(map)) ||
14311 (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
14312 vm_map_entry_t tmp_entry;
14313
14314 /*
14315 * Entry was either not a valid hint, or the vaddr
14316 * was not contained in the entry, so do a full lookup.
14317 */
14318 if (!vm_map_lookup_entry(map, vaddr, &tmp_entry)) {
14319 if ((cow_sub_map_parent) && (cow_sub_map_parent != map)) {
14320 vm_map_unlock(cow_sub_map_parent);
14321 }
14322 if ((*real_map != map)
14323 && (*real_map != cow_sub_map_parent)) {
14324 vm_map_unlock(*real_map);
14325 }
14326 vmlp_api_end(VM_MAP_LOOKUP_AND_LOCK_OBJECT, KERN_INVALID_ADDRESS);
14327 return KERN_INVALID_ADDRESS;
14328 }
14329
14330 entry = tmp_entry;
14331 }
14332 if (map == old_map) {
14333 old_start = entry->vme_start;
14334 old_end = entry->vme_end;
14335 }
14336
14337 /*
14338 * Handle submaps. Drop lock on upper map, submap is
14339 * returned locked.
14340 */
14341
14342 submap_needed_copy = FALSE;
14343 if (entry->is_sub_map) {
14344 vm_map_offset_t local_vaddr;
14345 vm_map_offset_t end_delta;
14346 vm_map_offset_t start_delta;
14347 vm_map_offset_t top_entry_saved_start;
14348 vm_object_offset_t top_entry_saved_offset;
14349 vm_map_entry_t submap_entry;
14350 vm_object_offset_t submap_entry_offset;
14351 vm_object_size_t submap_entry_size;
14352 vm_prot_t subentry_protection;
14353 vm_prot_t subentry_max_protection;
14354 boolean_t subentry_no_copy_on_read;
14355 boolean_t subentry_permanent;
14356 boolean_t subentry_csm_associated;
14357#if __arm64e__
14358 boolean_t subentry_used_for_tpro;
14359#endif /* __arm64e__ */
14360 boolean_t mapped_needs_copy = FALSE;
14361
14362 assertf(VM_MAP_PAGE_SHIFT(VME_SUBMAP(entry)) >= VM_MAP_PAGE_SHIFT(map),
14363 "map %p (%d) entry %p submap %p (%d)\n",
14364 map, VM_MAP_PAGE_SHIFT(map), entry,
14365 VME_SUBMAP(entry), VM_MAP_PAGE_SHIFT(VME_SUBMAP(entry)));
14366
14367 local_vaddr = vaddr;
14368 top_entry_saved_start = entry->vme_start;
14369 top_entry_saved_offset = VME_OFFSET(entry);
14370
14371 if ((entry->use_pmap &&
14372 !((fault_type & VM_PROT_WRITE) ||
14373 force_copy))) {
14374 /* if real_map equals map we unlock below */
14375 if ((*real_map != map) &&
14376 (*real_map != cow_sub_map_parent)) {
14377 vm_map_unlock(*real_map);
14378 }
14379 *real_map = VME_SUBMAP(entry);
14380 }
14381
14382 if (entry->needs_copy &&
14383 ((fault_type & VM_PROT_WRITE) ||
14384 force_copy)) {
14385 if (!mapped_needs_copy) {
14386 if (vm_map_lock_read_to_write(map)) {
14387 vm_map_lock_read(map);
14388 *real_map = map;
14389 goto RetryLookup;
14390 }
14391 vm_map_lock_read(VME_SUBMAP(entry));
14392 *var_map = VME_SUBMAP(entry);
14393 cow_sub_map_parent = map;
14394 /* reset base to map before cow object */
14395 /* this is the map which will accept */
14396 /* the new cow object */
14397 old_start = entry->vme_start;
14398 old_end = entry->vme_end;
14399 cow_parent_vaddr = vaddr;
14400 mapped_needs_copy = TRUE;
14401 } else {
14402 vm_map_lock_read(VME_SUBMAP(entry));
14403 *var_map = VME_SUBMAP(entry);
14404 if ((cow_sub_map_parent != map) &&
14405 (*real_map != map)) {
14406 vm_map_unlock(map);
14407 }
14408 }
14409 } else {
14410 if (entry->needs_copy) {
14411 submap_needed_copy = TRUE;
14412 }
14413 vm_map_lock_read(VME_SUBMAP(entry));
14414 *var_map = VME_SUBMAP(entry);
14415 /* leave map locked if it is a target */
14416 /* cow sub_map above otherwise, just */
14417 /* follow the maps down to the object */
14418 /* here we unlock knowing we are not */
14419 /* revisiting the map. */
14420 if ((*real_map != map) && (map != cow_sub_map_parent)) {
14421 vm_map_unlock_read(map);
14422 }
14423 }
14424
14425 entry = NULL;
14426 map = *var_map;
14427
14428 /* calculate the offset in the submap for vaddr */
14429 local_vaddr = (local_vaddr - top_entry_saved_start) + top_entry_saved_offset;
14430 assertf(VM_MAP_PAGE_ALIGNED(local_vaddr, fault_page_mask),
14431 "local_vaddr 0x%llx entry->vme_start 0x%llx fault_page_mask 0x%llx\n",
14432 (uint64_t)local_vaddr, (uint64_t)top_entry_saved_start, (uint64_t)fault_page_mask);
14433
14434RetrySubMap:
14435 if (!vm_map_lookup_entry(map, local_vaddr, &submap_entry)) {
14436 if ((cow_sub_map_parent) && (cow_sub_map_parent != map)) {
14437 vm_map_unlock(cow_sub_map_parent);
14438 }
14439 if ((*real_map != map)
14440 && (*real_map != cow_sub_map_parent)) {
14441 vm_map_unlock(*real_map);
14442 }
14443 *real_map = map;
14444 vmlp_api_end(VM_MAP_LOOKUP_AND_LOCK_OBJECT, KERN_INVALID_ADDRESS);
14445 return KERN_INVALID_ADDRESS;
14446 }
14447
14448 /* find the attenuated shadow of the underlying object */
14449 /* on our target map */
14450
14451 /* in english the submap object may extend beyond the */
14452 /* region mapped by the entry or, may only fill a portion */
14453 /* of it. For our purposes, we only care if the object */
14454 /* doesn't fill. In this case the area which will */
14455 /* ultimately be clipped in the top map will only need */
14456 /* to be as big as the portion of the underlying entry */
14457 /* which is mapped */
14458 start_delta = submap_entry->vme_start > top_entry_saved_offset ?
14459 submap_entry->vme_start - top_entry_saved_offset : 0;
14460
14461 end_delta =
14462 (top_entry_saved_offset + start_delta + (old_end - old_start)) <=
14463 submap_entry->vme_end ?
14464 0 : (top_entry_saved_offset +
14465 (old_end - old_start))
14466 - submap_entry->vme_end;
14467
14468 assertf(!submap_entry->is_sub_map, "Unexpected recursive submap entry %p", submap_entry);
14469 old_start += start_delta;
14470 old_end -= end_delta;
14471
14472 if (((fault_type & VM_PROT_WRITE) || force_copy)
14473 && cow_sub_map_parent) {
14474 vm_object_t sub_object, copy_object;
14475 vm_object_offset_t copy_offset;
14476 vm_map_offset_t local_start;
14477 vm_map_offset_t local_end;
14478 boolean_t object_copied = FALSE;
14479 vm_object_offset_t object_copied_offset = 0;
14480 boolean_t object_copied_needs_copy = FALSE;
14481 kern_return_t kr = KERN_SUCCESS;
14482
14483 if (__improbable(!vm_map_is_sealed(map))) {
14484 panic("%s: CoW fault on not-yet-sealed submap %p", __func__, map);
14485 }
14486 sub_object = VME_OBJECT(submap_entry);
14487 assert(sub_object != VM_OBJECT_NULL);
14488 local_start = local_vaddr -
14489 (cow_parent_vaddr - old_start);
14490 local_end = local_vaddr +
14491 (old_end - cow_parent_vaddr);
14492 /* This is the COW case, lets connect */
14493 /* an entry in our space to the underlying */
14494 /* object in the submap, bypassing the */
14495 /* submap. */
14496 submap_entry_offset = VME_OFFSET(submap_entry);
14497 submap_entry_size = submap_entry->vme_end - submap_entry->vme_start;
14498 /* adjust to out local range */
14499 if (submap_entry->vme_start < local_start) {
14500 vm_map_offset_t clip_start;
14501 clip_start = local_start - submap_entry->vme_start;
14502 submap_entry_offset += clip_start;
14503 submap_entry_size -= clip_start;
14504 }
14505 if (local_end < submap_entry->vme_end) {
14506 vm_map_offset_t clip_end;
14507 clip_end = submap_entry->vme_end - local_end;
14508 submap_entry_size -= clip_end;
14509 }
14510 assert(!submap_entry->wired_count);
14511 assert(sub_object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC);
14512 if ((submap_entry->protection & VM_PROT_EXECUTE) &&
14513 no_force_copy_if_executable) {
14514// printf("FBDP map %p entry %p start 0x%llx end 0x%llx wired %d strat %d\n", map, submap_entry, (uint64_t)local_start, (uint64_t)local_end, submap_entry->wired_count, sub_object->copy_strategy);
14515 if ((cow_sub_map_parent) && (cow_sub_map_parent != map)) {
14516 vm_map_unlock(cow_sub_map_parent);
14517 }
14518 if ((*real_map != map)
14519 && (*real_map != cow_sub_map_parent)) {
14520 vm_map_unlock(*real_map);
14521 }
14522 *real_map = map;
14523 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_SUBMAP_NO_COW_ON_EXECUTABLE), 0 /* arg */);
14524 // sealed map, so we already only hold the lock for read...
14525 // vm_map_lock_write_to_read(map);
14526 kr = KERN_PROTECTION_FAILURE;
14527 DTRACE_VM4(submap_no_copy_executable,
14528 vm_map_t, map,
14529 vm_object_offset_t, submap_entry_offset,
14530 vm_object_size_t, submap_entry_size,
14531 int, kr);
14532 return kr;
14533 }
14534
14535 assert(sub_object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC);
14536 copy_object = VM_OBJECT_NULL;
14537 object_copied_offset = submap_entry_offset;
14538 object_copied_needs_copy = FALSE;
14539 DTRACE_VM6(submap_copy_strategically,
14540 vm_map_t, cow_sub_map_parent,
14541 vm_map_offset_t, vaddr,
14542 vm_map_t, map,
14543 vm_object_size_t, submap_entry_size,
14544 int, submap_entry->wired_count,
14545 int, sub_object->copy_strategy);
14546 kr = vm_object_copy_strategically(
14547 sub_object,
14548 submap_entry_offset,
14549 submap_entry_size,
14550 false, /* forking */
14551 ©_object,
14552 &object_copied_offset,
14553 &object_copied_needs_copy);
14554 if (kr == KERN_MEMORY_RESTART_COPY) {
14555 old_start -= start_delta;
14556 old_end += end_delta;
14557 vm_object_deallocate(copy_object);
14558 copy_object = VM_OBJECT_NULL;
14559 vm_map_lookup_and_lock_object_copy_strategically_restart++;
14560 goto RetrySubMap;
14561 }
14562 if (kr != KERN_SUCCESS) {
14563 if ((cow_sub_map_parent) && (cow_sub_map_parent != map)) {
14564 vm_map_unlock(cow_sub_map_parent);
14565 }
14566 if ((*real_map != map)
14567 && (*real_map != cow_sub_map_parent)) {
14568 vm_map_unlock(*real_map);
14569 }
14570 *real_map = map;
14571 vm_object_deallocate(copy_object);
14572 copy_object = VM_OBJECT_NULL;
14573 ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_SUBMAP_COPY_STRAT_FAILED), 0 /* arg */);
14574 DTRACE_VM4(submap_copy_error_strategically,
14575 vm_object_t, sub_object,
14576 vm_object_offset_t, submap_entry_offset,
14577 vm_object_size_t, submap_entry_size,
14578 int, kr);
14579 vm_map_lookup_and_lock_object_copy_strategically_error++;
14580 return kr;
14581 }
14582 assert(copy_object != VM_OBJECT_NULL);
14583 assert(copy_object != sub_object);
14584 object_copied = TRUE;
14585 vm_map_lookup_and_lock_object_copy_strategically_count++;
14586 vm_map_lookup_and_lock_object_copy_strategically_size += submap_entry_size;
14587 if (submap_entry_size > vm_map_lookup_and_lock_object_copy_strategically_max) {
14588 vm_map_lookup_and_lock_object_copy_strategically_max = submap_entry_size;
14589 }
14590
14591 /*
14592 * Adjust the fault offset to the submap entry.
14593 */
14594 copy_offset = (local_vaddr -
14595 submap_entry->vme_start +
14596 VME_OFFSET(submap_entry));
14597
14598 /* This works diffently than the */
14599 /* normal submap case. We go back */
14600 /* to the parent of the cow map and*/
14601 /* clip out the target portion of */
14602 /* the sub_map, substituting the */
14603 /* new copy object, */
14604
14605 subentry_protection = submap_entry->protection;
14606 subentry_max_protection = submap_entry->max_protection;
14607 subentry_no_copy_on_read = submap_entry->vme_no_copy_on_read;
14608 subentry_permanent = submap_entry->vme_permanent;
14609 subentry_csm_associated = submap_entry->csm_associated;
14610#if __arm64e__
14611 subentry_used_for_tpro = submap_entry->used_for_tpro;
14612#endif // __arm64e__
14613 vm_map_unlock_read(map);
14614 submap_entry = NULL; /* not valid after map unlock */
14615
14616 local_start = old_start;
14617 local_end = old_end;
14618 map = cow_sub_map_parent;
14619 *var_map = cow_sub_map_parent;
14620 vaddr = cow_parent_vaddr;
14621 cow_sub_map_parent = NULL;
14622
14623 if (!vm_map_lookup_entry(map,
14624 vaddr, &entry)) {
14625 if ((cow_sub_map_parent) && (cow_sub_map_parent != map)) {
14626 vm_map_unlock(cow_sub_map_parent);
14627 }
14628 if ((*real_map != map)
14629 && (*real_map != cow_sub_map_parent)) {
14630 vm_map_unlock(*real_map);
14631 }
14632 *real_map = map;
14633 vm_object_deallocate(
14634 copy_object);
14635 copy_object = VM_OBJECT_NULL;
14636 vm_map_lock_write_to_read(map);
14637 DTRACE_VM4(submap_lookup_post_unlock,
14638 uint64_t, (uint64_t)entry->vme_start,
14639 uint64_t, (uint64_t)entry->vme_end,
14640 vm_map_offset_t, vaddr,
14641 int, object_copied);
14642 return KERN_INVALID_ADDRESS;
14643 }
14644
14645 /* clip out the portion of space */
14646 /* mapped by the sub map which */
14647 /* corresponds to the underlying */
14648 /* object */
14649
14650 /*
14651 * Clip (and unnest) the smallest nested chunk
14652 * possible around the faulting address...
14653 */
14654 local_start = vaddr & ~(pmap_shared_region_size_min(map->pmap) - 1);
14655 local_end = local_start + pmap_shared_region_size_min(map->pmap);
14656 /*
14657 * ... but don't go beyond the "old_start" to "old_end"
14658 * range, to avoid spanning over another VM region
14659 * with a possibly different VM object and/or offset.
14660 */
14661 if (local_start < old_start) {
14662 local_start = old_start;
14663 }
14664 if (local_end > old_end) {
14665 local_end = old_end;
14666 }
14667 /*
14668 * Adjust copy_offset to the start of the range.
14669 */
14670 copy_offset -= (vaddr - local_start);
14671
14672 vm_map_clip_start(map, entry, local_start);
14673 vm_map_clip_end(map, entry, local_end);
14674 if (entry->is_sub_map) {
14675 /* unnesting was done when clipping */
14676 assert(!entry->use_pmap);
14677 }
14678
14679 /* substitute copy object for */
14680 /* shared map entry */
14681 vm_map_deallocate(VME_SUBMAP(entry));
14682 assert(!entry->iokit_acct);
14683 entry->use_pmap = TRUE;
14684 VME_OBJECT_SET(entry, copy_object, false, 0);
14685
14686 /* propagate the submap entry's protections */
14687 if (entry->protection != VM_PROT_READ) {
14688 /*
14689 * Someone has already altered the top entry's
14690 * protections via vm_protect(VM_PROT_COPY).
14691 * Respect these new values and ignore the
14692 * submap entry's protections.
14693 */
14694 } else {
14695 /*
14696 * Regular copy-on-write: propagate the submap
14697 * entry's protections to the top map entry.
14698 */
14699 entry->protection |= subentry_protection;
14700 }
14701 entry->max_protection |= subentry_max_protection;
14702 /* propagate some attributes from subentry */
14703 entry->vme_no_copy_on_read = subentry_no_copy_on_read;
14704 entry->vme_permanent = subentry_permanent;
14705 entry->csm_associated = subentry_csm_associated;
14706#if __arm64e__
14707 /* propagate TPRO iff the destination map has TPRO enabled */
14708 if (subentry_used_for_tpro) {
14709 if (vm_map_tpro(map)) {
14710 entry->used_for_tpro = subentry_used_for_tpro;
14711 } else {
14712 /* "permanent" came from being TPRO */
14713 entry->vme_permanent = FALSE;
14714 }
14715 }
14716#endif /* __arm64e */
14717 if ((entry->protection & VM_PROT_WRITE) &&
14718 (entry->protection & VM_PROT_EXECUTE) &&
14719#if XNU_TARGET_OS_OSX
14720 map->pmap != kernel_pmap &&
14721 (vm_map_cs_enforcement(map)
14722#if __arm64__
14723 || !VM_MAP_IS_EXOTIC(map)
14724#endif /* __arm64__ */
14725 ) &&
14726#endif /* XNU_TARGET_OS_OSX */
14727#if CODE_SIGNING_MONITOR
14728 (csm_address_space_exempt(map->pmap) != KERN_SUCCESS) &&
14729#endif
14730 !(entry->used_for_jit) &&
14731 VM_MAP_POLICY_WX_STRIP_X(map)) {
14732 DTRACE_VM3(cs_wx,
14733 uint64_t, (uint64_t)entry->vme_start,
14734 uint64_t, (uint64_t)entry->vme_end,
14735 vm_prot_t, entry->protection);
14736 printf("CODE SIGNING: %d[%s] %s:%d(0x%llx,0x%llx,0x%x) can't have both write and exec at the same time\n",
14737 proc_selfpid(),
14738 (get_bsdtask_info(current_task())
14739 ? proc_name_address(get_bsdtask_info(current_task()))
14740 : "?"),
14741 __FUNCTION__, __LINE__,
14742#if DEVELOPMENT || DEBUG
14743 (uint64_t)entry->vme_start,
14744 (uint64_t)entry->vme_end,
14745#else /* DEVELOPMENT || DEBUG */
14746 (uint64_t)0,
14747 (uint64_t)0,
14748#endif /* DEVELOPMENT || DEBUG */
14749 entry->protection);
14750 entry->protection &= ~VM_PROT_EXECUTE;
14751 }
14752
14753 if (object_copied) {
14754 VME_OFFSET_SET(entry, local_start - old_start + object_copied_offset);
14755 entry->needs_copy = object_copied_needs_copy;
14756 entry->is_shared = FALSE;
14757 } else {
14758 assert(VME_OBJECT(entry) != VM_OBJECT_NULL);
14759 assert(VME_OBJECT(entry)->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC);
14760 assert(entry->wired_count == 0);
14761 VME_OFFSET_SET(entry, copy_offset);
14762 entry->needs_copy = TRUE;
14763 if (map != old_map) {
14764 entry->is_shared = TRUE;
14765 }
14766 }
14767 if (entry->inheritance == VM_INHERIT_SHARE) {
14768 entry->inheritance = VM_INHERIT_COPY;
14769 }
14770
14771 vm_map_lock_write_to_read(map);
14772 } else if (vm_map_is_sealed(map)) {
14773 assert(!submap_entry->is_sub_map);
14774 if ((cow_sub_map_parent)
14775 && (cow_sub_map_parent != *real_map)
14776 && (cow_sub_map_parent != map)) {
14777 vm_map_unlock(cow_sub_map_parent);
14778 }
14779 entry = submap_entry;
14780 vaddr = local_vaddr;
14781 } else {
14782 if ((cow_sub_map_parent)
14783 && (cow_sub_map_parent != *real_map)
14784 && (cow_sub_map_parent != map)) {
14785 vm_map_unlock(cow_sub_map_parent);
14786 }
14787 entry = submap_entry;
14788 vaddr = local_vaddr;
14789 }
14790 }
14791
14792 /*
14793 * Check whether this task is allowed to have
14794 * this page.
14795 */
14796
14797 prot = entry->protection;
14798
14799 if (override_nx(old_map, VME_ALIAS(entry)) && prot) {
14800 /*
14801 * HACK -- if not a stack, then allow execution
14802 */
14803 prot |= VM_PROT_EXECUTE;
14804 }
14805
14806#if __arm64e__
14807 /*
14808 * If the entry we're dealing with is TPRO and we have a write
14809 * fault, inject VM_PROT_WRITE into protections. This allows us
14810 * to maintain RO permissions when not marked as TPRO.
14811 */
14812 if (entry->used_for_tpro && (fault_type & VM_PROT_WRITE)) {
14813 prot |= VM_PROT_WRITE;
14814 }
14815#endif /* __arm64e__ */
14816 if (mask_protections) {
14817 fault_type &= prot;
14818 if (fault_type == VM_PROT_NONE) {
14819 goto protection_failure;
14820 }
14821 }
14822 if (((fault_type & prot) != fault_type)
14823#if __arm64__
14824 /* prefetch abort in execute-only page */
14825 && !(prot == VM_PROT_EXECUTE && fault_type == (VM_PROT_READ | VM_PROT_EXECUTE))
14826#elif defined(__x86_64__)
14827 /* Consider the UEXEC bit when handling an EXECUTE fault */
14828 && !((fault_type & VM_PROT_EXECUTE) && !(prot & VM_PROT_EXECUTE) && (prot & VM_PROT_UEXEC))
14829#endif
14830 ) {
14831protection_failure:
14832 if (*real_map != map) {
14833 vm_map_unlock(*real_map);
14834 }
14835 *real_map = map;
14836
14837 if ((fault_type & VM_PROT_EXECUTE) && prot) {
14838 log_stack_execution_failure((addr64_t)vaddr, prot);
14839 }
14840
14841 DTRACE_VM2(prot_fault, int, 1, (uint64_t *), NULL);
14842 DTRACE_VM3(prot_fault_detailed, vm_prot_t, fault_type, vm_prot_t, prot, void *, vaddr);
14843 /*
14844 * Noisy (esp. internally) and can be inferred from CrashReports. So OFF for now.
14845 *
14846 * ktriage_record(thread_tid(current_thread()), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_VM, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_VM_PROTECTION_FAILURE), 0);
14847 */
14848 vmlp_api_end(VM_MAP_LOOKUP_AND_LOCK_OBJECT, KERN_PROTECTION_FAILURE);
14849 return KERN_PROTECTION_FAILURE;
14850 }
14851
14852 /*
14853 * If this page is not pageable, we have to get
14854 * it for all possible accesses.
14855 */
14856
14857 *wired = (entry->wired_count != 0);
14858 if (*wired) {
14859 fault_type = prot;
14860 }
14861
14862 /*
14863 * If the entry was copy-on-write, we either ...
14864 */
14865
14866 if (entry->needs_copy) {
14867 /*
14868 * If we want to write the page, we may as well
14869 * handle that now since we've got the map locked.
14870 *
14871 * If we don't need to write the page, we just
14872 * demote the permissions allowed.
14873 */
14874
14875 if ((fault_type & VM_PROT_WRITE) || *wired || force_copy) {
14876 /*
14877 * Make a new object, and place it in the
14878 * object chain. Note that no new references
14879 * have appeared -- one just moved from the
14880 * map to the new object.
14881 */
14882
14883 if (vm_map_lock_read_to_write(map)) {
14884 vm_map_lock_read(map);
14885 goto RetryLookup;
14886 }
14887
14888 if (VME_OBJECT(entry)->shadowed == FALSE) {
14889 vm_object_lock(VME_OBJECT(entry));
14890 VM_OBJECT_SET_SHADOWED(VME_OBJECT(entry), TRUE);
14891 vm_object_unlock(VME_OBJECT(entry));
14892 }
14893 VME_OBJECT_SHADOW(entry,
14894 (vm_map_size_t) (entry->vme_end -
14895 entry->vme_start),
14896 vm_map_always_shadow(map));
14897 entry->needs_copy = FALSE;
14898
14899 vm_map_lock_write_to_read(map);
14900 }
14901 if ((fault_type & VM_PROT_WRITE) == 0 && *wired == 0) {
14902 /*
14903 * We're attempting to read a copy-on-write
14904 * page -- don't allow writes.
14905 */
14906
14907 prot &= (~VM_PROT_WRITE);
14908 }
14909 }
14910
14911 if (submap_needed_copy && (prot & VM_PROT_WRITE)) {
14912 /*
14913 * We went through a "needs_copy" submap without triggering
14914 * a copy, so granting write access to the page would bypass
14915 * that submap's "needs_copy".
14916 */
14917 assert(!(fault_type & VM_PROT_WRITE));
14918 assert(!*wired);
14919 assert(!force_copy);
14920 // printf("FBDP %d[%s] submap_needed_copy for %p 0x%llx\n", proc_selfpid(), proc_name_address(current_task()->bsd_info), map, vaddr);
14921 prot &= ~VM_PROT_WRITE;
14922 }
14923
14924 /*
14925 * Create an object if necessary.
14926 */
14927 if (VME_OBJECT(entry) == VM_OBJECT_NULL) {
14928 if (vm_map_lock_read_to_write(map)) {
14929 vm_map_lock_read(map);
14930 goto RetryLookup;
14931 }
14932
14933 VME_OBJECT_SET(entry,
14934 vm_object_allocate(
14935 (vm_map_size_t)(entry->vme_end -
14936 entry->vme_start),
14937 map->serial_id
14938 ), false, 0);
14939 VME_OFFSET_SET(entry, 0);
14940 assert(entry->use_pmap);
14941 vm_map_lock_write_to_read(map);
14942 }
14943
14944 /*
14945 * Return the object/offset from this entry. If the entry
14946 * was copy-on-write or empty, it has been fixed up. Also
14947 * return the protection.
14948 */
14949
14950 *offset = (vaddr - entry->vme_start) + VME_OFFSET(entry);
14951 *object = VME_OBJECT(entry);
14952 *out_prot = prot;
14953 KDBG_FILTERED(MACHDBG_CODE(DBG_MACH_WORKINGSET, VM_MAP_LOOKUP_OBJECT), VM_KERNEL_UNSLIDE_OR_PERM(*object), (unsigned long) VME_ALIAS(entry), 0, 0);
14954
14955 if (fault_info) {
14956 /*
14957 * Initialize fault information according to the entry being faulted
14958 * from.
14959 */
14960 fault_info->user_tag = VME_ALIAS(entry);
14961 fault_info->pmap_options = 0;
14962 if (entry->iokit_acct ||
14963 (!entry->is_sub_map && !entry->use_pmap)) {
14964 fault_info->pmap_options |= PMAP_OPTIONS_ALT_ACCT;
14965 }
14966 if (fault_info->behavior == VM_BEHAVIOR_DEFAULT) {
14967 fault_info->behavior = entry->behavior;
14968 }
14969 fault_info->lo_offset = VME_OFFSET(entry);
14970 fault_info->hi_offset =
14971 (entry->vme_end - entry->vme_start) + VME_OFFSET(entry);
14972 fault_info->no_cache = entry->no_cache;
14973 fault_info->io_sync = FALSE;
14974 fault_info->cs_bypass = (entry->used_for_jit ||
14975#if CODE_SIGNING_MONITOR
14976 (csm_address_space_exempt(map->pmap) == KERN_SUCCESS) ||
14977#endif
14978 entry->vme_resilient_codesign);
14979 fault_info->mark_zf_absent = FALSE;
14980 fault_info->batch_pmap_op = FALSE;
14981 /*
14982 * The pmap layer will validate this page
14983 * before allowing it to be executed from.
14984 */
14985#if CODE_SIGNING_MONITOR
14986 fault_info->csm_associated = entry->csm_associated;
14987#else
14988 fault_info->csm_associated = FALSE;
14989#endif
14990
14991 fault_info->resilient_media = entry->vme_resilient_media;
14992 fault_info->fi_xnu_user_debug = entry->vme_xnu_user_debug;
14993 fault_info->no_copy_on_read = entry->vme_no_copy_on_read;
14994#if __arm64e__
14995 fault_info->fi_used_for_tpro = entry->used_for_tpro;
14996#else /* __arm64e__ */
14997 fault_info->fi_used_for_tpro = FALSE;
14998#endif
14999 if (entry->translated_allow_execute) {
15000 fault_info->pmap_options |= PMAP_OPTIONS_TRANSLATED_ALLOW_EXECUTE;
15001 }
15002 }
15003
15004 /*
15005 * Lock the object to prevent it from disappearing
15006 */
15007 if (object_lock_type == OBJECT_LOCK_EXCLUSIVE) {
15008 if (contended == NULL) {
15009 vm_object_lock(*object);
15010 } else {
15011 *contended = vm_object_lock_check_contended(*object);
15012 }
15013 } else {
15014 vm_object_lock_shared(*object);
15015 }
15016
15017 /*
15018 * Save the version number
15019 */
15020
15021 out_version->main_timestamp = map->timestamp;
15022
15023 vmlp_range_event(map, entry->vme_start, entry->vme_end - entry->vme_start);
15024 vmlp_api_end(VM_MAP_LOOKUP_AND_LOCK_OBJECT, KERN_SUCCESS);
15025 return KERN_SUCCESS;
15026}
15027
15028
15029/*
15030 * vm_map_verify:
15031 *
15032 * Verifies that the map in question has not changed
15033 * since the given version. The map has to be locked
15034 * ("shared" mode is fine) before calling this function
15035 * and it will be returned locked too.
15036 */
15037boolean_t
15038vm_map_verify(
15039 vm_map_t map,
15040 vm_map_version_t *version) /* REF */
15041{
15042 boolean_t result;
15043
15044 vm_map_lock_assert_held(map);
15045 result = (map->timestamp == version->main_timestamp);
15046
15047 return result;
15048}
15049
15050
15051/* Helper function to interrogate a VM entry's state for vm_map_region_recurse */
15052uint8_t
15053vm_map_entry_info_flags(vm_map_entry_t entry)
15054{
15055 uint8_t flags = 0;
15056 if (entry->used_for_jit) {
15057 flags |= VM_REGION_FLAG_JIT_ENABLED;
15058 }
15059
15060
15061 return flags;
15062}
15063
15064/*
15065 * TEMPORARYTEMPORARYTEMPORARYTEMPORARYTEMPORARYTEMPORARY
15066 * Goes away after regular vm_region_recurse function migrates to
15067 * 64 bits
15068 * vm_region_recurse: A form of vm_region which follows the
15069 * submaps in a target map
15070 *
15071 */
15072
15073kern_return_t
15074vm_map_region_recurse_64(
15075 vm_map_t map,
15076 vm_map_offset_ut *address_u, /* IN/OUT */
15077 vm_map_size_ut *size_u, /* OUT */
15078 natural_t *nesting_depth, /* IN/OUT */
15079 vm_region_submap_info_64_t submap_info, /* IN/OUT */
15080 mach_msg_type_number_t *count) /* IN/OUT */
15081{
15082 mach_msg_type_number_t original_count;
15083 vm_region_extended_info_data_t extended;
15084 vm_map_entry_t tmp_entry;
15085 vm_map_offset_t user_address;
15086 unsigned int user_max_depth;
15087
15088 vmlp_api_start(VM_MAP_REGION_RECURSE_64);
15089
15090 /*
15091 * "curr_entry" is the VM map entry preceding or including the
15092 * address we're looking for.
15093 * "curr_map" is the map or sub-map containing "curr_entry".
15094 * "curr_address" is the equivalent of the top map's "user_address"
15095 * in the current map.
15096 * "curr_offset" is the cumulated offset of "curr_map" in the
15097 * target task's address space.
15098 * "curr_depth" is the depth of "curr_map" in the chain of
15099 * sub-maps.
15100 *
15101 * "curr_max_below" and "curr_max_above" limit the range (around
15102 * "curr_address") we should take into account in the current (sub)map.
15103 * They limit the range to what's visible through the map entries
15104 * we've traversed from the top map to the current map.
15105 *
15106 */
15107 vm_map_entry_t curr_entry;
15108 vm_map_t curr_entry_submap;
15109 vm_map_address_t curr_entry_start;
15110 vm_object_offset_t curr_entry_offset;
15111 vm_map_address_t curr_address;
15112 vm_map_offset_t curr_offset;
15113 vm_map_t curr_map;
15114 unsigned int curr_depth;
15115 vm_map_offset_t curr_max_below, curr_max_above;
15116 vm_map_offset_t curr_skip;
15117
15118 /*
15119 * "next_" is the same as "curr_" but for the VM region immediately
15120 * after the address we're looking for. We need to keep track of this
15121 * too because we want to return info about that region if the
15122 * address we're looking for is not mapped.
15123 */
15124 vm_map_entry_t next_entry;
15125 vm_map_offset_t next_offset;
15126 vm_map_offset_t next_address;
15127 vm_map_t next_map;
15128 unsigned int next_depth;
15129 vm_map_offset_t next_max_below, next_max_above;
15130 vm_map_offset_t next_skip;
15131
15132 boolean_t look_for_pages;
15133 vm_region_submap_short_info_64_t short_info;
15134 boolean_t do_region_footprint;
15135 int effective_page_size, effective_page_shift;
15136 boolean_t submap_needed_copy;
15137
15138 if (map == VM_MAP_NULL) {
15139 /* no address space to work on */
15140 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_INVALID_ARGUMENT);
15141 return KERN_INVALID_ARGUMENT;
15142 }
15143
15144 user_address = vm_sanitize_addr(map, *address_u);
15145
15146
15147 effective_page_shift = vm_self_region_page_shift(map);
15148 effective_page_size = (1 << effective_page_shift);
15149
15150 if (*count < VM_REGION_SUBMAP_SHORT_INFO_COUNT_64) {
15151 /*
15152 * "info" structure is not big enough and
15153 * would overflow
15154 */
15155 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_INVALID_ARGUMENT);
15156 return KERN_INVALID_ARGUMENT;
15157 }
15158
15159 do_region_footprint = task_self_region_footprint();
15160 original_count = *count;
15161
15162 if (original_count < VM_REGION_SUBMAP_INFO_V0_COUNT_64) {
15163 *count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
15164 look_for_pages = FALSE;
15165 short_info = (vm_region_submap_short_info_64_t) submap_info;
15166 submap_info = NULL;
15167 } else {
15168 look_for_pages = TRUE;
15169 *count = VM_REGION_SUBMAP_INFO_V0_COUNT_64;
15170 short_info = NULL;
15171
15172 if (original_count >= VM_REGION_SUBMAP_INFO_V1_COUNT_64) {
15173 *count = VM_REGION_SUBMAP_INFO_V1_COUNT_64;
15174 }
15175 if (original_count >= VM_REGION_SUBMAP_INFO_V2_COUNT_64) {
15176 *count = VM_REGION_SUBMAP_INFO_V2_COUNT_64;
15177 }
15178 }
15179
15180 user_max_depth = *nesting_depth;
15181 submap_needed_copy = FALSE;
15182
15183 if (not_in_kdp) {
15184 vm_map_lock_read(map);
15185 }
15186
15187recurse_again:
15188 curr_entry = NULL;
15189 curr_map = map;
15190 curr_address = user_address;
15191 curr_offset = 0;
15192 curr_skip = 0;
15193 curr_depth = 0;
15194 curr_max_above = ((vm_map_offset_t) -1) - curr_address;
15195 curr_max_below = curr_address;
15196
15197 next_entry = NULL;
15198 next_map = NULL;
15199 next_address = 0;
15200 next_offset = 0;
15201 next_skip = 0;
15202 next_depth = 0;
15203 next_max_above = (vm_map_offset_t) -1;
15204 next_max_below = (vm_map_offset_t) -1;
15205
15206 for (;;) {
15207 if (vm_map_lookup_entry(curr_map,
15208 curr_address,
15209 &tmp_entry)) {
15210 /* tmp_entry contains the address we're looking for */
15211 curr_entry = tmp_entry;
15212 } else {
15213 vm_map_offset_t skip;
15214 /*
15215 * The address is not mapped. "tmp_entry" is the
15216 * map entry preceding the address. We want the next
15217 * one, if it exists.
15218 */
15219 curr_entry = tmp_entry->vme_next;
15220
15221 if (curr_entry == vm_map_to_entry(curr_map) ||
15222 (curr_entry->vme_start >=
15223 curr_address + curr_max_above)) {
15224 /* no next entry at this level: stop looking */
15225 if (not_in_kdp) {
15226 vm_map_unlock_read(curr_map);
15227 }
15228 curr_entry = NULL;
15229 curr_map = NULL;
15230 curr_skip = 0;
15231 curr_offset = 0;
15232 curr_depth = 0;
15233 curr_max_above = 0;
15234 curr_max_below = 0;
15235 break;
15236 }
15237
15238 /* adjust current address and offset */
15239 skip = curr_entry->vme_start - curr_address;
15240 curr_address = curr_entry->vme_start;
15241 curr_skip += skip;
15242 curr_offset += skip;
15243 curr_max_above -= skip;
15244 curr_max_below = 0;
15245 }
15246
15247 /*
15248 * Is the next entry at this level closer to the address (or
15249 * deeper in the submap chain) than the one we had
15250 * so far ?
15251 */
15252 tmp_entry = curr_entry->vme_next;
15253 if (tmp_entry == vm_map_to_entry(curr_map)) {
15254 /* no next entry at this level */
15255 } else if (tmp_entry->vme_start >=
15256 curr_address + curr_max_above) {
15257 /*
15258 * tmp_entry is beyond the scope of what we mapped of
15259 * this submap in the upper level: ignore it.
15260 */
15261 } else if ((next_entry == NULL) ||
15262 (tmp_entry->vme_start + curr_offset <=
15263 next_entry->vme_start + next_offset)) {
15264 /*
15265 * We didn't have a "next_entry" or this one is
15266 * closer to the address we're looking for:
15267 * use this "tmp_entry" as the new "next_entry".
15268 */
15269 if (next_entry != NULL) {
15270 /* unlock the last "next_map" */
15271 if (next_map != curr_map && not_in_kdp) {
15272 vm_map_unlock_read(next_map);
15273 }
15274 }
15275 next_entry = tmp_entry;
15276 next_map = curr_map;
15277 next_depth = curr_depth;
15278 next_address = next_entry->vme_start;
15279 next_skip = curr_skip;
15280 next_skip += (next_address - curr_address);
15281 next_offset = curr_offset;
15282 next_offset += (next_address - curr_address);
15283 next_max_above = MIN(next_max_above, curr_max_above);
15284 next_max_above = MIN(next_max_above,
15285 next_entry->vme_end - next_address);
15286 next_max_below = MIN(next_max_below, curr_max_below);
15287 next_max_below = MIN(next_max_below,
15288 next_address - next_entry->vme_start);
15289 }
15290
15291 /*
15292 * "curr_max_{above,below}" allow us to keep track of the
15293 * portion of the submap that is actually mapped at this level:
15294 * the rest of that submap is irrelevant to us, since it's not
15295 * mapped here.
15296 * The relevant portion of the map starts at
15297 * "VME_OFFSET(curr_entry)" up to the size of "curr_entry".
15298 */
15299 curr_max_above = MIN(curr_max_above,
15300 curr_entry->vme_end - curr_address);
15301 curr_max_below = MIN(curr_max_below,
15302 curr_address - curr_entry->vme_start);
15303
15304 if (!curr_entry->is_sub_map ||
15305 curr_depth >= user_max_depth) {
15306 /*
15307 * We hit a leaf map or we reached the maximum depth
15308 * we could, so stop looking. Keep the current map
15309 * locked.
15310 */
15311 break;
15312 }
15313
15314 /*
15315 * Get down to the next submap level.
15316 */
15317
15318 if (curr_entry->needs_copy) {
15319 /* everything below this is effectively copy-on-write */
15320 submap_needed_copy = TRUE;
15321 }
15322
15323 /*
15324 * Lock the next level and unlock the current level,
15325 * unless we need to keep it locked to access the "next_entry"
15326 * later.
15327 */
15328 curr_entry_submap = VME_SUBMAP(curr_entry);
15329 curr_entry_start = curr_entry->vme_start;
15330 curr_entry_offset = VME_OFFSET(curr_entry);
15331 curr_entry = VM_MAP_ENTRY_NULL; /* no longer valid after unlocking the map */
15332 if (not_in_kdp) {
15333 vm_map_lock_read(curr_entry_submap);
15334 }
15335 if (curr_map == next_map) {
15336 /* keep "next_map" locked in case we need it */
15337 } else {
15338 /* release this map */
15339 if (not_in_kdp) {
15340 vm_map_unlock_read(curr_map);
15341 }
15342 }
15343
15344 /*
15345 * Adjust the offset. "curr_entry" mapped the submap
15346 * at relative address "curr_entry_start" in the
15347 * curr_map but skips the first "curr_entry_offset"
15348 * bytes of the submap.
15349 * "curr_offset" always represents the offset of a virtual
15350 * address in the curr_map relative to the absolute address
15351 * space (i.e. the top-level VM map).
15352 */
15353 curr_offset += curr_entry_offset - curr_entry_start;
15354 curr_address = user_address + curr_offset;
15355 /* switch to the submap */
15356 curr_map = curr_entry_submap;
15357 curr_depth++;
15358 }
15359
15360// LP64todo: all the current tools are 32bit, obviously never worked for 64b
15361// so probably should be a real 32b ID vs. ptr.
15362// Current users just check for equality
15363
15364 if (curr_entry == NULL) {
15365 /* no VM region contains the address... */
15366
15367 if (do_region_footprint && /* we want footprint numbers */
15368 next_entry == NULL && /* & there are no more regions */
15369 /* & we haven't already provided our fake region: */
15370 user_address <= vm_map_last_entry(map)->vme_end) {
15371 ledger_amount_t ledger_resident = 0, ledger_compressed = 0;
15372
15373 /*
15374 * Add a fake memory region to account for
15375 * purgeable and/or ledger-tagged memory that
15376 * counts towards this task's memory footprint,
15377 * i.e. the resident/compressed pages of non-volatile
15378 * objects owned by that task.
15379 */
15380 if (__improbable(map->pmap == NULL)) {
15381 /* Some VM tests reach this. (TODO make this more strict, rdar://148290198) */
15382 panic_on_release_builds("null pmap");
15383 } else {
15384 task_ledgers_footprint(map->pmap->ledger,
15385 &ledger_resident,
15386 &ledger_compressed);
15387 }
15388 if (ledger_resident + ledger_compressed == 0) {
15389 /* no purgeable memory usage to report */
15390 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_INVALID_ADDRESS);
15391 return KERN_INVALID_ADDRESS;
15392 }
15393 /* fake region to show nonvolatile footprint */
15394 if (look_for_pages) {
15395 submap_info->protection = VM_PROT_DEFAULT;
15396 submap_info->max_protection = VM_PROT_DEFAULT;
15397 submap_info->inheritance = VM_INHERIT_DEFAULT;
15398 submap_info->offset = 0;
15399 submap_info->user_tag = -1;
15400 submap_info->pages_resident = (unsigned int) (ledger_resident / effective_page_size);
15401 submap_info->pages_shared_now_private = 0;
15402 submap_info->pages_swapped_out = (unsigned int) (ledger_compressed / effective_page_size);
15403 submap_info->pages_dirtied = submap_info->pages_resident;
15404 submap_info->ref_count = 1;
15405 submap_info->shadow_depth = 0;
15406 submap_info->external_pager = 0;
15407 submap_info->share_mode = SM_PRIVATE;
15408 if (submap_needed_copy) {
15409 submap_info->share_mode = SM_COW;
15410 }
15411 submap_info->is_submap = 0;
15412 submap_info->behavior = VM_BEHAVIOR_DEFAULT;
15413 submap_info->object_id = VM_OBJECT_ID_FAKE(map, task_ledgers.purgeable_nonvolatile);
15414 submap_info->user_wired_count = 0;
15415 submap_info->pages_reusable = 0;
15416 } else {
15417 short_info->user_tag = -1;
15418 short_info->offset = 0;
15419 short_info->protection = VM_PROT_DEFAULT;
15420 short_info->inheritance = VM_INHERIT_DEFAULT;
15421 short_info->max_protection = VM_PROT_DEFAULT;
15422 short_info->behavior = VM_BEHAVIOR_DEFAULT;
15423 short_info->user_wired_count = 0;
15424 short_info->is_submap = 0;
15425 short_info->object_id = VM_OBJECT_ID_FAKE(map, task_ledgers.purgeable_nonvolatile);
15426 short_info->external_pager = 0;
15427 short_info->shadow_depth = 0;
15428 short_info->share_mode = SM_PRIVATE;
15429 if (submap_needed_copy) {
15430 short_info->share_mode = SM_COW;
15431 }
15432 short_info->ref_count = 1;
15433 }
15434 *nesting_depth = 0;
15435 *address_u = vm_sanitize_wrap_addr(vm_map_last_entry(map)->vme_end);
15436 *size_u = vm_sanitize_wrap_size(ledger_resident + ledger_compressed);
15437 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_SUCCESS);
15438 return KERN_SUCCESS;
15439 }
15440
15441 if (next_entry == NULL) {
15442 /* ... and no VM region follows it either */
15443 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_INVALID_ADDRESS);
15444 return KERN_INVALID_ADDRESS;
15445 }
15446 /* ... gather info about the next VM region */
15447 curr_entry = next_entry;
15448 curr_map = next_map; /* still locked ... */
15449 curr_address = next_address;
15450 curr_skip = next_skip;
15451 curr_offset = next_offset;
15452 curr_depth = next_depth;
15453 curr_max_above = next_max_above;
15454 curr_max_below = next_max_below;
15455 } else {
15456 /* we won't need "next_entry" after all */
15457 if (next_entry != NULL) {
15458 /* release "next_map" */
15459 if (next_map != curr_map && not_in_kdp) {
15460 vm_map_unlock_read(next_map);
15461 }
15462 }
15463 }
15464 next_entry = NULL;
15465 next_map = NULL;
15466 next_offset = 0;
15467 next_skip = 0;
15468 next_depth = 0;
15469 next_max_below = -1;
15470 next_max_above = -1;
15471
15472 if (curr_entry->is_sub_map &&
15473 curr_depth < user_max_depth) {
15474 /*
15475 * We're not as deep as we could be: we must have
15476 * gone back up after not finding anything mapped
15477 * below the original top-level map entry's.
15478 * Let's move "curr_address" forward and recurse again.
15479 */
15480 user_address = curr_address;
15481 goto recurse_again;
15482 }
15483
15484 vmlp_range_event_entry(curr_map, curr_entry);
15485
15486 *nesting_depth = curr_depth;
15487 *address_u = vm_sanitize_wrap_addr(
15488 user_address + curr_skip - curr_max_below);
15489 *size_u = vm_sanitize_wrap_size(curr_max_above + curr_max_below);
15490
15491 if (look_for_pages) {
15492 submap_info->user_tag = VME_ALIAS(curr_entry);
15493 submap_info->offset = VME_OFFSET(curr_entry);
15494 submap_info->protection = curr_entry->protection;
15495 submap_info->inheritance = curr_entry->inheritance;
15496 submap_info->max_protection = curr_entry->max_protection;
15497 submap_info->behavior = curr_entry->behavior;
15498 submap_info->user_wired_count = curr_entry->user_wired_count;
15499 submap_info->is_submap = curr_entry->is_sub_map;
15500 if (curr_entry->is_sub_map) {
15501 submap_info->object_id = VM_OBJECT_ID(VME_SUBMAP(curr_entry));
15502 } else {
15503 submap_info->object_id = VM_OBJECT_ID(VME_OBJECT(curr_entry));
15504 submap_info->flags = vm_map_entry_info_flags(curr_entry);
15505 }
15506 } else {
15507 short_info->user_tag = VME_ALIAS(curr_entry);
15508 short_info->offset = VME_OFFSET(curr_entry);
15509 short_info->protection = curr_entry->protection;
15510 short_info->inheritance = curr_entry->inheritance;
15511 short_info->max_protection = curr_entry->max_protection;
15512 short_info->behavior = curr_entry->behavior;
15513 short_info->user_wired_count = curr_entry->user_wired_count;
15514 short_info->is_submap = curr_entry->is_sub_map;
15515 if (curr_entry->is_sub_map) {
15516 short_info->object_id = VM_OBJECT_ID(VME_SUBMAP(curr_entry));
15517 } else {
15518 short_info->object_id = VM_OBJECT_ID(VME_OBJECT(curr_entry));
15519 short_info->flags = vm_map_entry_info_flags(curr_entry);
15520 }
15521 }
15522
15523 extended.pages_resident = 0;
15524 extended.pages_swapped_out = 0;
15525 extended.pages_shared_now_private = 0;
15526 extended.pages_dirtied = 0;
15527 extended.pages_reusable = 0;
15528 extended.external_pager = 0;
15529 extended.shadow_depth = 0;
15530 extended.share_mode = SM_EMPTY;
15531 extended.ref_count = 0;
15532
15533 if (not_in_kdp) {
15534 if (!curr_entry->is_sub_map) {
15535 vm_map_offset_t range_start, range_end;
15536 range_start = MAX((curr_address - curr_max_below),
15537 curr_entry->vme_start);
15538 range_end = MIN((curr_address + curr_max_above),
15539 curr_entry->vme_end);
15540 vm_map_region_walk(curr_map,
15541 range_start,
15542 curr_entry,
15543 (VME_OFFSET(curr_entry) +
15544 (range_start -
15545 curr_entry->vme_start)),
15546 range_end - range_start,
15547 &extended,
15548 look_for_pages, VM_REGION_EXTENDED_INFO_COUNT);
15549 if (submap_needed_copy) {
15550 extended.share_mode = SM_COW;
15551 }
15552 } else {
15553 if (curr_entry->use_pmap) {
15554 extended.share_mode = SM_TRUESHARED;
15555 } else {
15556 extended.share_mode = SM_PRIVATE;
15557 }
15558 extended.ref_count = os_ref_get_count_raw(&VME_SUBMAP(curr_entry)->map_refcnt);
15559 }
15560 }
15561
15562 if (look_for_pages) {
15563 submap_info->pages_resident = extended.pages_resident;
15564 submap_info->pages_swapped_out = extended.pages_swapped_out;
15565 submap_info->pages_shared_now_private =
15566 extended.pages_shared_now_private;
15567 submap_info->pages_dirtied = extended.pages_dirtied;
15568 submap_info->external_pager = extended.external_pager;
15569 submap_info->shadow_depth = extended.shadow_depth;
15570 submap_info->share_mode = extended.share_mode;
15571 submap_info->ref_count = extended.ref_count;
15572
15573 if (original_count >= VM_REGION_SUBMAP_INFO_V1_COUNT_64) {
15574 submap_info->pages_reusable = extended.pages_reusable;
15575 }
15576 if (original_count >= VM_REGION_SUBMAP_INFO_V2_COUNT_64) {
15577 if (curr_entry->is_sub_map) {
15578 submap_info->object_id_full = (vm_object_id_t)VM_KERNEL_ADDRHASH(VME_SUBMAP(curr_entry));
15579 } else if (VME_OBJECT(curr_entry)) {
15580 submap_info->object_id_full = (vm_object_id_t)VM_KERNEL_ADDRHASH(VME_OBJECT(curr_entry));
15581 } else {
15582 submap_info->object_id_full = 0ull;
15583 }
15584 }
15585 } else {
15586 short_info->external_pager = extended.external_pager;
15587 short_info->shadow_depth = extended.shadow_depth;
15588 short_info->share_mode = extended.share_mode;
15589 short_info->ref_count = extended.ref_count;
15590 }
15591
15592 if (not_in_kdp) {
15593 vm_map_unlock_read(curr_map);
15594 }
15595
15596 vmlp_api_end(VM_MAP_REGION_RECURSE_64, KERN_SUCCESS);
15597 return KERN_SUCCESS;
15598}
15599
15600/*
15601 * vm_region:
15602 *
15603 * User call to obtain information about a region in
15604 * a task's address map. Currently, only one flavor is
15605 * supported.
15606 *
15607 * XXX The reserved and behavior fields cannot be filled
15608 * in until the vm merge from the IK is completed, and
15609 * vm_reserve is implemented.
15610 */
15611
15612kern_return_t
15613vm_map_region(
15614 vm_map_t map,
15615 vm_map_offset_ut *address_u, /* IN/OUT */
15616 vm_map_size_ut *size_u, /* OUT */
15617 vm_region_flavor_t flavor, /* IN */
15618 vm_region_info_t info, /* OUT */
15619 mach_msg_type_number_t *count, /* IN/OUT */
15620 mach_port_t *object_name) /* OUT */
15621{
15622 vm_map_entry_t tmp_entry;
15623 vm_map_entry_t entry;
15624 vm_map_offset_t start;
15625
15626 if (map == VM_MAP_NULL) {
15627 return KERN_INVALID_ARGUMENT;
15628 }
15629
15630 vmlp_api_start(VM_MAP_REGION);
15631
15632 start = vm_sanitize_addr(map, *address_u);
15633
15634
15635 switch (flavor) {
15636 case VM_REGION_BASIC_INFO:
15637 /* legacy for old 32-bit objects info */
15638 {
15639 vm_region_basic_info_t basic;
15640
15641 if (*count < VM_REGION_BASIC_INFO_COUNT) {
15642 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15643 return KERN_INVALID_ARGUMENT;
15644 }
15645
15646 basic = (vm_region_basic_info_t) info;
15647 *count = VM_REGION_BASIC_INFO_COUNT;
15648
15649 vm_map_lock_read(map);
15650
15651 if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
15652 if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
15653 vm_map_unlock_read(map);
15654 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ADDRESS);
15655 return KERN_INVALID_ADDRESS;
15656 }
15657 } else {
15658 entry = tmp_entry;
15659 }
15660
15661 start = entry->vme_start;
15662 vmlp_range_event(map, start, entry->vme_end - start);
15663
15664 basic->offset = (uint32_t)VME_OFFSET(entry);
15665 basic->protection = entry->protection;
15666 basic->inheritance = entry->inheritance;
15667 basic->max_protection = entry->max_protection;
15668 basic->behavior = entry->behavior;
15669 basic->user_wired_count = entry->user_wired_count;
15670 basic->reserved = entry->is_sub_map;
15671
15672 *address_u = vm_sanitize_wrap_addr(start);
15673 *size_u = vm_sanitize_wrap_size(entry->vme_end - start);
15674
15675 if (object_name) {
15676 *object_name = IP_NULL;
15677 }
15678 if (entry->is_sub_map) {
15679 basic->shared = FALSE;
15680 } else {
15681 basic->shared = entry->is_shared;
15682 }
15683
15684 vm_map_unlock_read(map);
15685 vmlp_api_end(VM_MAP_REGION, KERN_SUCCESS);
15686 return KERN_SUCCESS;
15687 }
15688
15689 case VM_REGION_BASIC_INFO_64:
15690 {
15691 vm_region_basic_info_64_t basic;
15692
15693 if (*count < VM_REGION_BASIC_INFO_COUNT_64) {
15694 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15695 return KERN_INVALID_ARGUMENT;
15696 }
15697
15698 basic = (vm_region_basic_info_64_t) info;
15699 *count = VM_REGION_BASIC_INFO_COUNT_64;
15700
15701 vm_map_lock_read(map);
15702
15703 if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
15704 if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
15705 vm_map_unlock_read(map);
15706 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ADDRESS);
15707 return KERN_INVALID_ADDRESS;
15708 }
15709 } else {
15710 entry = tmp_entry;
15711 }
15712
15713 start = entry->vme_start;
15714 vmlp_range_event(map, start, entry->vme_end - start);
15715
15716 basic->offset = VME_OFFSET(entry);
15717 basic->protection = entry->protection;
15718 basic->inheritance = entry->inheritance;
15719 basic->max_protection = entry->max_protection;
15720 basic->behavior = entry->behavior;
15721 basic->user_wired_count = entry->user_wired_count;
15722 basic->reserved = entry->is_sub_map;
15723
15724 *address_u = vm_sanitize_wrap_addr(start);
15725 *size_u = vm_sanitize_wrap_size(entry->vme_end - start);
15726
15727 if (object_name) {
15728 *object_name = IP_NULL;
15729 }
15730 if (entry->is_sub_map) {
15731 basic->shared = FALSE;
15732 } else {
15733 basic->shared = entry->is_shared;
15734 }
15735
15736 vm_map_unlock_read(map);
15737 vmlp_api_end(VM_MAP_REGION, KERN_SUCCESS);
15738 return KERN_SUCCESS;
15739 }
15740 case VM_REGION_EXTENDED_INFO:
15741 if (*count < VM_REGION_EXTENDED_INFO_COUNT) {
15742 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15743 return KERN_INVALID_ARGUMENT;
15744 }
15745 OS_FALLTHROUGH;
15746 case VM_REGION_EXTENDED_INFO__legacy:
15747 {
15748 vm_region_extended_info_t extended;
15749 mach_msg_type_number_t original_count;
15750 int effective_page_size, effective_page_shift;
15751
15752 if (*count < VM_REGION_EXTENDED_INFO_COUNT__legacy) {
15753 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15754 return KERN_INVALID_ARGUMENT;
15755 }
15756
15757 extended = (vm_region_extended_info_t) info;
15758
15759 effective_page_shift = vm_self_region_page_shift(map);
15760 effective_page_size = (1 << effective_page_shift);
15761
15762 vm_map_lock_read(map);
15763
15764 if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
15765 if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
15766 vm_map_unlock_read(map);
15767 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ADDRESS);
15768 return KERN_INVALID_ADDRESS;
15769 }
15770 } else {
15771 entry = tmp_entry;
15772 }
15773 start = entry->vme_start;
15774 vmlp_range_event(map, start, entry->vme_end - start);
15775
15776 extended->protection = entry->protection;
15777 extended->user_tag = VME_ALIAS(entry);
15778 extended->pages_resident = 0;
15779 extended->pages_swapped_out = 0;
15780 extended->pages_shared_now_private = 0;
15781 extended->pages_dirtied = 0;
15782 extended->external_pager = 0;
15783 extended->shadow_depth = 0;
15784
15785 original_count = *count;
15786 if (flavor == VM_REGION_EXTENDED_INFO__legacy) {
15787 *count = VM_REGION_EXTENDED_INFO_COUNT__legacy;
15788 } else {
15789 extended->pages_reusable = 0;
15790 *count = VM_REGION_EXTENDED_INFO_COUNT;
15791 }
15792
15793 vm_map_region_walk(map, start, entry, VME_OFFSET(entry), entry->vme_end - start, extended, TRUE, *count);
15794
15795 if (object_name) {
15796 *object_name = IP_NULL;
15797 }
15798
15799 *address_u = vm_sanitize_wrap_addr(start);
15800 *size_u = vm_sanitize_wrap_size(entry->vme_end - start);
15801
15802 vm_map_unlock_read(map);
15803 vmlp_api_end(VM_MAP_REGION, KERN_SUCCESS);
15804 return KERN_SUCCESS;
15805 }
15806 case VM_REGION_TOP_INFO:
15807 {
15808 vm_region_top_info_t top;
15809
15810 if (*count < VM_REGION_TOP_INFO_COUNT) {
15811 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15812 return KERN_INVALID_ARGUMENT;
15813 }
15814
15815 top = (vm_region_top_info_t) info;
15816 *count = VM_REGION_TOP_INFO_COUNT;
15817
15818 vm_map_lock_read(map);
15819
15820 if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
15821 if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
15822 vm_map_unlock_read(map);
15823 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ADDRESS);
15824 return KERN_INVALID_ADDRESS;
15825 }
15826 } else {
15827 entry = tmp_entry;
15828 }
15829 start = entry->vme_start;
15830 vmlp_range_event(map, start, entry->vme_end - start);
15831
15832 top->private_pages_resident = 0;
15833 top->shared_pages_resident = 0;
15834
15835 vm_map_region_top_walk(entry, top);
15836
15837 if (object_name) {
15838 *object_name = IP_NULL;
15839 }
15840
15841 *address_u = vm_sanitize_wrap_addr(start);
15842 *size_u = vm_sanitize_wrap_size(entry->vme_end - start);
15843
15844 vm_map_unlock_read(map);
15845 vmlp_api_end(VM_MAP_REGION, KERN_SUCCESS);
15846 return KERN_SUCCESS;
15847 }
15848 default:
15849 vmlp_api_end(VM_MAP_REGION, KERN_INVALID_ARGUMENT);
15850 return KERN_INVALID_ARGUMENT;
15851 }
15852}
15853
15854#define OBJ_RESIDENT_COUNT(obj, entry_size) \
15855 MIN((entry_size), \
15856 ((obj)->all_reusable ? \
15857 (obj)->wired_page_count : \
15858 (obj)->resident_page_count - (obj)->reusable_page_count))
15859
15860void
15861vm_map_region_top_walk(
15862 vm_map_entry_t entry,
15863 vm_region_top_info_t top)
15864{
15865 if (entry->is_sub_map || VME_OBJECT(entry) == 0) {
15866 top->share_mode = SM_EMPTY;
15867 top->ref_count = 0;
15868 top->obj_id = 0;
15869 return;
15870 }
15871
15872 {
15873 struct vm_object *obj, *tmp_obj;
15874 int ref_count;
15875 uint32_t entry_size;
15876
15877 entry_size = (uint32_t) ((entry->vme_end - entry->vme_start) / PAGE_SIZE_64);
15878
15879 obj = VME_OBJECT(entry);
15880
15881 vm_object_lock(obj);
15882
15883 if ((ref_count = os_ref_get_count_raw(&obj->ref_count)) > 1 &&
15884 obj->paging_in_progress) {
15885 ref_count--;
15886 }
15887
15888 assert(obj->reusable_page_count <= obj->resident_page_count);
15889 if (obj->shadow) {
15890 if (ref_count == 1) {
15891 top->private_pages_resident =
15892 OBJ_RESIDENT_COUNT(obj, entry_size);
15893 } else {
15894 top->shared_pages_resident =
15895 OBJ_RESIDENT_COUNT(obj, entry_size);
15896 }
15897 top->ref_count = ref_count;
15898 top->share_mode = SM_COW;
15899
15900 while ((tmp_obj = obj->shadow)) {
15901 vm_object_lock(tmp_obj);
15902 vm_object_unlock(obj);
15903 obj = tmp_obj;
15904
15905 if ((ref_count = os_ref_get_count_raw(&obj->ref_count)) > 1 &&
15906 obj->paging_in_progress) {
15907 ref_count--;
15908 }
15909
15910 assert(obj->reusable_page_count <= obj->resident_page_count);
15911 top->shared_pages_resident +=
15912 OBJ_RESIDENT_COUNT(obj, entry_size);
15913 top->ref_count += ref_count - 1;
15914 }
15915 } else {
15916 if (entry->superpage_size) {
15917 top->share_mode = SM_LARGE_PAGE;
15918 top->shared_pages_resident = 0;
15919 top->private_pages_resident = entry_size;
15920 } else if (entry->needs_copy) {
15921 top->share_mode = SM_COW;
15922 top->shared_pages_resident =
15923 OBJ_RESIDENT_COUNT(obj, entry_size);
15924 } else {
15925 if (ref_count == 1 ||
15926 (ref_count == 2 && obj->named)) {
15927 top->share_mode = SM_PRIVATE;
15928 top->private_pages_resident =
15929 OBJ_RESIDENT_COUNT(obj,
15930 entry_size);
15931 } else {
15932 top->share_mode = SM_SHARED;
15933 top->shared_pages_resident =
15934 OBJ_RESIDENT_COUNT(obj,
15935 entry_size);
15936 }
15937 }
15938 top->ref_count = ref_count;
15939 }
15940
15941 vm_object_unlock(obj);
15942
15943 /* XXX K64: obj_id will be truncated */
15944 top->obj_id = (unsigned int) (uintptr_t)VM_KERNEL_ADDRHASH(obj);
15945 }
15946}
15947
15948void
15949vm_map_region_walk(
15950 vm_map_t map,
15951 vm_map_offset_t va,
15952 vm_map_entry_t entry,
15953 vm_object_offset_t offset,
15954 vm_object_size_t range,
15955 vm_region_extended_info_t extended,
15956 boolean_t look_for_pages,
15957 mach_msg_type_number_t count)
15958{
15959 struct vm_object *obj, *tmp_obj;
15960 vm_map_offset_t last_offset;
15961 int i;
15962 int ref_count;
15963 struct vm_object *shadow_object;
15964 unsigned short shadow_depth;
15965 boolean_t do_region_footprint;
15966 int effective_page_size, effective_page_shift;
15967 vm_map_offset_t effective_page_mask;
15968
15969 do_region_footprint = task_self_region_footprint();
15970
15971 if ((entry->is_sub_map) ||
15972 (VME_OBJECT(entry) == VM_OBJECT_NULL) ||
15973 (VME_OBJECT(entry)->phys_contiguous &&
15974 !entry->superpage_size)) {
15975 extended->share_mode = SM_EMPTY;
15976 extended->ref_count = 0;
15977 return;
15978 }
15979
15980 if (entry->superpage_size) {
15981 extended->shadow_depth = 0;
15982 extended->share_mode = SM_LARGE_PAGE;
15983 extended->ref_count = 1;
15984 extended->external_pager = 0;
15985
15986 /* TODO4K: Superpage in 4k mode? */
15987 extended->pages_resident = (unsigned int)(range >> PAGE_SHIFT);
15988 extended->shadow_depth = 0;
15989 return;
15990 }
15991
15992 effective_page_shift = vm_self_region_page_shift(map);
15993 effective_page_size = (1 << effective_page_shift);
15994 effective_page_mask = effective_page_size - 1;
15995
15996 offset = vm_map_trunc_page(offset, effective_page_mask);
15997
15998 obj = VME_OBJECT(entry);
15999
16000 vm_object_lock(obj);
16001
16002 if ((ref_count = os_ref_get_count_raw(&obj->ref_count)) > 1 &&
16003 obj->paging_in_progress) {
16004 ref_count--;
16005 }
16006
16007 if (look_for_pages) {
16008 for (last_offset = offset + range;
16009 offset < last_offset;
16010 offset += effective_page_size, va += effective_page_size) {
16011 if (do_region_footprint) {
16012 int disp;
16013
16014 disp = 0;
16015 if (map->has_corpse_footprint) {
16016 /*
16017 * Query the page info data we saved
16018 * while forking the corpse.
16019 */
16020 vm_map_corpse_footprint_query_page_info(
16021 map,
16022 va,
16023 &disp);
16024 } else {
16025 /*
16026 * Query the pmap.
16027 */
16028 vm_map_footprint_query_page_info_exclusive(
16029 map,
16030 entry,
16031 va,
16032 &disp);
16033 }
16034 if (disp & VM_PAGE_QUERY_PAGE_PRESENT) {
16035 extended->pages_resident++;
16036 }
16037 if (disp & VM_PAGE_QUERY_PAGE_REUSABLE) {
16038 extended->pages_reusable++;
16039 }
16040 if (disp & VM_PAGE_QUERY_PAGE_DIRTY) {
16041 extended->pages_dirtied++;
16042 }
16043 if (disp & PMAP_QUERY_PAGE_COMPRESSED) {
16044 extended->pages_swapped_out++;
16045 }
16046 continue;
16047 }
16048
16049 vm_map_region_look_for_page(map, va, obj,
16050 vm_object_trunc_page(offset), ref_count,
16051 0, extended, count);
16052 }
16053
16054 if (do_region_footprint) {
16055 goto collect_object_info;
16056 }
16057 } else {
16058collect_object_info:
16059 shadow_object = obj->shadow;
16060 shadow_depth = 0;
16061
16062 if (!(obj->internal)) {
16063 extended->external_pager = 1;
16064 }
16065
16066 if (shadow_object != VM_OBJECT_NULL) {
16067 vm_object_lock(shadow_object);
16068 for (;
16069 shadow_object != VM_OBJECT_NULL;
16070 shadow_depth++) {
16071 vm_object_t next_shadow;
16072
16073 if (!(shadow_object->internal)) {
16074 extended->external_pager = 1;
16075 }
16076
16077 next_shadow = shadow_object->shadow;
16078 if (next_shadow) {
16079 vm_object_lock(next_shadow);
16080 }
16081 vm_object_unlock(shadow_object);
16082 shadow_object = next_shadow;
16083 }
16084 }
16085 extended->shadow_depth = shadow_depth;
16086 }
16087
16088 if (extended->shadow_depth || entry->needs_copy) {
16089 extended->share_mode = SM_COW;
16090 } else {
16091 if (ref_count == 1) {
16092 extended->share_mode = SM_PRIVATE;
16093 } else {
16094 if (obj->true_share) {
16095 extended->share_mode = SM_TRUESHARED;
16096 } else {
16097 extended->share_mode = SM_SHARED;
16098 }
16099 }
16100 }
16101 extended->ref_count = ref_count - extended->shadow_depth;
16102
16103 for (i = 0; i < extended->shadow_depth; i++) {
16104 if ((tmp_obj = obj->shadow) == 0) {
16105 break;
16106 }
16107 vm_object_lock(tmp_obj);
16108 vm_object_unlock(obj);
16109
16110 if ((ref_count = os_ref_get_count_raw(&tmp_obj->ref_count)) > 1 &&
16111 tmp_obj->paging_in_progress) {
16112 ref_count--;
16113 }
16114
16115 extended->ref_count += ref_count;
16116 obj = tmp_obj;
16117 }
16118 vm_object_unlock(obj);
16119
16120 if (extended->external_pager && extended->ref_count == 2 && extended->share_mode == SM_SHARED) {
16121 extended->share_mode = SM_PRIVATE;
16122 } else if (extended->share_mode == SM_SHARED && !(task_self_region_info_flags() & VM_REGION_INFO_FLAGS_NO_ALIASED)) {
16123 vm_map_entry_t cur;
16124 vm_map_entry_t last;
16125 int my_refs;
16126
16127 obj = VME_OBJECT(entry);
16128 last = vm_map_to_entry(map);
16129 my_refs = 0;
16130
16131 if ((ref_count = os_ref_get_count_raw(&obj->ref_count)) > 1 &&
16132 obj->paging_in_progress) {
16133 ref_count--;
16134 }
16135 for (cur = vm_map_first_entry(map); cur != last; cur = cur->vme_next) {
16136 if (vm_map_region_has_obj_ref(cur, obj)) {
16137 my_refs++;
16138 }
16139 }
16140
16141 if (my_refs == ref_count) {
16142 extended->share_mode = SM_PRIVATE_ALIASED;
16143 } else if (my_refs > 1) {
16144 extended->share_mode = SM_SHARED_ALIASED;
16145 }
16146 }
16147}
16148
16149
16150/* object is locked on entry and locked on return */
16151
16152
16153static void
16154vm_map_region_look_for_page(
16155 __unused vm_map_t map,
16156 __unused vm_map_offset_t va,
16157 vm_object_t object,
16158 vm_object_offset_t offset,
16159 int max_refcnt,
16160 unsigned short depth,
16161 vm_region_extended_info_t extended,
16162 mach_msg_type_number_t count)
16163{
16164 vm_page_t p;
16165 vm_object_t shadow;
16166 int ref_count;
16167 vm_object_t caller_object;
16168
16169 shadow = object->shadow;
16170 caller_object = object;
16171
16172
16173 while (TRUE) {
16174 if (!(object->internal)) {
16175 extended->external_pager = 1;
16176 }
16177
16178 if ((p = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
16179 if (shadow && (max_refcnt == 1)) {
16180 extended->pages_shared_now_private++;
16181 }
16182
16183 if (!vm_page_is_fictitious(p) &&
16184 (p->vmp_dirty || pmap_is_modified(VM_PAGE_GET_PHYS_PAGE(p)))) {
16185 extended->pages_dirtied++;
16186 } else if (count >= VM_REGION_EXTENDED_INFO_COUNT) {
16187 if (p->vmp_reusable || object->all_reusable) {
16188 extended->pages_reusable++;
16189 }
16190 }
16191
16192 extended->pages_resident++;
16193
16194 if (object != caller_object) {
16195 vm_object_unlock(object);
16196 }
16197
16198 return;
16199 }
16200 if (object->internal &&
16201 object->alive &&
16202 !object->terminating &&
16203 object->pager_ready) {
16204 if (vm_object_compressor_pager_state_get(object, offset)
16205 == VM_EXTERNAL_STATE_EXISTS) {
16206 /* the pager has that page */
16207 extended->pages_swapped_out++;
16208 if (object != caller_object) {
16209 vm_object_unlock(object);
16210 }
16211 return;
16212 }
16213 }
16214
16215 if (shadow) {
16216 vm_object_lock(shadow);
16217 if ((ref_count = os_ref_get_count_raw(&shadow->ref_count)) > 1 &&
16218 shadow->paging_in_progress) {
16219 ref_count--;
16220 }
16221
16222 if (++depth > extended->shadow_depth) {
16223 extended->shadow_depth = depth;
16224 }
16225
16226 if (ref_count > max_refcnt) {
16227 max_refcnt = ref_count;
16228 }
16229
16230 if (object != caller_object) {
16231 vm_object_unlock(object);
16232 }
16233
16234 offset = offset + object->vo_shadow_offset;
16235 object = shadow;
16236 shadow = object->shadow;
16237 continue;
16238 }
16239 if (object != caller_object) {
16240 vm_object_unlock(object);
16241 }
16242 break;
16243 }
16244}
16245
16246static inline boolean_t
16247vm_map_region_has_obj_ref(
16248 vm_map_entry_t entry,
16249 vm_object_t object)
16250{
16251 vm_object_t cur_obj;
16252 vm_object_t shadow_obj;
16253
16254 if (entry->is_sub_map) {
16255 return FALSE;
16256 }
16257
16258 cur_obj = VME_OBJECT(entry);
16259 if (cur_obj == VM_OBJECT_NULL) {
16260 return FALSE;
16261 } else if (cur_obj == object) {
16262 return TRUE;
16263 }
16264
16265 /*
16266 * Avoid locks for first shadow check, otherwise diagnostic tools will
16267 * spend most of their time obtaining locks in this function when analyzing
16268 * processes with many VM entries which may commonly have no shadow chain.
16269 *
16270 * This is acceptable because:
16271 * - Shadow's fields are not accessed outside of its lock
16272 * - Objects are unlikely to be modified due to:
16273 * - Many diagnostic tools suspend the task
16274 * - VM map is locked
16275 * - The rare incorrect return from this function turns a guess into a
16276 * slightly worse guess
16277 * - Entire shadow chain is not locked as a whole, so can still change
16278 * while traversing, resulting in incorrect guess even with locking
16279 */
16280 shadow_obj = cur_obj->shadow;
16281 if (shadow_obj == VM_OBJECT_NULL) {
16282 return FALSE;
16283 } else if (shadow_obj == object) {
16284 return TRUE;
16285 }
16286
16287 vm_object_lock(cur_obj);
16288
16289 while ((shadow_obj = cur_obj->shadow)) {
16290 /* check if object was found before grabbing a lock */
16291 if (shadow_obj == object) {
16292 vm_object_unlock(cur_obj);
16293 return TRUE;
16294 }
16295
16296 vm_object_lock(shadow_obj);
16297 vm_object_unlock(cur_obj);
16298 cur_obj = shadow_obj;
16299 }
16300
16301 /* exhausted the shadow chain */
16302 vm_object_unlock(cur_obj);
16303 return FALSE;
16304}
16305
16306
16307/*
16308 * Routine: vm_map_simplify
16309 *
16310 * Description:
16311 * Attempt to simplify the map representation in
16312 * the vicinity of the given starting address.
16313 * Note:
16314 * This routine is intended primarily to keep the
16315 * kernel maps more compact -- they generally don't
16316 * benefit from the "expand a map entry" technology
16317 * at allocation time because the adjacent entry
16318 * is often wired down.
16319 */
16320void
16321vm_map_simplify_entry(
16322 vm_map_t map,
16323 vm_map_entry_t this_entry)
16324{
16325 vm_map_entry_t prev_entry;
16326
16327 prev_entry = VME_PREV(this_entry);
16328
16329 if ((this_entry != vm_map_to_entry(map)) &&
16330 (prev_entry != vm_map_to_entry(map)) &&
16331
16332 (prev_entry->vme_end == this_entry->vme_start) &&
16333
16334 (prev_entry->is_sub_map == this_entry->is_sub_map) &&
16335 (prev_entry->vme_object_value == this_entry->vme_object_value) &&
16336 (prev_entry->vme_kernel_object == this_entry->vme_kernel_object) &&
16337 ((VME_OFFSET(prev_entry) + (prev_entry->vme_end -
16338 prev_entry->vme_start))
16339 == VME_OFFSET(this_entry)) &&
16340
16341 (prev_entry->behavior == this_entry->behavior) &&
16342 (prev_entry->needs_copy == this_entry->needs_copy) &&
16343 (prev_entry->protection == this_entry->protection) &&
16344 (prev_entry->max_protection == this_entry->max_protection) &&
16345 (prev_entry->inheritance == this_entry->inheritance) &&
16346 (prev_entry->use_pmap == this_entry->use_pmap) &&
16347 (VME_ALIAS(prev_entry) == VME_ALIAS(this_entry)) &&
16348 (prev_entry->no_cache == this_entry->no_cache) &&
16349 (prev_entry->vme_permanent == this_entry->vme_permanent) &&
16350 (prev_entry->zero_wired_pages == this_entry->zero_wired_pages) &&
16351 (prev_entry->used_for_jit == this_entry->used_for_jit) &&
16352#if __arm64e__
16353 (prev_entry->used_for_tpro == this_entry->used_for_tpro) &&
16354#endif
16355 (prev_entry->csm_associated == this_entry->csm_associated) &&
16356 (prev_entry->vme_xnu_user_debug == this_entry->vme_xnu_user_debug) &&
16357 (prev_entry->iokit_acct == this_entry->iokit_acct) &&
16358 (prev_entry->vme_resilient_codesign ==
16359 this_entry->vme_resilient_codesign) &&
16360 (prev_entry->vme_resilient_media ==
16361 this_entry->vme_resilient_media) &&
16362 (prev_entry->vme_no_copy_on_read == this_entry->vme_no_copy_on_read) &&
16363 (prev_entry->translated_allow_execute == this_entry->translated_allow_execute) &&
16364
16365 (prev_entry->wired_count == this_entry->wired_count) &&
16366 (prev_entry->user_wired_count == this_entry->user_wired_count) &&
16367
16368 ((prev_entry->vme_atomic == FALSE) && (this_entry->vme_atomic == FALSE)) &&
16369 (prev_entry->in_transition == FALSE) &&
16370 (this_entry->in_transition == FALSE) &&
16371 (prev_entry->needs_wakeup == FALSE) &&
16372 (this_entry->needs_wakeup == FALSE) &&
16373 (prev_entry->is_shared == this_entry->is_shared) &&
16374 (prev_entry->superpage_size == FALSE) &&
16375 (this_entry->superpage_size == FALSE)
16376 ) {
16377 if (prev_entry->vme_permanent) {
16378 assert(this_entry->vme_permanent);
16379 prev_entry->vme_permanent = false;
16380 }
16381 vm_map_store_entry_unlink(map, prev_entry, true);
16382 assert(prev_entry->vme_start < this_entry->vme_end);
16383 assert(VM_MAP_PAGE_ALIGNED(prev_entry->vme_start,
16384 VM_MAP_PAGE_MASK(map)));
16385 this_entry->vme_start = prev_entry->vme_start;
16386 VME_OFFSET_SET(this_entry, VME_OFFSET(prev_entry));
16387
16388 if (map->holelistenabled) {
16389 vm_map_store_update_first_free(map, this_entry, TRUE);
16390 }
16391
16392 if (prev_entry->is_sub_map) {
16393 vm_map_deallocate(VME_SUBMAP(prev_entry));
16394 } else {
16395 vm_object_deallocate(VME_OBJECT(prev_entry));
16396 }
16397 vm_map_entry_dispose(prev_entry);
16398 SAVE_HINT_MAP_WRITE(map, this_entry);
16399 }
16400}
16401
16402void
16403vm_map_simplify(
16404 vm_map_t map,
16405 vm_map_offset_t start)
16406{
16407 vm_map_entry_t this_entry;
16408 vmlp_api_start(VM_MAP_SIMPLIFY);
16409 vm_map_lock(map);
16410 if (vm_map_lookup_entry(map, start, &this_entry)) {
16411 vmlp_range_event_entry(map, this_entry);
16412 vm_map_simplify_entry(map, this_entry);
16413 vmlp_range_event_entry(map, this_entry->vme_next);
16414 vm_map_simplify_entry(map, this_entry->vme_next);
16415 }
16416 vm_map_unlock(map);
16417 vmlp_api_end(VM_MAP_SIMPLIFY, 0);
16418}
16419
16420static void
16421vm_map_simplify_range(
16422 vm_map_t map,
16423 vm_map_offset_t start,
16424 vm_map_offset_t end)
16425{
16426 vm_map_entry_t entry;
16427
16428 /*
16429 * The map should be locked (for "write") by the caller.
16430 */
16431
16432 if (vm_map_is_sealed(map)) {
16433 return;
16434 }
16435
16436 if (start >= end) {
16437 /* invalid address range */
16438 return;
16439 }
16440
16441 start = vm_map_trunc_page(start,
16442 VM_MAP_PAGE_MASK(map));
16443 end = vm_map_round_page(end,
16444 VM_MAP_PAGE_MASK(map));
16445
16446 if (!vm_map_lookup_entry(map, start, &entry)) {
16447 /* "start" is not mapped and "entry" ends before "start" */
16448 if (entry == vm_map_to_entry(map)) {
16449 /* start with first entry in the map */
16450 entry = vm_map_first_entry(map);
16451 } else {
16452 /* start with next entry */
16453 entry = entry->vme_next;
16454 }
16455 }
16456
16457 while (entry != vm_map_to_entry(map) &&
16458 entry->vme_start <= end) {
16459 /* try and coalesce "entry" with its previous entry */
16460 vm_map_simplify_entry(map, entry);
16461 entry = entry->vme_next;
16462 }
16463}
16464
16465static __attribute__((always_inline, warn_unused_result))
16466kern_return_t
16467vm_map_machine_attribute_sanitize(
16468 vm_map_t map,
16469 vm_map_offset_ut start_u,
16470 vm_map_offset_ut end_u,
16471 mach_vm_offset_t *start,
16472 mach_vm_offset_t *end,
16473 vm_map_size_t *size)
16474{
16475 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
16476
16477
16478 return vm_sanitize_addr_end(start_u, end_u,
16479 VM_SANITIZE_CALLER_VM_MAP_MACHINE_ATTRIBUTE, map,
16480 flags, start, end, size);
16481}
16482
16483
16484/*
16485 * Routine: vm_map_machine_attribute
16486 * Purpose:
16487 * Provide machine-specific attributes to mappings,
16488 * such as cachability etc. for machines that provide
16489 * them. NUMA architectures and machines with big/strange
16490 * caches will use this.
16491 * Note:
16492 * Responsibilities for locking and checking are handled here,
16493 * everything else in the pmap module. If any non-volatile
16494 * information must be kept, the pmap module should handle
16495 * it itself. [This assumes that attributes do not
16496 * need to be inherited, which seems ok to me]
16497 */
16498kern_return_t
16499vm_map_machine_attribute(
16500 vm_map_t map,
16501 vm_map_offset_ut start_u,
16502 vm_map_offset_ut end_u,
16503 vm_machine_attribute_t attribute,
16504 vm_machine_attribute_val_t *value) /* IN/OUT */
16505{
16506 mach_vm_offset_t start, end;
16507 vm_map_size_t sync_size;
16508 kern_return_t ret;
16509 vm_map_entry_t entry;
16510
16511 vmlp_api_start(VM_MAP_MACHINE_ATTRIBUTE);
16512
16513 ret = vm_map_machine_attribute_sanitize(map,
16514 start_u,
16515 end_u,
16516 &start,
16517 &end,
16518 &sync_size);
16519 if (__improbable(ret != KERN_SUCCESS)) {
16520 ret = vm_sanitize_get_kr(ret);
16521 vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, ret);
16522 return ret;
16523 }
16524
16525 if (start < vm_map_min(map) || end > vm_map_max(map)) {
16526 vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, KERN_INVALID_ADDRESS);
16527 return KERN_INVALID_ADDRESS;
16528 }
16529
16530 vm_map_lock(map);
16531 vmlp_range_event(map, start, end - start);
16532
16533 if (attribute != MATTR_CACHE) {
16534 /* If we don't have to find physical addresses, we */
16535 /* don't have to do an explicit traversal here. */
16536 ret = pmap_attribute(map->pmap, start, end - start,
16537 attribute, value);
16538 vm_map_unlock(map);
16539 vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, ret);
16540 return ret;
16541 }
16542
16543 ret = KERN_SUCCESS; /* Assume it all worked */
16544
16545 while (sync_size) {
16546 if (vm_map_lookup_entry(map, start, &entry)) {
16547 vm_map_size_t sub_size;
16548 if ((entry->vme_end - start) > sync_size) {
16549 sub_size = sync_size;
16550 sync_size = 0;
16551 } else {
16552 sub_size = entry->vme_end - start;
16553 sync_size -= sub_size;
16554 }
16555 if (entry->is_sub_map) {
16556 vm_map_offset_t sub_start;
16557 vm_map_offset_t sub_end;
16558
16559 sub_start = (start - entry->vme_start)
16560 + VME_OFFSET(entry);
16561 sub_end = sub_start + sub_size;
16562 vm_map_machine_attribute(
16563 VME_SUBMAP(entry),
16564 sub_start,
16565 sub_end,
16566 attribute, value);
16567 } else if (VME_OBJECT(entry)) {
16568 vm_page_t m;
16569 vm_object_t object;
16570 vm_object_t base_object;
16571 vm_object_t last_object;
16572 vm_object_offset_t offset;
16573 vm_object_offset_t base_offset;
16574 vm_map_size_t range;
16575 range = sub_size;
16576 offset = (start - entry->vme_start)
16577 + VME_OFFSET(entry);
16578 offset = vm_object_trunc_page(offset);
16579 base_offset = offset;
16580 object = VME_OBJECT(entry);
16581 base_object = object;
16582 last_object = NULL;
16583
16584 vm_object_lock(object);
16585
16586 while (range) {
16587 m = vm_page_lookup(
16588 object, offset);
16589
16590 if (m && !vm_page_is_fictitious(m)) {
16591 ret =
16592 pmap_attribute_cache_sync(
16593 VM_PAGE_GET_PHYS_PAGE(m),
16594 PAGE_SIZE,
16595 attribute, value);
16596 } else if (object->shadow) {
16597 offset = offset + object->vo_shadow_offset;
16598 last_object = object;
16599 object = object->shadow;
16600 vm_object_lock(last_object->shadow);
16601 vm_object_unlock(last_object);
16602 continue;
16603 }
16604 if (range < PAGE_SIZE) {
16605 range = 0;
16606 } else {
16607 range -= PAGE_SIZE;
16608 }
16609
16610 if (base_object != object) {
16611 vm_object_unlock(object);
16612 vm_object_lock(base_object);
16613 object = base_object;
16614 }
16615 /* Bump to the next page */
16616 base_offset += PAGE_SIZE;
16617 offset = base_offset;
16618 }
16619 vm_object_unlock(object);
16620 }
16621 start += sub_size;
16622 } else {
16623 vm_map_unlock(map);
16624 vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, KERN_FAILURE);
16625 return KERN_FAILURE;
16626 }
16627 }
16628
16629 vm_map_unlock(map);
16630
16631 vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, ret);
16632 return ret;
16633}
16634
16635/*
16636 * vm_map_behavior_set:
16637 *
16638 * Sets the paging reference behavior of the specified address
16639 * range in the target map. Paging reference behavior affects
16640 * how pagein operations resulting from faults on the map will be
16641 * clustered.
16642 */
16643kern_return_t
16644vm_map_behavior_set(
16645 vm_map_t map,
16646 vm_map_offset_t start,
16647 vm_map_offset_t end,
16648 vm_behavior_t new_behavior)
16649{
16650 kern_return_t kr;
16651 vm_map_entry_t entry;
16652 vm_map_entry_t temp_entry;
16653
16654 vmlp_api_start(VM_MAP_BEHAVIOR_SET);
16655 vmlp_range_event(map, start, end - start);
16656
16657 if (start > end ||
16658 start < vm_map_min(map) ||
16659 end > vm_map_max(map)) {
16660 vmlp_api_end(VM_MAP_BEHAVIOR_SET, KERN_NO_SPACE);
16661 return KERN_NO_SPACE;
16662 }
16663 if (__improbable(vm_map_range_overflows(map, start, end - start))) {
16664 vmlp_api_end(VM_MAP_BEHAVIOR_SET, KERN_INVALID_ADDRESS);
16665 return KERN_INVALID_ADDRESS;
16666 }
16667
16668 switch (new_behavior) {
16669 /*
16670 * This first block of behaviors all set a persistent state on the specified
16671 * memory range. All we have to do here is to record the desired behavior
16672 * in the vm_map_entry_t's.
16673 */
16674
16675 case VM_BEHAVIOR_DEFAULT:
16676 case VM_BEHAVIOR_RANDOM:
16677 case VM_BEHAVIOR_SEQUENTIAL:
16678 case VM_BEHAVIOR_RSEQNTL:
16679 case VM_BEHAVIOR_ZERO_WIRED_PAGES:
16680 vm_map_lock(map);
16681
16682 /*
16683 * The entire address range must be valid for the map.
16684 * Note that vm_map_range_check() does a
16685 * vm_map_lookup_entry() internally and returns the
16686 * entry containing the start of the address range if
16687 * the entire range is valid.
16688 */
16689 if (vm_map_range_check(map, start, end, &temp_entry)) {
16690 entry = temp_entry;
16691 vm_map_clip_start(map, entry, start);
16692 } else {
16693 vm_map_unlock(map);
16694 vmlp_api_end(VM_MAP_BEHAVIOR_SET, KERN_INVALID_ADDRESS);
16695 return KERN_INVALID_ADDRESS;
16696 }
16697
16698 if (new_behavior == VM_BEHAVIOR_ZERO_WIRED_PAGES) {
16699 /* zeroing requires write access */
16700 temp_entry = entry;
16701 for (;
16702 entry != vm_map_to_entry(map) && (entry->vme_start < end);
16703 entry = entry->vme_next) {
16704 if (!(entry->protection & VM_PROT_WRITE) ||
16705#if __arm64e__
16706 entry->used_for_tpro ||
16707#endif /* __arm64e__ */
16708 entry->used_for_jit) {
16709 vm_map_unlock(map);
16710 return KERN_PROTECTION_FAILURE;
16711 }
16712 }
16713 entry = temp_entry;
16714 }
16715
16716 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
16717 vm_map_clip_end(map, entry, end);
16718 if (entry->is_sub_map) {
16719 assert(!entry->use_pmap);
16720 }
16721
16722 if (new_behavior == VM_BEHAVIOR_ZERO_WIRED_PAGES) {
16723 assert(entry->protection & VM_PROT_WRITE);
16724#if __arm64e__
16725 assert(!entry->used_for_tpro);
16726#endif /* __arm64e__ */
16727 assert(!entry->used_for_jit);
16728 entry->zero_wired_pages = TRUE;
16729 } else {
16730 entry->behavior = new_behavior;
16731 }
16732 entry = entry->vme_next;
16733 }
16734
16735 vm_map_unlock(map);
16736 kr = KERN_SUCCESS;
16737 break;
16738
16739 /*
16740 * The rest of these are different from the above in that they cause
16741 * an immediate action to take place as opposed to setting a behavior that
16742 * affects future actions.
16743 */
16744
16745 case VM_BEHAVIOR_WILLNEED:
16746 kr = vm_map_willneed(map, start, end);
16747 break;
16748
16749 case VM_BEHAVIOR_DONTNEED:
16750 kr = vm_map_msync(map, start, end - start, VM_SYNC_DEACTIVATE | VM_SYNC_CONTIGUOUS);
16751 break;
16752
16753 case VM_BEHAVIOR_FREE:
16754 kr = vm_map_msync(map, start, end - start, VM_SYNC_KILLPAGES | VM_SYNC_CONTIGUOUS);
16755 break;
16756
16757 case VM_BEHAVIOR_REUSABLE:
16758 kr = vm_map_reusable_pages(map, start, end);
16759 break;
16760
16761 case VM_BEHAVIOR_REUSE:
16762 kr = vm_map_reuse_pages(map, start, end);
16763 break;
16764
16765 case VM_BEHAVIOR_CAN_REUSE:
16766 kr = vm_map_can_reuse(map, start, end);
16767 break;
16768
16769#if MACH_ASSERT
16770 case VM_BEHAVIOR_PAGEOUT:
16771 kr = vm_map_pageout(map, start, end);
16772 break;
16773#endif /* MACH_ASSERT */
16774
16775 case VM_BEHAVIOR_ZERO:
16776 kr = vm_map_zero(map, start, end);
16777 break;
16778
16779 default:
16780 kr = KERN_INVALID_ARGUMENT;
16781 break;
16782 }
16783
16784 vmlp_api_end(VM_MAP_BEHAVIOR_SET, kr);
16785 return kr;
16786}
16787
16788
16789/*
16790 * Internals for madvise(MADV_WILLNEED) system call.
16791 *
16792 * The implementation is to do:-
16793 * a) read-ahead if the mapping corresponds to a mapped regular file
16794 * b) or, fault in the pages (zero-fill, decompress etc) if it's an anonymous mapping
16795 */
16796static kern_return_t
16797vm_map_willneed(
16798 vm_map_t map,
16799 vm_map_offset_t start,
16800 vm_map_offset_t end
16801 )
16802{
16803 vm_map_entry_t entry;
16804 kern_return_t kr;
16805 vm_object_size_t len;
16806 vm_size_t region_size;
16807
16808 vmlp_api_start(VM_MAP_WILLNEED);
16809
16810 KDBG(VMDBG_CODE(DBG_VM_MAP_WILLNEED) | DBG_FUNC_START,
16811 start, end);
16812 struct vm_object_fault_info fault_info = {
16813 .interruptible = THREAD_UNINT,
16814 .behavior = VM_BEHAVIOR_SEQUENTIAL,
16815 /* Do not activate pages after faulting */
16816 .stealth = true,
16817 /* Don't wait for busy pages */
16818 .fi_no_sleep = true,
16819 };
16820
16821 /*
16822 * The MADV_WILLNEED operation doesn't require any changes to the
16823 * vm_map_entry_t's, so the read lock is sufficient.
16824 */
16825
16826 vm_map_lock_read(map);
16827
16828 vmlp_range_event(map, start, end);
16829
16830 /*
16831 * The madvise semantics require that the address range be fully
16832 * allocated with no holes. Otherwise, we're required to return
16833 * an error.
16834 */
16835
16836 if (!vm_map_range_check(map, start, end, &entry)) {
16837 vm_map_unlock_read(map);
16838 kr = KERN_INVALID_ADDRESS;
16839 goto done;
16840 }
16841
16842 /*
16843 * Examine each vm_map_entry_t in the range.
16844 */
16845 while (start < end) {
16846 /*
16847 * Set the length so we don't go beyond the end of the
16848 * map_entry or beyond the end of the range we were given.
16849 * This range could span also multiple map entries all of which
16850 * map different files, so make sure we only do the right amount
16851 * of I/O for each object. Note that it's possible for there
16852 * to be multiple map entries all referring to the same object
16853 * but with different page permissions, but it's not worth
16854 * trying to optimize that case.
16855 */
16856 len = MIN(entry->vme_end - start, end - start);
16857
16858 vm_map_offset_t addr = start;
16859
16860 vm_size_t effective_page_mask = MIN(vm_map_page_mask(map), PAGE_MASK);
16861 vm_map_offset_t effective_page_size = effective_page_mask + 1;
16862
16863 /*
16864 * Write-fault if the entry supports it to preclude subsequent soft-faults
16865 */
16866 vm_prot_t fault_prot = entry->protection & VM_PROT_WRITE ?
16867 VM_PROT_WRITE : VM_PROT_READ;
16868
16869 vm_map_unlock_read(map);
16870
16871 region_size = len;
16872 while (region_size) {
16873 /*
16874 * Provide a hint for how much clustering we would like. Note that
16875 * each individual fault will limit the size of each request to
16876 * MAX_UPL_TRANSFER_BYTES.
16877 */
16878 fault_info.cluster_size = region_size;
16879 kr = vm_pre_fault_with_info(
16880 map,
16881 vm_map_trunc_page(addr, effective_page_mask),
16882 fault_prot,
16883 &fault_info);
16884 if (kr == KERN_ALREADY_WAITING) {
16885 /*
16886 * The page is busy being faulted/paged by another thread.
16887 */
16888 KDBG(VMDBG_CODE(DBG_VM_MAP_WILLNEED) | DBG_FUNC_NONE,
16889 task_pid(current_task()), addr, kr);
16890 kr = KERN_SUCCESS;
16891 } else if (kr != KERN_SUCCESS) {
16892 goto done;
16893 }
16894 region_size -= effective_page_size;
16895 addr += effective_page_size;
16896 }
16897
16898 start += len;
16899 if (start >= end) {
16900 kr = KERN_SUCCESS;
16901 goto done;
16902 }
16903
16904 if (thread_should_abort(current_thread())) {
16905 kr = KERN_ABORTED;
16906 goto done;
16907 }
16908
16909 /* look up next entry */
16910 vm_map_lock_read(map);
16911 if (!vm_map_lookup_entry(map, start, &entry)) {
16912 /*
16913 * There's a new hole in the address range.
16914 */
16915 vm_map_unlock_read(map);
16916 kr = KERN_INVALID_ADDRESS;
16917 goto done;
16918 }
16919 }
16920
16921 vm_map_unlock_read(map);
16922done:
16923 KDBG(VMDBG_CODE(DBG_VM_MAP_WILLNEED) | DBG_FUNC_END,
16924 start, kr);
16925 vmlp_api_end(VM_MAP_WILLNEED, kr);
16926 return kr;
16927}
16928
16929static boolean_t
16930vm_map_entry_is_reusable(
16931 vm_map_entry_t entry)
16932{
16933 vm_object_t object;
16934
16935 /* Only user map entries */
16936 if (entry->is_sub_map) {
16937 return FALSE;
16938 }
16939
16940 switch (VME_ALIAS(entry)) {
16941 case VM_MEMORY_MALLOC:
16942 case VM_MEMORY_MALLOC_SMALL:
16943 case VM_MEMORY_MALLOC_LARGE:
16944 case VM_MEMORY_REALLOC:
16945 case VM_MEMORY_MALLOC_TINY:
16946 case VM_MEMORY_MALLOC_LARGE_REUSABLE:
16947 case VM_MEMORY_MALLOC_LARGE_REUSED:
16948 /*
16949 * This is a malloc() memory region: check if it's still
16950 * in its original state and can be re-used for more
16951 * malloc() allocations.
16952 */
16953 break;
16954 default:
16955 /*
16956 * Not a malloc() memory region: let the caller decide if
16957 * it's re-usable.
16958 */
16959 return TRUE;
16960 }
16961
16962 if (/*entry->is_shared ||*/
16963 entry->is_sub_map ||
16964 entry->in_transition ||
16965 entry->protection != VM_PROT_DEFAULT ||
16966 entry->max_protection != VM_PROT_ALL ||
16967 entry->inheritance != VM_INHERIT_DEFAULT ||
16968 entry->no_cache ||
16969 entry->vme_permanent ||
16970 entry->superpage_size != FALSE ||
16971 entry->zero_wired_pages ||
16972 entry->wired_count != 0 ||
16973 entry->user_wired_count != 0) {
16974 return FALSE;
16975 }
16976
16977 object = VME_OBJECT(entry);
16978 if (object == VM_OBJECT_NULL) {
16979 return TRUE;
16980 }
16981 if (
16982#if 0
16983 /*
16984 * Let's proceed even if the VM object is potentially
16985 * shared.
16986 * We check for this later when processing the actual
16987 * VM pages, so the contents will be safe if shared.
16988 *
16989 * But we can still mark this memory region as "reusable" to
16990 * acknowledge that the caller did let us know that the memory
16991 * could be re-used and should not be penalized for holding
16992 * on to it. This allows its "resident size" to not include
16993 * the reusable range.
16994 */
16995 object->ref_count == 1 &&
16996#endif
16997 object->vo_copy == VM_OBJECT_NULL &&
16998 object->shadow == VM_OBJECT_NULL &&
16999 object->internal &&
17000 object->purgable == VM_PURGABLE_DENY &&
17001 HAS_DEFAULT_CACHEABILITY(object->wimg_bits & VM_WIMG_MASK) &&
17002 !object->code_signed) {
17003 return TRUE;
17004 }
17005 return FALSE;
17006}
17007
17008static kern_return_t
17009vm_map_reuse_pages(
17010 vm_map_t map,
17011 vm_map_offset_t start,
17012 vm_map_offset_t end)
17013{
17014 vm_map_entry_t entry;
17015 vm_object_t object;
17016 vm_object_offset_t start_offset, end_offset;
17017
17018 vmlp_api_start(VM_MAP_REUSE_PAGES);
17019
17020 /*
17021 * The MADV_REUSE operation doesn't require any changes to the
17022 * vm_map_entry_t's, so the read lock is sufficient.
17023 */
17024
17025 if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) {
17026 /*
17027 * XXX TODO4K
17028 * need to figure out what reusable means for a
17029 * portion of a native page.
17030 */
17031 vmlp_api_end(VM_MAP_REUSE_PAGES, KERN_SUCCESS);
17032 return KERN_SUCCESS;
17033 }
17034
17035 vm_map_lock_read(map);
17036 assert(map->pmap != kernel_pmap); /* protect alias access */
17037
17038 /*
17039 * The madvise semantics require that the address range be fully
17040 * allocated with no holes. Otherwise, we're required to return
17041 * an error.
17042 */
17043
17044 if (!vm_map_range_check(map, start, end, &entry)) {
17045 vm_map_unlock_read(map);
17046 vm_page_stats_reusable.reuse_pages_failure++;
17047 vmlp_api_end(VM_MAP_REUSE_PAGES, KERN_INVALID_ADDRESS);
17048 return KERN_INVALID_ADDRESS;
17049 }
17050
17051 vmlp_range_event(map, start, end - start);
17052
17053 /*
17054 * Examine each vm_map_entry_t in the range.
17055 */
17056 for (; entry != vm_map_to_entry(map) && entry->vme_start < end;
17057 entry = entry->vme_next) {
17058 /*
17059 * Sanity check on the VM map entry.
17060 */
17061 if (!vm_map_entry_is_reusable(entry)) {
17062 vm_map_unlock_read(map);
17063 vm_page_stats_reusable.reuse_pages_failure++;
17064 vmlp_api_end(VM_MAP_REUSE_PAGES, KERN_INVALID_ADDRESS);
17065 return KERN_INVALID_ADDRESS;
17066 }
17067
17068 /*
17069 * The first time through, the start address could be anywhere
17070 * within the vm_map_entry we found. So adjust the offset to
17071 * correspond.
17072 */
17073 if (entry->vme_start < start) {
17074 start_offset = start - entry->vme_start;
17075 } else {
17076 start_offset = 0;
17077 }
17078 end_offset = MIN(end, entry->vme_end) - entry->vme_start;
17079 start_offset += VME_OFFSET(entry);
17080 end_offset += VME_OFFSET(entry);
17081
17082 object = VME_OBJECT(entry);
17083 if (object != VM_OBJECT_NULL) {
17084 vm_object_lock(object);
17085 vm_object_reuse_pages(object, start_offset, end_offset,
17086 TRUE);
17087 vm_object_unlock(object);
17088 }
17089
17090 if (VME_ALIAS(entry) == VM_MEMORY_MALLOC_LARGE_REUSABLE) {
17091 /*
17092 * XXX
17093 * We do not hold the VM map exclusively here.
17094 * The "alias" field is not that critical, so it's
17095 * safe to update it here, as long as it is the only
17096 * one that can be modified while holding the VM map
17097 * "shared".
17098 */
17099 VME_ALIAS_SET(entry, VM_MEMORY_MALLOC_LARGE_REUSED);
17100 }
17101 }
17102
17103 vm_map_unlock_read(map);
17104 vm_page_stats_reusable.reuse_pages_success++;
17105 vmlp_api_end(VM_MAP_REUSE_PAGES, KERN_SUCCESS);
17106 return KERN_SUCCESS;
17107}
17108
17109
17110static kern_return_t
17111vm_map_reusable_pages(
17112 vm_map_t map,
17113 vm_map_offset_t start,
17114 vm_map_offset_t end)
17115{
17116 vm_map_entry_t entry;
17117 vm_object_t object;
17118 vm_object_offset_t start_offset, end_offset;
17119 vm_map_offset_t pmap_offset;
17120
17121 vmlp_api_start(VM_MAP_REUSABLE_PAGES);
17122
17123 if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) {
17124 /*
17125 * XXX TODO4K
17126 * need to figure out what reusable means for a portion
17127 * of a native page.
17128 */
17129 vmlp_api_end(VM_MAP_REUSABLE_PAGES, KERN_SUCCESS);
17130 return KERN_SUCCESS;
17131 }
17132
17133 /*
17134 * The MADV_REUSABLE operation doesn't require any changes to the
17135 * vm_map_entry_t's, so the read lock is sufficient.
17136 */
17137
17138 vm_map_lock_read(map);
17139 assert(map->pmap != kernel_pmap); /* protect alias access */
17140
17141 /*
17142 * The madvise semantics require that the address range be fully
17143 * allocated with no holes. Otherwise, we're required to return
17144 * an error.
17145 */
17146
17147 if (!vm_map_range_check(map, start, end, &entry)) {
17148 vm_map_unlock_read(map);
17149 vm_page_stats_reusable.reusable_pages_failure++;
17150 vmlp_api_end(VM_MAP_REUSABLE_PAGES, KERN_INVALID_ADDRESS);
17151 return KERN_INVALID_ADDRESS;
17152 }
17153
17154 vmlp_range_event(map, start, end - start);
17155
17156 /*
17157 * Examine each vm_map_entry_t in the range.
17158 */
17159 for (; entry != vm_map_to_entry(map) && entry->vme_start < end;
17160 entry = entry->vme_next) {
17161 int kill_pages = 0;
17162 boolean_t kill_no_write = FALSE;
17163
17164 /*
17165 * Sanity check on the VM map entry.
17166 */
17167 if (!vm_map_entry_is_reusable(entry)) {
17168 vm_map_unlock_read(map);
17169 vm_page_stats_reusable.reusable_pages_failure++;
17170 vmlp_api_end(VM_MAP_REUSABLE_PAGES, KERN_INVALID_ADDRESS);
17171 return KERN_INVALID_ADDRESS;
17172 }
17173
17174 if (!(entry->protection & VM_PROT_WRITE) && !entry->used_for_jit
17175#if __arm64e__
17176 && !entry->used_for_tpro
17177#endif
17178 ) {
17179 /* not writable: can't discard contents */
17180 vm_map_unlock_read(map);
17181 vm_page_stats_reusable.reusable_nonwritable++;
17182 vm_page_stats_reusable.reusable_pages_failure++;
17183 vmlp_api_end(VM_MAP_REUSABLE_PAGES, KERN_PROTECTION_FAILURE);
17184 return KERN_PROTECTION_FAILURE;
17185 }
17186
17187 /*
17188 * The first time through, the start address could be anywhere
17189 * within the vm_map_entry we found. So adjust the offset to
17190 * correspond.
17191 */
17192 if (entry->vme_start < start) {
17193 start_offset = start - entry->vme_start;
17194 pmap_offset = start;
17195 } else {
17196 start_offset = 0;
17197 pmap_offset = entry->vme_start;
17198 }
17199 end_offset = MIN(end, entry->vme_end) - entry->vme_start;
17200 start_offset += VME_OFFSET(entry);
17201 end_offset += VME_OFFSET(entry);
17202
17203 object = VME_OBJECT(entry);
17204 if (object == VM_OBJECT_NULL) {
17205 continue;
17206 }
17207
17208 if ((entry->protection & VM_PROT_EXECUTE) ||
17209 entry->vme_xnu_user_debug) {
17210 /*
17211 * Executable or user debug pages might be write-protected by
17212 * hardware, so do not attempt to write to these pages.
17213 */
17214 kill_no_write = TRUE;
17215 }
17216
17217 vm_object_lock(object);
17218 if (((os_ref_get_count_raw(&object->ref_count) == 1) ||
17219 (object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC &&
17220 object->vo_copy == VM_OBJECT_NULL)) &&
17221 object->shadow == VM_OBJECT_NULL &&
17222 /*
17223 * "iokit_acct" entries are billed for their virtual size
17224 * (rather than for their resident pages only), so they
17225 * wouldn't benefit from making pages reusable, and it
17226 * would be hard to keep track of pages that are both
17227 * "iokit_acct" and "reusable" in the pmap stats and
17228 * ledgers.
17229 */
17230 !(entry->iokit_acct ||
17231 (!entry->is_sub_map && !entry->use_pmap))) {
17232 if (os_ref_get_count_raw(&object->ref_count) != 1) {
17233 vm_page_stats_reusable.reusable_shared++;
17234 }
17235 kill_pages = 1;
17236 } else {
17237 kill_pages = -1;
17238 }
17239 if (kill_pages != -1) {
17240 vm_object_deactivate_pages(object,
17241 start_offset,
17242 end_offset - start_offset,
17243 kill_pages,
17244 TRUE /*reusable_pages*/,
17245 kill_no_write,
17246 map->pmap,
17247 pmap_offset);
17248 } else {
17249 vm_page_stats_reusable.reusable_pages_shared++;
17250 DTRACE_VM4(vm_map_reusable_pages_shared,
17251 unsigned int, VME_ALIAS(entry),
17252 vm_map_t, map,
17253 vm_map_entry_t, entry,
17254 vm_object_t, object);
17255 }
17256 vm_object_unlock(object);
17257
17258 if (VME_ALIAS(entry) == VM_MEMORY_MALLOC_LARGE ||
17259 VME_ALIAS(entry) == VM_MEMORY_MALLOC_LARGE_REUSED) {
17260 /*
17261 * XXX
17262 * We do not hold the VM map exclusively here.
17263 * The "alias" field is not that critical, so it's
17264 * safe to update it here, as long as it is the only
17265 * one that can be modified while holding the VM map
17266 * "shared".
17267 */
17268 VME_ALIAS_SET(entry, VM_MEMORY_MALLOC_LARGE_REUSABLE);
17269 }
17270 }
17271
17272 vm_map_unlock_read(map);
17273 vm_page_stats_reusable.reusable_pages_success++;
17274 vmlp_api_end(VM_MAP_REUSABLE_PAGES, KERN_SUCCESS);
17275 return KERN_SUCCESS;
17276}
17277
17278
17279static kern_return_t
17280vm_map_can_reuse(
17281 vm_map_t map,
17282 vm_map_offset_t start,
17283 vm_map_offset_t end)
17284{
17285 vm_map_entry_t entry;
17286
17287 vmlp_api_start(VM_MAP_CAN_REUSE);
17288 vmlp_range_event(map, start, end - start);
17289
17290 /*
17291 * The MADV_REUSABLE operation doesn't require any changes to the
17292 * vm_map_entry_t's, so the read lock is sufficient.
17293 */
17294
17295 vm_map_lock_read(map);
17296 assert(map->pmap != kernel_pmap); /* protect alias access */
17297
17298 /*
17299 * The madvise semantics require that the address range be fully
17300 * allocated with no holes. Otherwise, we're required to return
17301 * an error.
17302 */
17303
17304 if (!vm_map_range_check(map, start, end, &entry)) {
17305 vm_map_unlock_read(map);
17306 vm_page_stats_reusable.can_reuse_failure++;
17307 vmlp_api_end(VM_MAP_CAN_REUSE, KERN_INVALID_ADDRESS);
17308 return KERN_INVALID_ADDRESS;
17309 }
17310
17311 /*
17312 * Examine each vm_map_entry_t in the range.
17313 */
17314 for (; entry != vm_map_to_entry(map) && entry->vme_start < end;
17315 entry = entry->vme_next) {
17316 /*
17317 * Sanity check on the VM map entry.
17318 */
17319 if (!vm_map_entry_is_reusable(entry)) {
17320 vm_map_unlock_read(map);
17321 vm_page_stats_reusable.can_reuse_failure++;
17322 vmlp_api_end(VM_MAP_CAN_REUSE, KERN_INVALID_ADDRESS);
17323 return KERN_INVALID_ADDRESS;
17324 }
17325 }
17326
17327 vm_map_unlock_read(map);
17328 vm_page_stats_reusable.can_reuse_success++;
17329 vmlp_api_end(VM_MAP_CAN_REUSE, KERN_SUCCESS);
17330 return KERN_SUCCESS;
17331}
17332
17333
17334#if MACH_ASSERT
17335static kern_return_t
17336vm_map_pageout(
17337 vm_map_t map,
17338 vm_map_offset_t start,
17339 vm_map_offset_t end)
17340{
17341 vm_map_entry_t entry;
17342
17343 vmlp_api_start(VM_MAP_PAGEOUT);
17344
17345 /*
17346 * The MADV_PAGEOUT operation doesn't require any changes to the
17347 * vm_map_entry_t's, so the read lock is sufficient.
17348 */
17349
17350 vm_map_lock_read(map);
17351 vmlp_range_event(map, start, end - start);
17352
17353 /*
17354 * The madvise semantics require that the address range be fully
17355 * allocated with no holes. Otherwise, we're required to return
17356 * an error.
17357 */
17358
17359 if (!vm_map_range_check(map, start, end, &entry)) {
17360 vm_map_unlock_read(map);
17361 vmlp_api_end(VM_MAP_PAGEOUT, KERN_INVALID_ADDRESS);
17362 return KERN_INVALID_ADDRESS;
17363 }
17364
17365 /*
17366 * Examine each vm_map_entry_t in the range.
17367 */
17368 for (; entry != vm_map_to_entry(map) && entry->vme_start < end;
17369 entry = entry->vme_next) {
17370 vm_object_t object;
17371
17372 /*
17373 * Sanity check on the VM map entry.
17374 */
17375 if (entry->is_sub_map) {
17376 vm_map_t submap;
17377 vm_map_offset_t submap_start;
17378 vm_map_offset_t submap_end;
17379 vm_map_entry_t submap_entry;
17380
17381 submap = VME_SUBMAP(entry);
17382 submap_start = VME_OFFSET(entry);
17383 submap_end = submap_start + (entry->vme_end -
17384 entry->vme_start);
17385
17386 vm_map_lock_read(submap);
17387
17388 if (!vm_map_range_check(submap,
17389 submap_start,
17390 submap_end,
17391 &submap_entry)) {
17392 vm_map_unlock_read(submap);
17393 vm_map_unlock_read(map);
17394 vmlp_api_end(VM_MAP_PAGEOUT, KERN_INVALID_ADDRESS);
17395 return KERN_INVALID_ADDRESS;
17396 }
17397
17398 if (submap_entry->is_sub_map) {
17399 vm_map_unlock_read(submap);
17400 continue;
17401 }
17402
17403 object = VME_OBJECT(submap_entry);
17404 if (object == VM_OBJECT_NULL || !object->internal) {
17405 vm_map_unlock_read(submap);
17406 continue;
17407 }
17408
17409 vm_object_pageout(object);
17410
17411 vm_map_unlock_read(submap);
17412 submap = VM_MAP_NULL;
17413 submap_entry = VM_MAP_ENTRY_NULL;
17414 continue;
17415 }
17416
17417 object = VME_OBJECT(entry);
17418 if (object == VM_OBJECT_NULL || !object->internal) {
17419 continue;
17420 }
17421
17422 vm_object_pageout(object);
17423 }
17424
17425 vm_map_unlock_read(map);
17426 vmlp_api_end(VM_MAP_PAGEOUT, KERN_SUCCESS);
17427 return KERN_SUCCESS;
17428}
17429#endif /* MACH_ASSERT */
17430
17431/*
17432 * This function determines if the zero operation can be run on the
17433 * respective entry. Additional checks on the object are in
17434 * vm_object_zero_preflight.
17435 */
17436static kern_return_t
17437vm_map_zero_entry_preflight(vm_map_entry_t entry)
17438{
17439 /*
17440 * Zeroing is restricted to writable non-executable entries and non-JIT
17441 * regions.
17442 */
17443 if (!(entry->protection & VM_PROT_WRITE) ||
17444 (entry->protection & VM_PROT_EXECUTE) ||
17445 entry->used_for_jit ||
17446 entry->vme_xnu_user_debug) {
17447 return KERN_PROTECTION_FAILURE;
17448 }
17449
17450 /*
17451 * Zeroing for copy on write isn't yet supported. Zeroing is also not
17452 * allowed for submaps.
17453 */
17454 if (entry->needs_copy || entry->is_sub_map) {
17455 return KERN_NO_ACCESS;
17456 }
17457
17458 return KERN_SUCCESS;
17459}
17460
17461/*
17462 * This function translates entry's start and end to offsets in the object
17463 */
17464static void
17465vm_map_get_bounds_in_object(
17466 vm_map_entry_t entry,
17467 vm_map_offset_t start,
17468 vm_map_offset_t end,
17469 vm_map_offset_t *start_offset,
17470 vm_map_offset_t *end_offset)
17471{
17472 if (entry->vme_start < start) {
17473 *start_offset = start - entry->vme_start;
17474 } else {
17475 *start_offset = 0;
17476 }
17477 *end_offset = MIN(end, entry->vme_end) - entry->vme_start;
17478 *start_offset += VME_OFFSET(entry);
17479 *end_offset += VME_OFFSET(entry);
17480}
17481
17482/*
17483 * This function iterates through the entries in the requested range
17484 * and zeroes any resident pages in the corresponding objects. Compressed
17485 * pages are dropped instead of being faulted in and zeroed.
17486 */
17487static kern_return_t
17488vm_map_zero(
17489 vm_map_t map,
17490 vm_map_offset_t start,
17491 vm_map_offset_t end)
17492{
17493 vm_map_entry_t entry;
17494 vm_map_offset_t cur = start;
17495 kern_return_t ret;
17496
17497 vmlp_api_start(VM_MAP_ZERO);
17498
17499 /*
17500 * This operation isn't supported where the map page size is less than
17501 * the hardware page size. Caller will need to handle error and
17502 * explicitly zero memory if needed.
17503 */
17504 if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) {
17505 vmlp_api_end(VM_MAP_ZERO, KERN_NO_ACCESS);
17506 return KERN_NO_ACCESS;
17507 }
17508
17509 /*
17510 * The MADV_ZERO operation doesn't require any changes to the
17511 * vm_map_entry_t's, so the read lock is sufficient.
17512 */
17513 vm_map_lock_read(map);
17514 assert(map->pmap != kernel_pmap); /* protect alias access */
17515
17516 vmlp_range_event(map, start, end - start);
17517
17518 /*
17519 * The madvise semantics require that the address range be fully
17520 * allocated with no holes. Otherwise, we're required to return
17521 * an error. This check needs to be redone if the map has changed.
17522 */
17523 if (!vm_map_range_check(map, cur, end, &entry)) {
17524 vm_map_unlock_read(map);
17525 vmlp_api_end(VM_MAP_ZERO, KERN_INVALID_ADDRESS);
17526 return KERN_INVALID_ADDRESS;
17527 }
17528
17529 /*
17530 * Examine each vm_map_entry_t in the range.
17531 */
17532 while (entry != vm_map_to_entry(map) && entry->vme_start < end) {
17533 vm_map_offset_t start_offset;
17534 vm_map_offset_t cur_offset;
17535 vm_map_offset_t end_offset;
17536 unsigned int last_timestamp = map->timestamp;
17537 vm_object_t object;
17538
17539 ret = vm_map_zero_entry_preflight(entry);
17540 if (ret != KERN_SUCCESS) {
17541 vm_map_unlock_read(map);
17542 vmlp_api_end(VM_MAP_ZERO, ret);
17543 return ret;
17544 }
17545
17546 object = VME_OBJECT(entry);
17547 if (object == VM_OBJECT_NULL) {
17548 entry = entry->vme_next;
17549 continue;
17550 }
17551
17552 vm_map_get_bounds_in_object(entry, cur, end, &start_offset, &end_offset);
17553 vm_object_lock(object);
17554 /*
17555 * Take a reference on the object as vm_object_zero will drop the object
17556 * lock when it encounters a busy page.
17557 */
17558 vm_object_reference_locked(object);
17559 vm_map_unlock_read(map);
17560
17561 cur_offset = start_offset;
17562 ret = vm_object_zero(object, &cur_offset, end_offset);
17563 vm_object_unlock(object);
17564 vm_object_deallocate(object);
17565 if (ret != KERN_SUCCESS) {
17566 vmlp_api_end(VM_MAP_ZERO, ret);
17567 return ret;
17568 }
17569 /*
17570 * Update cur as vm_object_zero has succeeded.
17571 * It can bail out early if it had to unlock a COPY_SYMMETRIC object, so
17572 * the processed range is [start_offset:cur_offset).
17573 * If the mapping became "needs_copy" while the object (and the map) was
17574 * unlocked, we'll detect that the map has changed while unlocked
17575 * and we'll redo the lookup and preflight for the remaining range.
17576 */
17577 cur += (cur_offset - start_offset);
17578 if (cur == end) {
17579 vmlp_api_end(VM_MAP_ZERO, KERN_SUCCESS);
17580 return KERN_SUCCESS;
17581 }
17582
17583 /*
17584 * If the map timestamp has changed, restart by relooking up cur in the
17585 * map.
17586 * We also need to re-lookup the entry if we did not fully process
17587 * this entry (i.e. cur_offset did not reach end_offset).
17588 */
17589 vm_map_lock_read(map);
17590 if (last_timestamp != map->timestamp ||
17591 cur_offset < end_offset) {
17592 /*
17593 * Relookup cur in the map
17594 */
17595 if (!vm_map_range_check(map, cur, end, &entry)) {
17596 vm_map_unlock_read(map);
17597 vmlp_api_end(VM_MAP_ZERO, KERN_INVALID_ADDRESS);
17598 return KERN_INVALID_ADDRESS;
17599 }
17600 continue;
17601 }
17602 /*
17603 * If the map hasn't changed proceed with the next entry
17604 */
17605 entry = entry->vme_next;
17606 }
17607
17608 vm_map_unlock_read(map);
17609 vmlp_api_end(VM_MAP_ZERO, KERN_SUCCESS);
17610 return KERN_SUCCESS;
17611}
17612
17613
17614/*
17615 * Routine: vm_map_entry_insert
17616 *
17617 * Description: This routine inserts a new vm_entry in a locked map.
17618 */
17619static vm_map_entry_t
17620vm_map_entry_insert(
17621 vm_map_t map,
17622 vm_map_entry_t insp_entry,
17623 vm_map_offset_t start,
17624 vm_map_offset_t end,
17625 vm_object_t object,
17626 vm_object_offset_t offset,
17627 vm_map_kernel_flags_t vmk_flags,
17628 boolean_t needs_copy,
17629 vm_prot_t cur_protection,
17630 vm_prot_t max_protection,
17631 vm_inherit_t inheritance)
17632{
17633 vm_map_entry_t new_entry;
17634
17635 assert(insp_entry != (vm_map_entry_t)0);
17636 vm_map_lock_assert_exclusive(map);
17637
17638 __assert_only vm_object_offset_t end_offset = 0;
17639 assertf(!os_add_overflow(end - start, offset, &end_offset), "size 0x%llx, offset 0x%llx caused overflow", (uint64_t)(end - start), offset);
17640
17641 assert(VM_MAP_PAGE_ALIGNED(start, VM_MAP_PAGE_MASK(map)));
17642 assert(VM_MAP_PAGE_ALIGNED(end, VM_MAP_PAGE_MASK(map)));
17643 assert(start < end);
17644
17645 new_entry = vm_map_entry_create(map);
17646
17647 new_entry->vme_start = start;
17648 new_entry->vme_end = end;
17649
17650 if (vmk_flags.vmkf_submap) {
17651 new_entry->vme_atomic = vmk_flags.vmkf_submap_atomic;
17652 VME_SUBMAP_SET(new_entry, (vm_map_t)object);
17653 } else {
17654 VME_OBJECT_SET(new_entry, object, false, 0);
17655 }
17656 VME_OFFSET_SET(new_entry, offset);
17657 VME_ALIAS_SET(new_entry, vmk_flags.vm_tag);
17658
17659 new_entry->needs_copy = needs_copy;
17660 new_entry->inheritance = inheritance;
17661 new_entry->protection = cur_protection;
17662 new_entry->max_protection = max_protection;
17663 /*
17664 * submap: "use_pmap" means "nested".
17665 * default: false.
17666 *
17667 * object: "use_pmap" means "use pmap accounting" for footprint.
17668 * default: true.
17669 */
17670 new_entry->use_pmap = !vmk_flags.vmkf_submap;
17671 new_entry->no_cache = vmk_flags.vmf_no_cache;
17672 new_entry->vme_permanent = vmk_flags.vmf_permanent;
17673 new_entry->translated_allow_execute = vmk_flags.vmkf_translated_allow_execute;
17674 new_entry->vme_no_copy_on_read = vmk_flags.vmkf_no_copy_on_read;
17675 new_entry->superpage_size = (vmk_flags.vmf_superpage_size != 0);
17676
17677 if (vmk_flags.vmkf_map_jit) {
17678 if (!(map->jit_entry_exists) ||
17679 VM_MAP_POLICY_ALLOW_MULTIPLE_JIT(map)) {
17680 new_entry->used_for_jit = TRUE;
17681 map->jit_entry_exists = TRUE;
17682 }
17683 }
17684
17685 /*
17686 * Insert the new entry into the list.
17687 */
17688
17689 vm_map_store_entry_link(map, insp_entry, new_entry, vmk_flags);
17690 map->size += end - start;
17691
17692 /*
17693 * Update the free space hint and the lookup hint.
17694 */
17695
17696 SAVE_HINT_MAP_WRITE(map, new_entry);
17697 return new_entry;
17698}
17699
17700/*
17701 * Routine: vm_map_remap_extract
17702 *
17703 * Description: This routine returns a vm_entry list from a map.
17704 */
17705static kern_return_t
17706vm_map_remap_extract(
17707 vm_map_t map,
17708 vm_map_offset_t addr,
17709 vm_map_size_t size,
17710 boolean_t copy,
17711 vm_map_copy_t map_copy,
17712 vm_prot_t *cur_protection, /* IN/OUT */
17713 vm_prot_t *max_protection, /* IN/OUT */
17714 /* What, no behavior? */
17715 vm_inherit_t inheritance,
17716 vm_map_kernel_flags_t vmk_flags)
17717{
17718 struct vm_map_header *map_header = &map_copy->cpy_hdr;
17719 kern_return_t result;
17720 vm_map_size_t mapped_size;
17721 vm_map_size_t tmp_size;
17722 vm_map_entry_t src_entry; /* result of last map lookup */
17723 vm_map_entry_t new_entry;
17724 vm_object_offset_t offset;
17725 vm_map_offset_t map_address;
17726 vm_map_offset_t src_start; /* start of entry to map */
17727 vm_map_offset_t src_end; /* end of region to be mapped */
17728 vm_object_t object;
17729 vm_map_version_t version;
17730 boolean_t src_needs_copy;
17731 boolean_t new_entry_needs_copy;
17732 vm_map_entry_t saved_src_entry;
17733 boolean_t src_entry_was_wired;
17734 vm_prot_t max_prot_for_prot_copy;
17735 vm_map_offset_t effective_page_mask;
17736 bool pageable, same_map;
17737 boolean_t vm_remap_legacy;
17738 vm_prot_t required_cur_prot, required_max_prot;
17739 vm_object_t new_copy_object; /* vm_object_copy_* result */
17740 boolean_t saved_used_for_jit; /* Saved used_for_jit. */
17741
17742 vmlp_api_start(VM_MAP_REMAP_EXTRACT);
17743
17744 pageable = vmk_flags.vmkf_copy_pageable;
17745 same_map = vmk_flags.vmkf_copy_same_map;
17746
17747 effective_page_mask = MIN(PAGE_MASK, VM_MAP_PAGE_MASK(map));
17748
17749 assert(map != VM_MAP_NULL);
17750 assert(size != 0);
17751 assert(size == vm_map_round_page(size, effective_page_mask));
17752 assert(inheritance == VM_INHERIT_NONE ||
17753 inheritance == VM_INHERIT_COPY ||
17754 inheritance == VM_INHERIT_SHARE);
17755 assert(!(*cur_protection & ~(VM_PROT_ALL | VM_PROT_ALLEXEC)));
17756 assert(!(*max_protection & ~(VM_PROT_ALL | VM_PROT_ALLEXEC)));
17757 assert((*cur_protection & *max_protection) == *cur_protection);
17758
17759 /*
17760 * Compute start and end of region.
17761 */
17762 src_start = vm_map_trunc_page(addr, effective_page_mask);
17763 src_end = vm_map_round_page(src_start + size, effective_page_mask);
17764
17765 /*
17766 * Initialize map_header.
17767 */
17768 map_header->nentries = 0;
17769 map_header->entries_pageable = pageable;
17770// map_header->page_shift = MIN(VM_MAP_PAGE_SHIFT(map), PAGE_SHIFT);
17771 map_header->page_shift = (uint16_t)VM_MAP_PAGE_SHIFT(map);
17772 map_header->rb_head_store.rbh_root = (void *)(int)SKIP_RB_TREE;
17773 vm_map_store_init(map_header);
17774
17775 if (copy && vmk_flags.vmkf_remap_prot_copy) {
17776 /*
17777 * Special case for vm_map_protect(VM_PROT_COPY):
17778 * we want to set the new mappings' max protection to the
17779 * specified *max_protection...
17780 */
17781 max_prot_for_prot_copy = *max_protection & (VM_PROT_ALL | VM_PROT_ALLEXEC);
17782 /* ... but we want to use the vm_remap() legacy mode */
17783 vmk_flags.vmkf_remap_legacy_mode = true;
17784 *max_protection = VM_PROT_NONE;
17785 *cur_protection = VM_PROT_NONE;
17786 } else {
17787 max_prot_for_prot_copy = VM_PROT_NONE;
17788 }
17789
17790 if (vmk_flags.vmkf_remap_legacy_mode) {
17791 /*
17792 * vm_remap() legacy mode:
17793 * Extract all memory regions in the specified range and
17794 * collect the strictest set of protections allowed on the
17795 * entire range, so the caller knows what they can do with
17796 * the remapped range.
17797 * We start with VM_PROT_ALL and we'll remove the protections
17798 * missing from each memory region.
17799 */
17800 vm_remap_legacy = TRUE;
17801 *cur_protection = VM_PROT_ALL;
17802 *max_protection = VM_PROT_ALL;
17803 required_cur_prot = VM_PROT_NONE;
17804 required_max_prot = VM_PROT_NONE;
17805 } else {
17806 /*
17807 * vm_remap_new() mode:
17808 * Extract all memory regions in the specified range and
17809 * ensure that they have at least the protections specified
17810 * by the caller via *cur_protection and *max_protection.
17811 * The resulting mapping should have these protections.
17812 */
17813 vm_remap_legacy = FALSE;
17814 if (copy) {
17815 required_cur_prot = VM_PROT_NONE;
17816 required_max_prot = VM_PROT_READ;
17817 } else {
17818 required_cur_prot = *cur_protection;
17819 required_max_prot = *max_protection;
17820 }
17821 }
17822
17823 map_address = 0;
17824 mapped_size = 0;
17825 result = KERN_SUCCESS;
17826
17827 /*
17828 * The specified source virtual space might correspond to
17829 * multiple map entries, need to loop on them.
17830 */
17831 if (vm_map_is_sealed(map)) {
17832 vm_map_lock_read(map);
17833 } else {
17834 vm_map_lock(map);
17835 }
17836 vmlp_range_event(map, addr, size);
17837
17838 if (map->pmap == kernel_pmap) {
17839 map_copy->is_kernel_range = true;
17840 map_copy->orig_range = kmem_addr_get_range(addr, size);
17841#if CONFIG_MAP_RANGES
17842 } else if (map->uses_user_ranges) {
17843 map_copy->is_user_range = true;
17844 map_copy->orig_range = vm_map_user_range_resolve(map, addr, size, NULL);
17845#endif /* CONFIG_MAP_RANGES */
17846 }
17847
17848 if (VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) {
17849 /*
17850 * This address space uses sub-pages so the range might
17851 * not be re-mappable in an address space with larger
17852 * pages. Re-assemble any broken-up VM map entries to
17853 * improve our chances of making it work.
17854 */
17855 vm_map_simplify_range(map, src_start, src_end);
17856 }
17857 while (mapped_size != size) {
17858 vm_map_size_t entry_size;
17859
17860 /*
17861 * Find the beginning of the region.
17862 */
17863 if (!vm_map_lookup_entry(map, src_start, &src_entry)) {
17864 result = KERN_INVALID_ADDRESS;
17865 break;
17866 }
17867
17868 if (src_start < src_entry->vme_start ||
17869 (mapped_size && src_start != src_entry->vme_start)) {
17870 result = KERN_INVALID_ADDRESS;
17871 break;
17872 }
17873
17874 tmp_size = size - mapped_size;
17875 if (src_end > src_entry->vme_end) {
17876 tmp_size -= (src_end - src_entry->vme_end);
17877 }
17878
17879 entry_size = (vm_map_size_t)(src_entry->vme_end -
17880 src_entry->vme_start);
17881
17882 if (src_entry->is_sub_map &&
17883 vmk_flags.vmkf_copy_single_object) {
17884 vm_map_t submap;
17885 vm_map_offset_t submap_start;
17886 vm_map_size_t submap_size;
17887 boolean_t submap_needs_copy;
17888
17889 /*
17890 * No check for "required protection" on "src_entry"
17891 * because the protections that matter are the ones
17892 * on the submap's VM map entry, which will be checked
17893 * during the call to vm_map_remap_extract() below.
17894 */
17895 object = VM_OBJECT_NULL;
17896
17897 submap_size = src_entry->vme_end - src_start;
17898 if (submap_size > size) {
17899 submap_size = size;
17900 }
17901 submap_start = VME_OFFSET(src_entry) + src_start - src_entry->vme_start;
17902 submap = VME_SUBMAP(src_entry);
17903 if (copy) {
17904 /*
17905 * The caller wants a copy-on-write re-mapping,
17906 * so let's extract from the submap accordingly.
17907 */
17908 submap_needs_copy = TRUE;
17909 } else if (src_entry->needs_copy) {
17910 /*
17911 * The caller wants a shared re-mapping but the
17912 * submap is mapped with "needs_copy", so its
17913 * contents can't be shared as is. Extract the
17914 * contents of the submap as "copy-on-write".
17915 * The re-mapping won't be shared with the
17916 * original mapping but this is equivalent to
17917 * what happened with the original "remap from
17918 * submap" code.
17919 * The shared region is mapped "needs_copy", for
17920 * example.
17921 */
17922 submap_needs_copy = TRUE;
17923 } else {
17924 /*
17925 * The caller wants a shared re-mapping and
17926 * this mapping can be shared (no "needs_copy"),
17927 * so let's extract from the submap accordingly.
17928 * Kernel submaps are mapped without
17929 * "needs_copy", for example.
17930 */
17931 submap_needs_copy = FALSE;
17932 }
17933 vm_map_reference(submap);
17934 vm_map_unlock(map);
17935 src_entry = NULL;
17936 if (vm_remap_legacy) {
17937 *cur_protection = VM_PROT_NONE;
17938 *max_protection = VM_PROT_NONE;
17939 }
17940
17941 DTRACE_VM7(remap_submap_recurse,
17942 vm_map_t, map,
17943 vm_map_offset_t, addr,
17944 vm_map_size_t, size,
17945 boolean_t, copy,
17946 vm_map_offset_t, submap_start,
17947 vm_map_size_t, submap_size,
17948 boolean_t, submap_needs_copy);
17949
17950 result = vm_map_remap_extract(submap,
17951 submap_start,
17952 submap_size,
17953 submap_needs_copy,
17954 map_copy,
17955 cur_protection,
17956 max_protection,
17957 inheritance,
17958 vmk_flags);
17959 vm_map_deallocate(submap);
17960
17961 if (result == KERN_SUCCESS &&
17962 submap_needs_copy &&
17963 !copy) {
17964 /*
17965 * We were asked for a "shared"
17966 * re-mapping but had to ask for a
17967 * "copy-on-write" remapping of the
17968 * submap's mapping to honor the
17969 * submap's "needs_copy".
17970 * We now need to resolve that
17971 * pending "copy-on-write" to
17972 * get something we can share.
17973 */
17974 vm_map_entry_t copy_entry;
17975 vm_object_offset_t copy_offset;
17976 vm_map_size_t copy_size;
17977 vm_object_t copy_object;
17978 copy_entry = vm_map_copy_first_entry(map_copy);
17979 copy_size = copy_entry->vme_end - copy_entry->vme_start;
17980 copy_object = VME_OBJECT(copy_entry);
17981 copy_offset = VME_OFFSET(copy_entry);
17982 if (copy_object == VM_OBJECT_NULL) {
17983 assert(copy_offset == 0);
17984 assert(!copy_entry->needs_copy);
17985 if (copy_entry->max_protection == VM_PROT_NONE) {
17986 assert(copy_entry->protection == VM_PROT_NONE);
17987 /* nothing to share */
17988 } else {
17989 assert(copy_offset == 0);
17990 copy_object = vm_object_allocate(copy_size, submap->serial_id);
17991 VME_OFFSET_SET(copy_entry, 0);
17992 VME_OBJECT_SET(copy_entry, copy_object, false, 0);
17993 assert(copy_entry->use_pmap);
17994 }
17995 } else if (copy_object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) {
17996 /* already shareable */
17997 assert(!copy_entry->needs_copy);
17998 } else if (copy_entry->needs_copy ||
17999 copy_object->shadowed ||
18000 (copy_object->internal &&
18001 !copy_object->true_share &&
18002 !copy_entry->is_shared &&
18003 copy_object->vo_size > copy_size)) {
18004 VME_OBJECT_SHADOW(copy_entry, copy_size, TRUE);
18005 assert(copy_entry->use_pmap);
18006 if (copy_entry->needs_copy) {
18007 /* already write-protected */
18008 } else {
18009 vm_prot_t prot;
18010 prot = copy_entry->protection & ~VM_PROT_WRITE;
18011 vm_object_pmap_protect(copy_object,
18012 copy_offset,
18013 copy_size,
18014 PMAP_NULL,
18015 PAGE_SIZE,
18016 0,
18017 prot);
18018 }
18019 copy_entry->needs_copy = FALSE;
18020 }
18021 copy_object = VME_OBJECT(copy_entry);
18022 copy_offset = VME_OFFSET(copy_entry);
18023 if (copy_object &&
18024 copy_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
18025 copy_object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
18026 copy_object->true_share = TRUE;
18027 }
18028 }
18029
18030 vmlp_api_end(VM_MAP_REMAP_EXTRACT, result);
18031 return result;
18032 }
18033
18034 if (src_entry->is_sub_map) {
18035 assert(!vm_map_is_sealed(map));
18036 /* protections for submap mapping are irrelevant here */
18037 } else if (((src_entry->protection & required_cur_prot) !=
18038 required_cur_prot) ||
18039 ((src_entry->max_protection & required_max_prot) !=
18040 required_max_prot)) {
18041 if (vmk_flags.vmkf_copy_single_object &&
18042 mapped_size != 0) {
18043 /*
18044 * Single object extraction.
18045 * We can't extract more with the required
18046 * protection but we've extracted some, so
18047 * stop there and declare success.
18048 * The caller should check the size of
18049 * the copy entry we've extracted.
18050 */
18051 result = KERN_SUCCESS;
18052 } else {
18053 /*
18054 * VM range extraction.
18055 * Required proctection is not available
18056 * for this part of the range: fail.
18057 */
18058 result = KERN_PROTECTION_FAILURE;
18059 }
18060 break;
18061 }
18062
18063 if (src_entry->is_sub_map) {
18064 vm_map_t submap;
18065 vm_map_offset_t submap_start;
18066 vm_map_size_t submap_size;
18067 vm_map_copy_t submap_copy;
18068 vm_prot_t submap_curprot, submap_maxprot;
18069 boolean_t submap_needs_copy;
18070
18071 assert(!vm_map_is_sealed(map));
18072 /*
18073 * No check for "required protection" on "src_entry"
18074 * because the protections that matter are the ones
18075 * on the submap's VM map entry, which will be checked
18076 * during the call to vm_map_copy_extract() below.
18077 */
18078 object = VM_OBJECT_NULL;
18079 submap_copy = VM_MAP_COPY_NULL;
18080
18081 /* find equivalent range in the submap */
18082 submap = VME_SUBMAP(src_entry);
18083 submap_start = VME_OFFSET(src_entry) + src_start - src_entry->vme_start;
18084 submap_size = tmp_size;
18085 if (copy) {
18086 /*
18087 * The caller wants a copy-on-write re-mapping,
18088 * so let's extract from the submap accordingly.
18089 */
18090 submap_needs_copy = TRUE;
18091 } else if (src_entry->needs_copy) {
18092 /*
18093 * The caller wants a shared re-mapping but the
18094 * submap is mapped with "needs_copy", so its
18095 * contents can't be shared as is. Extract the
18096 * contents of the submap as "copy-on-write".
18097 * The re-mapping won't be shared with the
18098 * original mapping but this is equivalent to
18099 * what happened with the original "remap from
18100 * submap" code.
18101 * The shared region is mapped "needs_copy", for
18102 * example.
18103 */
18104 submap_needs_copy = TRUE;
18105 } else {
18106 /*
18107 * The caller wants a shared re-mapping and
18108 * this mapping can be shared (no "needs_copy"),
18109 * so let's extract from the submap accordingly.
18110 * Kernel submaps are mapped without
18111 * "needs_copy", for example.
18112 */
18113 submap_needs_copy = FALSE;
18114 }
18115 /* extra ref to keep submap alive */
18116 vm_map_reference(submap);
18117
18118 DTRACE_VM7(remap_submap_recurse,
18119 vm_map_t, map,
18120 vm_map_offset_t, addr,
18121 vm_map_size_t, size,
18122 boolean_t, copy,
18123 vm_map_offset_t, submap_start,
18124 vm_map_size_t, submap_size,
18125 boolean_t, submap_needs_copy);
18126
18127 /*
18128 * The map can be safely unlocked since we
18129 * already hold a reference on the submap.
18130 *
18131 * No timestamp since we don't care if the map
18132 * gets modified while we're down in the submap.
18133 * We'll resume the extraction at src_start + tmp_size
18134 * anyway.
18135 */
18136 vm_map_unlock(map);
18137 src_entry = NULL; /* not valid once map is unlocked */
18138
18139 if (vm_remap_legacy) {
18140 submap_curprot = VM_PROT_NONE;
18141 submap_maxprot = VM_PROT_NONE;
18142 if (max_prot_for_prot_copy) {
18143 submap_maxprot = max_prot_for_prot_copy;
18144 }
18145 } else {
18146 assert(!max_prot_for_prot_copy);
18147 submap_curprot = *cur_protection;
18148 submap_maxprot = *max_protection;
18149 }
18150 result = vm_map_copy_extract(submap,
18151 submap_start,
18152 submap_size,
18153 submap_needs_copy,
18154 &submap_copy,
18155 &submap_curprot,
18156 &submap_maxprot,
18157 inheritance,
18158 vmk_flags);
18159
18160 /* release extra ref on submap */
18161 vm_map_deallocate(submap);
18162 submap = VM_MAP_NULL;
18163
18164 if (result != KERN_SUCCESS) {
18165 vm_map_lock(map);
18166 break;
18167 }
18168
18169 /* transfer submap_copy entries to map_header */
18170 while (vm_map_copy_first_entry(submap_copy) !=
18171 vm_map_copy_to_entry(submap_copy)) {
18172 vm_map_entry_t copy_entry;
18173 vm_map_size_t copy_entry_size;
18174
18175 copy_entry = vm_map_copy_first_entry(submap_copy);
18176
18177 /*
18178 * Prevent kernel_object from being exposed to
18179 * user space.
18180 */
18181 if (__improbable(copy_entry->vme_kernel_object)) {
18182 printf("%d[%s]: rejecting attempt to extract from kernel_object\n",
18183 proc_selfpid(),
18184 (get_bsdtask_info(current_task())
18185 ? proc_name_address(get_bsdtask_info(current_task()))
18186 : "?"));
18187 DTRACE_VM(extract_kernel_only);
18188 result = KERN_INVALID_RIGHT;
18189 vm_map_copy_discard(submap_copy);
18190 submap_copy = VM_MAP_COPY_NULL;
18191 vm_map_lock(map);
18192 break;
18193 }
18194
18195 vm_map_copy_entry_unlink(submap_copy, copy_entry);
18196 copy_entry_size = copy_entry->vme_end - copy_entry->vme_start;
18197 copy_entry->vme_start = map_address;
18198 copy_entry->vme_end = map_address + copy_entry_size;
18199 map_address += copy_entry_size;
18200 mapped_size += copy_entry_size;
18201 src_start += copy_entry_size;
18202 assert(src_start <= src_end);
18203 _vm_map_store_entry_link(map_header,
18204 VMH_PREV(map_header),
18205 copy_entry);
18206 }
18207 /* done with submap_copy */
18208 vm_map_copy_discard(submap_copy);
18209
18210 if (vm_remap_legacy) {
18211 *cur_protection &= submap_curprot;
18212 *max_protection &= submap_maxprot;
18213 }
18214
18215 /* re-acquire the map lock and continue to next entry */
18216 vm_map_lock(map);
18217 continue;
18218 } else {
18219 object = VME_OBJECT(src_entry);
18220
18221 /*
18222 * Prevent kernel_object from being exposed to
18223 * user space.
18224 */
18225 if (__improbable(is_kernel_object(object))) {
18226 printf("%d[%s]: rejecting attempt to extract from kernel_object\n",
18227 proc_selfpid(),
18228 (get_bsdtask_info(current_task())
18229 ? proc_name_address(get_bsdtask_info(current_task()))
18230 : "?"));
18231 DTRACE_VM(extract_kernel_only);
18232 result = KERN_INVALID_RIGHT;
18233 break;
18234 }
18235
18236 if (src_entry->iokit_acct) {
18237 /*
18238 * This entry uses "IOKit accounting".
18239 */
18240 } else if (object != VM_OBJECT_NULL &&
18241 object->internal &&
18242 (object->purgable != VM_PURGABLE_DENY ||
18243 object->vo_ledger_tag != VM_LEDGER_TAG_NONE)) {
18244 /*
18245 * Purgeable objects have their own accounting:
18246 * no pmap accounting for them.
18247 */
18248 assertf(!src_entry->use_pmap,
18249 "map=%p src_entry=%p [0x%llx:0x%llx] 0x%x/0x%x %d",
18250 map,
18251 src_entry,
18252 (uint64_t)src_entry->vme_start,
18253 (uint64_t)src_entry->vme_end,
18254 src_entry->protection,
18255 src_entry->max_protection,
18256 VME_ALIAS(src_entry));
18257 } else {
18258 /*
18259 * Not IOKit or purgeable:
18260 * must be accounted by pmap stats.
18261 */
18262 assertf(src_entry->use_pmap,
18263 "map=%p src_entry=%p [0x%llx:0x%llx] 0x%x/0x%x %d",
18264 map,
18265 src_entry,
18266 (uint64_t)src_entry->vme_start,
18267 (uint64_t)src_entry->vme_end,
18268 src_entry->protection,
18269 src_entry->max_protection,
18270 VME_ALIAS(src_entry));
18271 }
18272
18273 if (object == VM_OBJECT_NULL) {
18274 assert(!vm_map_is_sealed(map));
18275 assert(!src_entry->needs_copy);
18276 if (src_entry->max_protection == VM_PROT_NONE) {
18277 assert(src_entry->protection == VM_PROT_NONE);
18278 /*
18279 * No VM object and no permissions:
18280 * this must be a reserved range with
18281 * nothing to share or copy.
18282 * There could also be all sorts of
18283 * pmap shenanigans within that reserved
18284 * range, so let's just copy the map
18285 * entry as is to remap a similar
18286 * reserved range.
18287 */
18288 offset = 0; /* no object => no offset */
18289 goto copy_src_entry;
18290 }
18291 object = vm_object_allocate(entry_size, map->serial_id);
18292 VME_OFFSET_SET(src_entry, 0);
18293 VME_OBJECT_SET(src_entry, object, false, 0);
18294 assert(src_entry->use_pmap);
18295 assert(!map->mapped_in_other_pmaps);
18296 } else if (src_entry->wired_count ||
18297 object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) {
18298 /*
18299 * A wired memory region should not have
18300 * any pending copy-on-write and needs to
18301 * keep pointing at the VM object that
18302 * contains the wired pages.
18303 * If we're sharing this memory (copy=false),
18304 * we'll share this VM object.
18305 * If we're copying this memory (copy=true),
18306 * we'll call vm_object_copy_slowly() below
18307 * and use the new VM object for the remapping.
18308 *
18309 * Or, we are already using an asymmetric
18310 * copy, and therefore we already have
18311 * the right object.
18312 */
18313 assert(!src_entry->needs_copy);
18314 } else if (src_entry->needs_copy || object->shadowed ||
18315 (object->internal && !object->true_share &&
18316 !src_entry->is_shared &&
18317 object->vo_size > entry_size)) {
18318 bool is_writable;
18319
18320 assert(!vm_map_is_sealed(map));
18321 VME_OBJECT_SHADOW(src_entry, entry_size,
18322 vm_map_always_shadow(map));
18323 assert(src_entry->use_pmap);
18324
18325 is_writable = false;
18326 if (src_entry->protection & VM_PROT_WRITE) {
18327 is_writable = true;
18328#if __arm64e__
18329 } else if (src_entry->used_for_tpro) {
18330 is_writable = true;
18331#endif /* __arm64e__ */
18332 }
18333 if (!src_entry->needs_copy && is_writable) {
18334 vm_prot_t prot;
18335
18336 if (pmap_has_prot_policy(map->pmap, src_entry->translated_allow_execute, src_entry->protection)) {
18337 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
18338 __FUNCTION__,
18339 map, map->pmap,
18340 src_entry,
18341 (uint64_t)src_entry->vme_start,
18342 (uint64_t)src_entry->vme_end,
18343 src_entry->protection);
18344 }
18345
18346 prot = src_entry->protection & ~VM_PROT_WRITE;
18347
18348 if (override_nx(map,
18349 VME_ALIAS(src_entry))
18350 && prot) {
18351 prot |= VM_PROT_EXECUTE;
18352 }
18353
18354 if (pmap_has_prot_policy(map->pmap, src_entry->translated_allow_execute, prot)) {
18355 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
18356 __FUNCTION__,
18357 map, map->pmap,
18358 src_entry,
18359 (uint64_t)src_entry->vme_start,
18360 (uint64_t)src_entry->vme_end,
18361 prot);
18362 }
18363
18364 if (map->mapped_in_other_pmaps) {
18365 vm_object_pmap_protect(
18366 VME_OBJECT(src_entry),
18367 VME_OFFSET(src_entry),
18368 entry_size,
18369 PMAP_NULL,
18370 PAGE_SIZE,
18371 src_entry->vme_start,
18372 prot);
18373#if MACH_ASSERT
18374 } else if (__improbable(map->pmap == PMAP_NULL)) {
18375 /*
18376 * Some VM tests (in vm_tests.c)
18377 * sometimes want to use a VM
18378 * map without a pmap.
18379 * Otherwise, this should never
18380 * happen.
18381 */
18382 if (!thread_get_test_option(test_option_vm_map_allow_null_pmap)) {
18383 panic("null pmap");
18384 }
18385#endif /* MACH_ASSERT */
18386 } else {
18387 pmap_protect(vm_map_pmap(map),
18388 src_entry->vme_start,
18389 src_entry->vme_end,
18390 prot);
18391 }
18392 }
18393
18394 object = VME_OBJECT(src_entry);
18395 src_entry->needs_copy = FALSE;
18396 }
18397
18398
18399 vm_object_lock(object);
18400 vm_object_reference_locked(object); /* object ref. for new entry */
18401 assert(!src_entry->needs_copy);
18402 if (object->copy_strategy ==
18403 MEMORY_OBJECT_COPY_SYMMETRIC) {
18404 /*
18405 * If we want to share this object (copy==0),
18406 * it needs to be COPY_DELAY.
18407 * If we want to copy this object (copy==1),
18408 * we can't just set "needs_copy" on our side
18409 * and expect the other side to do the same
18410 * (symmetrically), so we can't let the object
18411 * stay COPY_SYMMETRIC.
18412 * So we always switch from COPY_SYMMETRIC to
18413 * COPY_DELAY.
18414 */
18415 assert(!vm_map_is_sealed(map));
18416 object->copy_strategy =
18417 MEMORY_OBJECT_COPY_DELAY;
18418 VM_OBJECT_SET_TRUE_SHARE(object, TRUE);
18419 }
18420 vm_object_unlock(object);
18421 }
18422
18423 offset = (VME_OFFSET(src_entry) +
18424 (src_start - src_entry->vme_start));
18425
18426copy_src_entry:
18427
18428
18429 new_entry = _vm_map_entry_create(map_header);
18430 vm_map_entry_copy(map, new_entry, src_entry);
18431 if (new_entry->is_sub_map) {
18432 /* clr address space specifics */
18433 assert(!vm_map_is_sealed(map));
18434 new_entry->use_pmap = FALSE;
18435 } else if (copy) {
18436 /*
18437 * We're dealing with a copy-on-write operation,
18438 * so the resulting mapping should not inherit the
18439 * original mapping's accounting settings.
18440 * "use_pmap" should be reset to its default (TRUE)
18441 * so that the new mapping gets accounted for in
18442 * the task's memory footprint.
18443 */
18444 new_entry->use_pmap = TRUE;
18445 }
18446 /* "iokit_acct" was cleared in vm_map_entry_copy() */
18447 assert(!new_entry->iokit_acct);
18448
18449 new_entry->vme_start = map_address;
18450 new_entry->vme_end = map_address + tmp_size;
18451 assert(new_entry->vme_start < new_entry->vme_end);
18452 if (copy && vmk_flags.vmkf_remap_prot_copy) {
18453 /* security: keep "permanent" and "csm_associated" */
18454 new_entry->vme_permanent = src_entry->vme_permanent;
18455 new_entry->csm_associated = src_entry->csm_associated;
18456 /*
18457 * Remapping for vm_map_protect(VM_PROT_COPY)
18458 * to convert a read-only mapping into a
18459 * copy-on-write version of itself but
18460 * with write access:
18461 * keep the original inheritance but let's not
18462 * add VM_PROT_WRITE to the max protection yet
18463 * since we want to do more security checks against
18464 * the target map.
18465 */
18466 new_entry->inheritance = src_entry->inheritance;
18467 new_entry->protection &= max_prot_for_prot_copy;
18468
18469#ifdef __arm64e__
18470 /*
18471 * Remapping for vm_map_protect(VM_PROT_COPY) to remap a TPRO
18472 * region to be explicitly writable without TPRO is only permitted
18473 * if TPRO enforcement has been overridden.
18474 *
18475 * In this case we ensure any entries reset the TPRO state
18476 * and we permit the region to be downgraded from permanent.
18477 */
18478 if (new_entry->used_for_tpro) {
18479 if (vmk_flags.vmkf_tpro_enforcement_override) {
18480 new_entry->used_for_tpro = FALSE;
18481 new_entry->vme_permanent = FALSE;
18482 } else {
18483 result = KERN_PROTECTION_FAILURE;
18484 vm_object_deallocate(object);
18485 vm_map_entry_dispose(new_entry);
18486 new_entry = VM_MAP_ENTRY_NULL;
18487 break;
18488 }
18489 }
18490#endif
18491 } else {
18492 new_entry->inheritance = inheritance;
18493 if (!vm_remap_legacy) {
18494 new_entry->protection = *cur_protection;
18495 new_entry->max_protection = *max_protection;
18496 }
18497 }
18498
18499 VME_OFFSET_SET(new_entry, offset);
18500
18501 /*
18502 * The new region has to be copied now if required.
18503 */
18504RestartCopy:
18505 if (!copy) {
18506 if (src_entry->used_for_jit == TRUE) {
18507 if (same_map) {
18508 } else if (!VM_MAP_POLICY_ALLOW_JIT_SHARING(map)) {
18509 /*
18510 * Cannot allow an entry describing a JIT
18511 * region to be shared across address spaces.
18512 */
18513 result = KERN_INVALID_ARGUMENT;
18514 vm_object_deallocate(object);
18515 vm_map_entry_dispose(new_entry);
18516 new_entry = VM_MAP_ENTRY_NULL;
18517 break;
18518 }
18519 }
18520
18521 if (!src_entry->is_sub_map &&
18522 VME_OBJECT(src_entry) == VM_OBJECT_NULL) {
18523 /* no accessible memory; nothing to share */
18524 assert(!vm_map_is_sealed(map));
18525 assert(src_entry->protection == VM_PROT_NONE);
18526 assert(src_entry->max_protection == VM_PROT_NONE);
18527 src_entry->is_shared = FALSE;
18528 } else {
18529 src_entry->is_shared = TRUE;
18530 }
18531 if (!new_entry->is_sub_map &&
18532 VME_OBJECT(new_entry) == VM_OBJECT_NULL) {
18533 /* no accessible memory; nothing to share */
18534 assert(new_entry->protection == VM_PROT_NONE);
18535 assert(new_entry->max_protection == VM_PROT_NONE);
18536 new_entry->is_shared = FALSE;
18537 } else {
18538 new_entry->is_shared = TRUE;
18539 }
18540 if (!(new_entry->is_sub_map)) {
18541 new_entry->needs_copy = FALSE;
18542 }
18543 } else if (src_entry->is_sub_map) {
18544 /* make this a COW sub_map if not already */
18545 assert(!vm_map_is_sealed(map));
18546 assert(new_entry->wired_count == 0);
18547 new_entry->needs_copy = TRUE;
18548 object = VM_OBJECT_NULL;
18549 } else if (src_entry->wired_count == 0 &&
18550 !(debug4k_no_cow_copyin && VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT) &&
18551 vm_object_copy_quickly(VME_OBJECT(new_entry),
18552 VME_OFFSET(new_entry),
18553 (new_entry->vme_end -
18554 new_entry->vme_start),
18555 &src_needs_copy,
18556 &new_entry_needs_copy)) {
18557 new_entry->needs_copy = new_entry_needs_copy;
18558 new_entry->is_shared = FALSE;
18559 assertf(new_entry->use_pmap, "map %p new_entry %p\n", map, new_entry);
18560
18561 /*
18562 * Handle copy_on_write semantics.
18563 */
18564 if (src_needs_copy && !src_entry->needs_copy) {
18565 vm_prot_t prot;
18566
18567 if (pmap_has_prot_policy(map->pmap, src_entry->translated_allow_execute, src_entry->protection)) {
18568 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
18569 __FUNCTION__,
18570 map, map->pmap, src_entry,
18571 (uint64_t)src_entry->vme_start,
18572 (uint64_t)src_entry->vme_end,
18573 src_entry->protection);
18574 }
18575
18576 prot = src_entry->protection & ~VM_PROT_WRITE;
18577
18578 if (override_nx(map,
18579 VME_ALIAS(src_entry))
18580 && prot) {
18581 prot |= VM_PROT_EXECUTE;
18582 }
18583
18584 if (pmap_has_prot_policy(map->pmap, src_entry->translated_allow_execute, prot)) {
18585 panic("%s: map %p pmap %p entry %p 0x%llx:0x%llx prot 0x%x",
18586 __FUNCTION__,
18587 map, map->pmap, src_entry,
18588 (uint64_t)src_entry->vme_start,
18589 (uint64_t)src_entry->vme_end,
18590 prot);
18591 }
18592
18593 vm_object_pmap_protect(object,
18594 offset,
18595 entry_size,
18596 ((src_entry->is_shared
18597 || map->mapped_in_other_pmaps) ?
18598 PMAP_NULL : map->pmap),
18599 VM_MAP_PAGE_SIZE(map),
18600 src_entry->vme_start,
18601 prot);
18602
18603 assert(src_entry->wired_count == 0);
18604 src_entry->needs_copy = TRUE;
18605 }
18606 /*
18607 * Throw away the old object reference of the new entry.
18608 */
18609 vm_object_deallocate(object);
18610 } else {
18611 new_entry->is_shared = FALSE;
18612 assertf(new_entry->use_pmap, "map %p new_entry %p\n", map, new_entry);
18613
18614 src_entry_was_wired = (src_entry->wired_count > 0);
18615 saved_src_entry = src_entry;
18616 src_entry = VM_MAP_ENTRY_NULL;
18617
18618 /*
18619 * The map can be safely unlocked since we
18620 * already hold a reference on the object.
18621 *
18622 * Record the timestamp of the map for later
18623 * verification, and unlock the map.
18624 */
18625 version.main_timestamp = map->timestamp;
18626 if (vm_map_is_sealed(map)) {
18627 vm_map_unlock_read(map);
18628 } else {
18629 vm_map_unlock(map); /* Increments timestamp once! */
18630 }
18631
18632 /*
18633 * Perform the copy.
18634 */
18635 if (src_entry_was_wired > 0 ||
18636 (debug4k_no_cow_copyin &&
18637 VM_MAP_PAGE_SHIFT(map) < PAGE_SHIFT)) {
18638 vm_object_lock(object);
18639 result = vm_object_copy_slowly(
18640 object,
18641 offset,
18642 (new_entry->vme_end -
18643 new_entry->vme_start),
18644 THREAD_UNINT,
18645 &new_copy_object);
18646 /* VME_OBJECT_SET will reset used_for_jit, so preserve it. */
18647 saved_used_for_jit = new_entry->used_for_jit;
18648 VME_OBJECT_SET(new_entry, new_copy_object, false, 0);
18649 new_entry->used_for_jit = saved_used_for_jit;
18650 VME_OFFSET_SET(new_entry, offset - vm_object_trunc_page(offset));
18651 new_entry->needs_copy = FALSE;
18652 } else {
18653 vm_object_offset_t new_offset;
18654
18655 new_offset = VME_OFFSET(new_entry);
18656 result = vm_object_copy_strategically(
18657 object,
18658 offset,
18659 (new_entry->vme_end -
18660 new_entry->vme_start),
18661 false, /* forking */
18662 &new_copy_object,
18663 &new_offset,
18664 &new_entry_needs_copy);
18665 /* VME_OBJECT_SET will reset used_for_jit, so preserve it. */
18666 saved_used_for_jit = new_entry->used_for_jit;
18667 VME_OBJECT_SET(new_entry, new_copy_object, false, 0);
18668 new_entry->used_for_jit = saved_used_for_jit;
18669 if (new_offset != VME_OFFSET(new_entry)) {
18670 VME_OFFSET_SET(new_entry, new_offset);
18671 }
18672
18673 new_entry->needs_copy = new_entry_needs_copy;
18674 }
18675
18676 /*
18677 * Throw away the old object reference of the new entry.
18678 */
18679 vm_object_deallocate(object);
18680
18681 if (result != KERN_SUCCESS &&
18682 result != KERN_MEMORY_RESTART_COPY) {
18683 vm_map_entry_dispose(new_entry);
18684 if (vm_map_is_sealed(map)) {
18685 vm_map_lock_read(map);
18686 } else {
18687 vm_map_lock(map);
18688 }
18689 break;
18690 }
18691
18692 /*
18693 * Verify that the map has not substantially
18694 * changed while the copy was being made.
18695 */
18696
18697 if (vm_map_is_sealed(map)) {
18698 vm_map_lock_read(map);
18699 version.main_timestamp--; /* we don't expect an increment */
18700 } else {
18701 vm_map_lock(map);
18702 }
18703 if (version.main_timestamp + 1 != map->timestamp) {
18704 /*
18705 * Simple version comparison failed.
18706 *
18707 * Retry the lookup and verify that the
18708 * same object/offset are still present.
18709 */
18710 saved_src_entry = VM_MAP_ENTRY_NULL;
18711 vm_object_deallocate(VME_OBJECT(new_entry));
18712 vm_map_entry_dispose(new_entry);
18713 if (result == KERN_MEMORY_RESTART_COPY) {
18714 result = KERN_SUCCESS;
18715 }
18716 continue;
18717 }
18718 /* map hasn't changed: src_entry is still valid */
18719 src_entry = saved_src_entry;
18720 saved_src_entry = VM_MAP_ENTRY_NULL;
18721
18722 if (result == KERN_MEMORY_RESTART_COPY) {
18723 vm_object_reference(object);
18724 goto RestartCopy;
18725 }
18726 }
18727
18728 _vm_map_store_entry_link(map_header,
18729 VMH_PREV(map_header), new_entry);
18730
18731 /* protections for submap mapping are irrelevant here */
18732 if (vm_remap_legacy && !src_entry->is_sub_map) {
18733 *cur_protection &= src_entry->protection;
18734 *max_protection &= src_entry->max_protection;
18735 }
18736
18737 map_address += tmp_size;
18738 mapped_size += tmp_size;
18739 src_start += tmp_size;
18740
18741 if (vmk_flags.vmkf_copy_single_object) {
18742 if (mapped_size != size) {
18743 DEBUG4K_SHARE("map %p addr 0x%llx size 0x%llx clipped copy at mapped_size 0x%llx\n",
18744 map, (uint64_t)addr, (uint64_t)size, (uint64_t)mapped_size);
18745 if (src_entry->vme_next != vm_map_to_entry(map) &&
18746 src_entry->vme_next->vme_object_value ==
18747 src_entry->vme_object_value) {
18748 /* XXX TODO4K */
18749 DEBUG4K_ERROR("could have extended copy to next entry...\n");
18750 }
18751 }
18752 break;
18753 }
18754 } /* end while */
18755
18756 if (vm_map_is_sealed(map)) {
18757 vm_map_unlock_read(map);
18758 } else {
18759 vm_map_unlock(map);
18760 }
18761 if (result != KERN_SUCCESS) {
18762 /*
18763 * Free all allocated elements.
18764 */
18765 for (src_entry = map_header->links.next;
18766 src_entry != CAST_TO_VM_MAP_ENTRY(&map_header->links);
18767 src_entry = new_entry) {
18768 new_entry = src_entry->vme_next;
18769 _vm_map_store_entry_unlink(map_header, src_entry, false);
18770 if (src_entry->is_sub_map) {
18771 vm_map_deallocate(VME_SUBMAP(src_entry));
18772 } else {
18773 vm_object_deallocate(VME_OBJECT(src_entry));
18774 }
18775 vm_map_entry_dispose(src_entry);
18776 }
18777 }
18778 vmlp_api_end(VM_MAP_REMAP_EXTRACT, result);
18779 return result;
18780}
18781
18782bool
18783vm_map_is_exotic(
18784 vm_map_t map)
18785{
18786 return VM_MAP_IS_EXOTIC(map);
18787}
18788
18789bool
18790vm_map_is_alien(
18791 vm_map_t map)
18792{
18793 return VM_MAP_IS_ALIEN(map);
18794}
18795
18796#if XNU_TARGET_OS_OSX
18797void
18798vm_map_mark_alien(
18799 vm_map_t map)
18800{
18801 vmlp_api_start(VM_MAP_MARK_ALIEN);
18802 vm_map_lock(map);
18803 vmlp_range_event_none(map);
18804 map->is_alien = true;
18805 vm_map_unlock(map);
18806 vmlp_api_end(VM_MAP_MARK_ALIEN, 0);
18807}
18808
18809void
18810vm_map_single_jit(
18811 vm_map_t map)
18812{
18813 vmlp_api_start(VM_MAP_SINGLE_JIT);
18814 vm_map_lock(map);
18815 vmlp_range_event_none(map);
18816 map->single_jit = true;
18817 vm_map_unlock(map);
18818 vmlp_api_end(VM_MAP_SINGLE_JIT, 0);
18819}
18820#endif /* XNU_TARGET_OS_OSX */
18821
18822
18823/*
18824 * Callers of this function must call vm_map_copy_require on
18825 * previously created vm_map_copy_t or pass a newly created
18826 * one to ensure that it hasn't been forged.
18827 */
18828static kern_return_t
18829vm_map_copy_to_physcopy(
18830 vm_map_copy_t copy_map,
18831 vm_map_t target_map)
18832{
18833 vm_map_size_t size;
18834 vm_map_entry_t entry;
18835 vm_map_entry_t new_entry;
18836 vm_object_t new_object;
18837 unsigned int pmap_flags;
18838 pmap_t new_pmap;
18839 vm_map_t new_map;
18840 vm_map_address_t src_start, src_end, src_cur;
18841 vm_map_address_t dst_start, dst_end, dst_cur;
18842 kern_return_t kr;
18843 void *kbuf;
18844
18845 /*
18846 * Perform the equivalent of vm_allocate() and memcpy().
18847 * Replace the mappings in "copy_map" with the newly allocated mapping.
18848 */
18849 DEBUG4K_COPY("copy_map %p (%d %d 0x%llx 0x%llx) BEFORE\n", copy_map, copy_map->cpy_hdr.page_shift, copy_map->cpy_hdr.nentries, copy_map->offset, (uint64_t)copy_map->size);
18850
18851 assert(copy_map->cpy_hdr.page_shift != VM_MAP_PAGE_MASK(target_map));
18852
18853 /* create a new pmap to map "copy_map" */
18854 pmap_flags = 0;
18855 assert(copy_map->cpy_hdr.page_shift == FOURK_PAGE_SHIFT);
18856#if PMAP_CREATE_FORCE_4K_PAGES
18857 pmap_flags |= PMAP_CREATE_FORCE_4K_PAGES;
18858#endif /* PMAP_CREATE_FORCE_4K_PAGES */
18859 pmap_flags |= PMAP_CREATE_64BIT;
18860 new_pmap = pmap_create_options(NULL, (vm_map_size_t)0, pmap_flags);
18861 if (new_pmap == NULL) {
18862 return KERN_RESOURCE_SHORTAGE;
18863 }
18864
18865 /* allocate new VM object */
18866 size = VM_MAP_ROUND_PAGE(copy_map->size, PAGE_MASK);
18867 new_object = vm_object_allocate(size, VM_MAP_SERIAL_NONE);
18868 assert(new_object);
18869
18870 /* allocate new VM map entry */
18871 new_entry = vm_map_copy_entry_create(copy_map);
18872 assert(new_entry);
18873
18874 /* finish initializing new VM map entry */
18875 new_entry->protection = VM_PROT_DEFAULT;
18876 new_entry->max_protection = VM_PROT_DEFAULT;
18877 new_entry->use_pmap = TRUE;
18878
18879 /* make new VM map entry point to new VM object */
18880 new_entry->vme_start = 0;
18881 new_entry->vme_end = size;
18882 VME_OBJECT_SET(new_entry, new_object, false, 0);
18883 VME_OFFSET_SET(new_entry, 0);
18884
18885 /* create a new pageable VM map to map "copy_map" */
18886 new_map = vm_map_create_options(new_pmap, 0, MACH_VM_MAX_ADDRESS,
18887 VM_MAP_CREATE_PAGEABLE);
18888 assert(new_map);
18889 vm_map_set_page_shift(new_map, copy_map->cpy_hdr.page_shift);
18890
18891 /* map "copy_map" in the new VM map */
18892 src_start = 0;
18893 kr = vm_map_copyout_internal(
18894 new_map,
18895 &src_start,
18896 copy_map,
18897 copy_map->size,
18898 FALSE, /* consume_on_success */
18899 VM_PROT_DEFAULT,
18900 VM_PROT_DEFAULT,
18901 VM_INHERIT_DEFAULT);
18902 assert(kr == KERN_SUCCESS);
18903 src_end = src_start + copy_map->size;
18904
18905 /* map "new_object" in the new VM map */
18906 vm_object_reference(new_object);
18907 dst_start = 0;
18908 kr = vm_map_enter(new_map,
18909 &dst_start,
18910 size,
18911 0, /* mask */
18912 VM_MAP_KERNEL_FLAGS_ANYWHERE(.vm_tag = VM_KERN_MEMORY_OSFMK),
18913 new_object,
18914 0, /* offset */
18915 FALSE, /* needs copy */
18916 VM_PROT_DEFAULT,
18917 VM_PROT_DEFAULT,
18918 VM_INHERIT_DEFAULT);
18919 assert(kr == KERN_SUCCESS);
18920 dst_end = dst_start + size;
18921
18922 /* get a kernel buffer */
18923 kbuf = kalloc_data(PAGE_SIZE, Z_WAITOK | Z_NOFAIL);
18924
18925 /* physically copy "copy_map" mappings to new VM object */
18926 for (src_cur = src_start, dst_cur = dst_start;
18927 src_cur < src_end;
18928 src_cur += PAGE_SIZE, dst_cur += PAGE_SIZE) {
18929 vm_size_t bytes;
18930
18931 bytes = PAGE_SIZE;
18932 if (src_cur + PAGE_SIZE > src_end) {
18933 /* partial copy for last page */
18934 bytes = src_end - src_cur;
18935 assert(bytes > 0 && bytes < PAGE_SIZE);
18936 /* rest of dst page should be zero-filled */
18937 }
18938 /* get bytes from src mapping */
18939 kr = copyinmap(new_map, src_cur, kbuf, bytes);
18940 if (kr != KERN_SUCCESS) {
18941 DEBUG4K_COPY("copyinmap(%p, 0x%llx, %p, 0x%llx) kr 0x%x\n", new_map, (uint64_t)src_cur, kbuf, (uint64_t)bytes, kr);
18942 }
18943 /* put bytes in dst mapping */
18944 assert(dst_cur < dst_end);
18945 assert(dst_cur + bytes <= dst_end);
18946 kr = copyoutmap(new_map, kbuf, dst_cur, bytes);
18947 if (kr != KERN_SUCCESS) {
18948 DEBUG4K_COPY("copyoutmap(%p, %p, 0x%llx, 0x%llx) kr 0x%x\n", new_map, kbuf, (uint64_t)dst_cur, (uint64_t)bytes, kr);
18949 }
18950 }
18951
18952 /* free kernel buffer */
18953 kfree_data(kbuf, PAGE_SIZE);
18954
18955 /* destroy new map */
18956 vm_map_destroy(new_map);
18957 new_map = VM_MAP_NULL;
18958
18959 /* dispose of the old map entries in "copy_map" */
18960 while (vm_map_copy_first_entry(copy_map) !=
18961 vm_map_copy_to_entry(copy_map)) {
18962 entry = vm_map_copy_first_entry(copy_map);
18963 vm_map_copy_entry_unlink(copy_map, entry);
18964 if (entry->is_sub_map) {
18965 vm_map_deallocate(VME_SUBMAP(entry));
18966 } else {
18967 vm_object_deallocate(VME_OBJECT(entry));
18968 }
18969 vm_map_copy_entry_dispose(entry);
18970 }
18971
18972 /* change "copy_map"'s page_size to match "target_map" */
18973 copy_map->cpy_hdr.page_shift = (uint16_t)VM_MAP_PAGE_SHIFT(target_map);
18974 copy_map->offset = 0;
18975 copy_map->size = size;
18976
18977 /* insert new map entry in "copy_map" */
18978 assert(vm_map_copy_last_entry(copy_map) == vm_map_copy_to_entry(copy_map));
18979 vm_map_copy_entry_link(copy_map, vm_map_copy_last_entry(copy_map), new_entry);
18980
18981 DEBUG4K_COPY("copy_map %p (%d %d 0x%llx 0x%llx) AFTER\n", copy_map, copy_map->cpy_hdr.page_shift, copy_map->cpy_hdr.nentries, copy_map->offset, (uint64_t)copy_map->size);
18982 return KERN_SUCCESS;
18983}
18984
18985void
18986vm_map_copy_adjust_get_target_copy_map(
18987 vm_map_copy_t copy_map,
18988 vm_map_copy_t *target_copy_map_p);
18989void
18990vm_map_copy_adjust_get_target_copy_map(
18991 vm_map_copy_t copy_map,
18992 vm_map_copy_t *target_copy_map_p)
18993{
18994 vm_map_copy_t target_copy_map;
18995 vm_map_entry_t entry, target_entry;
18996
18997 if (*target_copy_map_p != VM_MAP_COPY_NULL) {
18998 /* the caller already has a "target_copy_map": use it */
18999 return;
19000 }
19001
19002 /* the caller wants us to create a new copy of "copy_map" */
19003 assert(copy_map->type == VM_MAP_COPY_ENTRY_LIST);
19004 target_copy_map = vm_map_copy_allocate(copy_map->type);
19005 target_copy_map->offset = copy_map->offset;
19006 target_copy_map->size = copy_map->size;
19007 target_copy_map->cpy_hdr.page_shift = copy_map->cpy_hdr.page_shift;
19008 for (entry = vm_map_copy_first_entry(copy_map);
19009 entry != vm_map_copy_to_entry(copy_map);
19010 entry = entry->vme_next) {
19011 target_entry = vm_map_copy_entry_create(target_copy_map);
19012 vm_map_entry_copy_full(target_entry, entry);
19013 if (target_entry->is_sub_map) {
19014 vm_map_reference(VME_SUBMAP(target_entry));
19015 } else {
19016 vm_object_reference(VME_OBJECT(target_entry));
19017 }
19018 vm_map_copy_entry_link(
19019 target_copy_map,
19020 vm_map_copy_last_entry(target_copy_map),
19021 target_entry);
19022 }
19023 entry = VM_MAP_ENTRY_NULL;
19024 *target_copy_map_p = target_copy_map;
19025}
19026
19027/*
19028 * Callers of this function must call vm_map_copy_require on
19029 * previously created vm_map_copy_t or pass a newly created
19030 * one to ensure that it hasn't been forged.
19031 */
19032static void
19033vm_map_copy_trim(
19034 vm_map_copy_t copy_map,
19035 uint16_t new_page_shift,
19036 vm_map_offset_t trim_start,
19037 vm_map_offset_t trim_end)
19038{
19039 uint16_t copy_page_shift;
19040 vm_map_entry_t entry, next_entry;
19041
19042 assert(copy_map->type == VM_MAP_COPY_ENTRY_LIST);
19043 assert(copy_map->cpy_hdr.nentries > 0);
19044
19045 trim_start += vm_map_copy_first_entry(copy_map)->vme_start;
19046 trim_end += vm_map_copy_first_entry(copy_map)->vme_start;
19047
19048 /* use the new page_shift to do the clipping */
19049 copy_page_shift = VM_MAP_COPY_PAGE_SHIFT(copy_map);
19050 copy_map->cpy_hdr.page_shift = new_page_shift;
19051
19052 for (entry = vm_map_copy_first_entry(copy_map);
19053 entry != vm_map_copy_to_entry(copy_map);
19054 entry = next_entry) {
19055 next_entry = entry->vme_next;
19056 if (entry->vme_end <= trim_start) {
19057 /* entry fully before trim range: skip */
19058 continue;
19059 }
19060 if (entry->vme_start >= trim_end) {
19061 /* entry fully after trim range: done */
19062 break;
19063 }
19064 /* clip entry if needed */
19065 vm_map_copy_clip_start(copy_map, entry, trim_start);
19066 vm_map_copy_clip_end(copy_map, entry, trim_end);
19067 /* dispose of entry */
19068 copy_map->size -= entry->vme_end - entry->vme_start;
19069 vm_map_copy_entry_unlink(copy_map, entry);
19070 if (entry->is_sub_map) {
19071 vm_map_deallocate(VME_SUBMAP(entry));
19072 } else {
19073 vm_object_deallocate(VME_OBJECT(entry));
19074 }
19075 vm_map_copy_entry_dispose(entry);
19076 entry = VM_MAP_ENTRY_NULL;
19077 }
19078
19079 /* restore copy_map's original page_shift */
19080 copy_map->cpy_hdr.page_shift = copy_page_shift;
19081}
19082
19083/*
19084 * Make any necessary adjustments to "copy_map" to allow it to be
19085 * mapped into "target_map".
19086 * If no changes were necessary, "target_copy_map" points to the
19087 * untouched "copy_map".
19088 * If changes are necessary, changes will be made to "target_copy_map".
19089 * If "target_copy_map" was NULL, we create a new "vm_map_copy_t" and
19090 * copy the original "copy_map" to it before applying the changes.
19091 * The caller should discard "target_copy_map" if it's not the same as
19092 * the original "copy_map".
19093 */
19094/* TODO4K: also adjust to sub-range in the copy_map -> add start&end? */
19095kern_return_t
19096vm_map_copy_adjust_to_target(
19097 vm_map_copy_t src_copy_map,
19098 vm_map_offset_ut offset_u,
19099 vm_map_size_ut size_u,
19100 vm_map_t target_map,
19101 boolean_t copy,
19102 vm_map_copy_t *target_copy_map_p,
19103 vm_map_offset_t *overmap_start_p,
19104 vm_map_offset_t *overmap_end_p,
19105 vm_map_offset_t *trimmed_start_p)
19106{
19107 vm_map_copy_t copy_map, target_copy_map;
19108 vm_map_size_t target_size;
19109 vm_map_size_t src_copy_map_size;
19110 vm_map_size_t overmap_start, overmap_end;
19111 int misalignments;
19112 vm_map_entry_t entry, target_entry;
19113 vm_map_offset_t addr_adjustment;
19114 vm_map_offset_t new_start, new_end;
19115 int copy_page_mask, target_page_mask;
19116 uint16_t copy_page_shift, target_page_shift;
19117 vm_map_offset_t trimmed_end;
19118 vm_map_size_t map_size;
19119 kern_return_t kr;
19120
19121 /*
19122 * Sanitize any input parameters that are addr/size/prot/inherit
19123 */
19124 kr = vm_map_copy_addr_size_sanitize(
19125 target_map,
19126 offset_u,
19127 size_u,
19128 VM_SANITIZE_CALLER_MACH_MEMORY_ENTRY_MAP_SIZE,
19129 &new_start,
19130 &new_end,
19131 &map_size);
19132 if (__improbable(kr != KERN_SUCCESS)) {
19133 return vm_sanitize_get_kr(kr);
19134 }
19135
19136 /*
19137 * Assert that the vm_map_copy is coming from the right
19138 * zone and hasn't been forged
19139 */
19140 vm_map_copy_require(src_copy_map);
19141 assert(src_copy_map->type == VM_MAP_COPY_ENTRY_LIST);
19142
19143 /*
19144 * Start working with "src_copy_map" but we'll switch
19145 * to "target_copy_map" as soon as we start making adjustments.
19146 */
19147 copy_map = src_copy_map;
19148 src_copy_map_size = src_copy_map->size;
19149
19150 copy_page_shift = VM_MAP_COPY_PAGE_SHIFT(copy_map);
19151 copy_page_mask = VM_MAP_COPY_PAGE_MASK(copy_map);
19152 target_page_shift = (uint16_t)VM_MAP_PAGE_SHIFT(target_map);
19153 target_page_mask = VM_MAP_PAGE_MASK(target_map);
19154
19155 DEBUG4K_ADJUST("copy_map %p (%d offset 0x%llx size 0x%llx) target_map %p (%d) copy %d offset 0x%llx size 0x%llx target_copy_map %p...\n", copy_map, copy_page_shift, (uint64_t)copy_map->offset, (uint64_t)copy_map->size, target_map, target_page_shift, copy, (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(offset_u), (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(size_u), *target_copy_map_p);
19156
19157 target_copy_map = *target_copy_map_p;
19158 if (target_copy_map != VM_MAP_COPY_NULL) {
19159 vm_map_copy_require(target_copy_map);
19160 }
19161
19162 if (new_end > copy_map->size) {
19163 DEBUG4K_ERROR("copy_map %p (%d->%d) copy_map->size 0x%llx offset 0x%llx size 0x%llx KERN_INVALID_ARGUMENT\n", copy_map, copy_page_shift, target_page_shift, (uint64_t)copy_map->size, (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(offset_u), (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(size_u));
19164 return KERN_INVALID_ARGUMENT;
19165 }
19166
19167 /* trim the end */
19168 trimmed_end = 0;
19169 new_end = VM_MAP_ROUND_PAGE(new_end, target_page_mask);
19170 if (new_end < copy_map->size) {
19171 trimmed_end = src_copy_map_size - new_end;
19172 DEBUG4K_ADJUST("copy_map %p (%d->%d) copy %d offset 0x%llx size 0x%llx target_copy_map %p... trim end from 0x%llx to 0x%llx\n", copy_map, copy_page_shift, target_page_shift, copy, (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(offset_u), (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(size_u), target_copy_map, (uint64_t)new_end, (uint64_t)copy_map->size);
19173 /* get "target_copy_map" if needed and adjust it */
19174 vm_map_copy_adjust_get_target_copy_map(copy_map,
19175 &target_copy_map);
19176 copy_map = target_copy_map;
19177 vm_map_copy_trim(target_copy_map, target_page_shift,
19178 new_end, copy_map->size);
19179 }
19180
19181 /* trim the start */
19182 new_start = VM_MAP_TRUNC_PAGE(new_start, target_page_mask);
19183 if (new_start != 0) {
19184 DEBUG4K_ADJUST("copy_map %p (%d->%d) copy %d offset 0x%llx size 0x%llx target_copy_map %p... trim start from 0x%llx to 0x%llx\n", copy_map, copy_page_shift, target_page_shift, copy, (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(offset_u), (uint64_t)VM_SANITIZE_UNSAFE_UNWRAP(size_u), target_copy_map, (uint64_t)0, (uint64_t)new_start);
19185 /* get "target_copy_map" if needed and adjust it */
19186 vm_map_copy_adjust_get_target_copy_map(copy_map,
19187 &target_copy_map);
19188 copy_map = target_copy_map;
19189 vm_map_copy_trim(target_copy_map, target_page_shift,
19190 0, new_start);
19191 }
19192 *trimmed_start_p = new_start;
19193
19194 /* target_size starts with what's left after trimming */
19195 target_size = copy_map->size;
19196 assertf(target_size == src_copy_map_size - *trimmed_start_p - trimmed_end,
19197 "target_size 0x%llx src_copy_map_size 0x%llx trimmed_start 0x%llx trimmed_end 0x%llx\n",
19198 (uint64_t)target_size, (uint64_t)src_copy_map_size,
19199 (uint64_t)*trimmed_start_p, (uint64_t)trimmed_end);
19200
19201 /* check for misalignments but don't adjust yet */
19202 misalignments = 0;
19203 overmap_start = 0;
19204 overmap_end = 0;
19205 if (copy_page_shift < target_page_shift) {
19206 /*
19207 * Remapping from 4K to 16K: check the VM object alignments
19208 * throughout the range.
19209 * If the start and end of the range are mis-aligned, we can
19210 * over-map to re-align, and adjust the "overmap" start/end
19211 * and "target_size" of the range accordingly.
19212 * If there is any mis-alignment within the range:
19213 * if "copy":
19214 * we can do immediate-copy instead of copy-on-write,
19215 * else:
19216 * no way to remap and share; fail.
19217 */
19218 for (entry = vm_map_copy_first_entry(copy_map);
19219 entry != vm_map_copy_to_entry(copy_map);
19220 entry = entry->vme_next) {
19221 vm_object_offset_t object_offset_start, object_offset_end;
19222
19223 object_offset_start = VME_OFFSET(entry);
19224 object_offset_end = object_offset_start;
19225 object_offset_end += entry->vme_end - entry->vme_start;
19226 if (object_offset_start & target_page_mask) {
19227 if (entry == vm_map_copy_first_entry(copy_map) && !copy) {
19228 overmap_start++;
19229 } else {
19230 misalignments++;
19231 }
19232 }
19233 if (object_offset_end & target_page_mask) {
19234 if (entry->vme_next == vm_map_copy_to_entry(copy_map) && !copy) {
19235 overmap_end++;
19236 } else {
19237 misalignments++;
19238 }
19239 }
19240 }
19241 }
19242 entry = VM_MAP_ENTRY_NULL;
19243
19244 /* decide how to deal with misalignments */
19245 assert(overmap_start <= 1);
19246 assert(overmap_end <= 1);
19247 if (!overmap_start && !overmap_end && !misalignments) {
19248 /* copy_map is properly aligned for target_map ... */
19249 if (*trimmed_start_p) {
19250 /* ... but we trimmed it, so still need to adjust */
19251 } else {
19252 /* ... and we didn't trim anything: we're done */
19253 if (target_copy_map == VM_MAP_COPY_NULL) {
19254 target_copy_map = copy_map;
19255 }
19256 *target_copy_map_p = target_copy_map;
19257 *overmap_start_p = 0;
19258 *overmap_end_p = 0;
19259 DEBUG4K_ADJUST("copy_map %p (%d offset 0x%llx size 0x%llx) target_map %p (%d) copy %d target_copy_map %p (%d offset 0x%llx size 0x%llx) -> trimmed 0x%llx overmap start 0x%llx end 0x%llx KERN_SUCCESS\n", copy_map, copy_page_shift, (uint64_t)copy_map->offset, (uint64_t)copy_map->size, target_map, target_page_shift, copy, *target_copy_map_p, VM_MAP_COPY_PAGE_SHIFT(*target_copy_map_p), (uint64_t)(*target_copy_map_p)->offset, (uint64_t)(*target_copy_map_p)->size, (uint64_t)*trimmed_start_p, (uint64_t)*overmap_start_p, (uint64_t)*overmap_end_p);
19260 return KERN_SUCCESS;
19261 }
19262 } else if (misalignments && !copy) {
19263 /* can't "share" if misaligned */
19264 DEBUG4K_ADJUST("unsupported sharing\n");
19265#if MACH_ASSERT
19266 if (debug4k_panic_on_misaligned_sharing) {
19267 panic("DEBUG4k %s:%d unsupported sharing", __FUNCTION__, __LINE__);
19268 }
19269#endif /* MACH_ASSERT */
19270 DEBUG4K_ADJUST("copy_map %p (%d) target_map %p (%d) copy %d target_copy_map %p -> KERN_NOT_SUPPORTED\n", copy_map, copy_page_shift, target_map, target_page_shift, copy, *target_copy_map_p);
19271 return KERN_NOT_SUPPORTED;
19272 } else {
19273 /* can't virtual-copy if misaligned (but can physical-copy) */
19274 DEBUG4K_ADJUST("mis-aligned copying\n");
19275 }
19276
19277 /* get a "target_copy_map" if needed and switch to it */
19278 vm_map_copy_adjust_get_target_copy_map(copy_map, &target_copy_map);
19279 copy_map = target_copy_map;
19280
19281 if (misalignments && copy) {
19282 vm_map_size_t target_copy_map_size;
19283
19284 /*
19285 * Can't do copy-on-write with misaligned mappings.
19286 * Replace the mappings with a physical copy of the original
19287 * mappings' contents.
19288 */
19289 target_copy_map_size = target_copy_map->size;
19290 kr = vm_map_copy_to_physcopy(target_copy_map, target_map);
19291 if (kr != KERN_SUCCESS) {
19292 return kr;
19293 }
19294 *target_copy_map_p = target_copy_map;
19295 *overmap_start_p = 0;
19296 *overmap_end_p = target_copy_map->size - target_copy_map_size;
19297 DEBUG4K_ADJUST("copy_map %p (%d offset 0x%llx size 0x%llx) target_map %p (%d) copy %d target_copy_map %p (%d offset 0x%llx size 0x%llx)-> trimmed 0x%llx overmap start 0x%llx end 0x%llx PHYSCOPY\n", copy_map, copy_page_shift, (uint64_t)copy_map->offset, (uint64_t)copy_map->size, target_map, target_page_shift, copy, *target_copy_map_p, VM_MAP_COPY_PAGE_SHIFT(*target_copy_map_p), (uint64_t)(*target_copy_map_p)->offset, (uint64_t)(*target_copy_map_p)->size, (uint64_t)*trimmed_start_p, (uint64_t)*overmap_start_p, (uint64_t)*overmap_end_p);
19298 return KERN_SUCCESS;
19299 }
19300
19301 /* apply the adjustments */
19302 misalignments = 0;
19303 overmap_start = 0;
19304 overmap_end = 0;
19305 /* remove copy_map->offset, so that everything starts at offset 0 */
19306 addr_adjustment = copy_map->offset;
19307 /* also remove whatever we trimmed from the start */
19308 addr_adjustment += *trimmed_start_p;
19309 for (target_entry = vm_map_copy_first_entry(target_copy_map);
19310 target_entry != vm_map_copy_to_entry(target_copy_map);
19311 target_entry = target_entry->vme_next) {
19312 vm_object_offset_t object_offset_start, object_offset_end;
19313
19314 DEBUG4K_ADJUST("copy %p (%d 0x%llx 0x%llx) entry %p [ 0x%llx 0x%llx ] object %p offset 0x%llx BEFORE\n", target_copy_map, VM_MAP_COPY_PAGE_SHIFT(target_copy_map), target_copy_map->offset, (uint64_t)target_copy_map->size, target_entry, (uint64_t)target_entry->vme_start, (uint64_t)target_entry->vme_end, VME_OBJECT(target_entry), VME_OFFSET(target_entry));
19315 object_offset_start = VME_OFFSET(target_entry);
19316 if (object_offset_start & target_page_mask) {
19317 DEBUG4K_ADJUST("copy %p (%d 0x%llx 0x%llx) entry %p [ 0x%llx 0x%llx ] object %p offset 0x%llx misaligned at start\n", target_copy_map, VM_MAP_COPY_PAGE_SHIFT(target_copy_map), target_copy_map->offset, (uint64_t)target_copy_map->size, target_entry, (uint64_t)target_entry->vme_start, (uint64_t)target_entry->vme_end, VME_OBJECT(target_entry), VME_OFFSET(target_entry));
19318 if (target_entry == vm_map_copy_first_entry(target_copy_map)) {
19319 /*
19320 * start of 1st entry is mis-aligned:
19321 * re-adjust by over-mapping.
19322 */
19323 overmap_start = object_offset_start - trunc_page_mask_64(object_offset_start, target_page_mask);
19324 DEBUG4K_ADJUST("entry %p offset 0x%llx copy %d -> overmap_start 0x%llx\n", target_entry, VME_OFFSET(target_entry), copy, (uint64_t)overmap_start);
19325 VME_OFFSET_SET(target_entry, VME_OFFSET(target_entry) - overmap_start);
19326 } else {
19327 misalignments++;
19328 DEBUG4K_ADJUST("entry %p offset 0x%llx copy %d -> misalignments %d\n", target_entry, VME_OFFSET(target_entry), copy, misalignments);
19329 assert(copy);
19330 }
19331 }
19332
19333 if (target_entry == vm_map_copy_first_entry(target_copy_map)) {
19334 target_size += overmap_start;
19335 } else {
19336 target_entry->vme_start += overmap_start;
19337 }
19338 target_entry->vme_end += overmap_start;
19339
19340 object_offset_end = VME_OFFSET(target_entry) + target_entry->vme_end - target_entry->vme_start;
19341 if (object_offset_end & target_page_mask) {
19342 DEBUG4K_ADJUST("copy %p (%d 0x%llx 0x%llx) entry %p [ 0x%llx 0x%llx ] object %p offset 0x%llx misaligned at end\n", target_copy_map, VM_MAP_COPY_PAGE_SHIFT(target_copy_map), target_copy_map->offset, (uint64_t)target_copy_map->size, target_entry, (uint64_t)target_entry->vme_start, (uint64_t)target_entry->vme_end, VME_OBJECT(target_entry), VME_OFFSET(target_entry));
19343 if (target_entry->vme_next == vm_map_copy_to_entry(target_copy_map)) {
19344 /*
19345 * end of last entry is mis-aligned: re-adjust by over-mapping.
19346 */
19347 overmap_end = round_page_mask_64(object_offset_end, target_page_mask) - object_offset_end;
19348 DEBUG4K_ADJUST("entry %p offset 0x%llx copy %d -> overmap_end 0x%llx\n", target_entry, VME_OFFSET(target_entry), copy, (uint64_t)overmap_end);
19349 target_entry->vme_end += overmap_end;
19350 target_size += overmap_end;
19351 } else {
19352 misalignments++;
19353 DEBUG4K_ADJUST("entry %p offset 0x%llx copy %d -> misalignments %d\n", target_entry, VME_OFFSET(target_entry), copy, misalignments);
19354 assert(copy);
19355 }
19356 }
19357 target_entry->vme_start -= addr_adjustment;
19358 target_entry->vme_end -= addr_adjustment;
19359 DEBUG4K_ADJUST("copy %p (%d 0x%llx 0x%llx) entry %p [ 0x%llx 0x%llx ] object %p offset 0x%llx AFTER\n", target_copy_map, VM_MAP_COPY_PAGE_SHIFT(target_copy_map), target_copy_map->offset, (uint64_t)target_copy_map->size, target_entry, (uint64_t)target_entry->vme_start, (uint64_t)target_entry->vme_end, VME_OBJECT(target_entry), VME_OFFSET(target_entry));
19360 }
19361
19362 target_copy_map->size = target_size;
19363 target_copy_map->offset += overmap_start;
19364 target_copy_map->offset -= addr_adjustment;
19365 target_copy_map->cpy_hdr.page_shift = target_page_shift;
19366
19367// assert(VM_MAP_PAGE_ALIGNED(target_copy_map->size, target_page_mask));
19368// assert(VM_MAP_PAGE_ALIGNED(target_copy_map->offset, FOURK_PAGE_MASK));
19369 assert(overmap_start < VM_MAP_PAGE_SIZE(target_map));
19370 assert(overmap_end < VM_MAP_PAGE_SIZE(target_map));
19371
19372 *target_copy_map_p = target_copy_map;
19373 *overmap_start_p = overmap_start;
19374 *overmap_end_p = overmap_end;
19375
19376 DEBUG4K_ADJUST("copy_map %p (%d offset 0x%llx size 0x%llx) target_map %p (%d) copy %d target_copy_map %p (%d offset 0x%llx size 0x%llx) -> trimmed 0x%llx overmap start 0x%llx end 0x%llx KERN_SUCCESS\n", copy_map, copy_page_shift, (uint64_t)copy_map->offset, (uint64_t)copy_map->size, target_map, target_page_shift, copy, *target_copy_map_p, VM_MAP_COPY_PAGE_SHIFT(*target_copy_map_p), (uint64_t)(*target_copy_map_p)->offset, (uint64_t)(*target_copy_map_p)->size, (uint64_t)*trimmed_start_p, (uint64_t)*overmap_start_p, (uint64_t)*overmap_end_p);
19377 return KERN_SUCCESS;
19378}
19379
19380kern_return_t
19381vm_map_range_physical_size(
19382 vm_map_t map,
19383 vm_map_address_t start,
19384 mach_vm_size_t size,
19385 mach_vm_size_t * phys_size)
19386{
19387 kern_return_t kr;
19388 vm_map_copy_t copy_map, target_copy_map;
19389 vm_map_offset_t adjusted_start, adjusted_end;
19390 vm_map_size_t adjusted_size;
19391 vm_prot_t cur_prot, max_prot;
19392 vm_map_offset_t overmap_start, overmap_end, trimmed_start, end;
19393 vm_map_kernel_flags_t vmk_flags;
19394
19395 if (size == 0) {
19396 DEBUG4K_SHARE("map %p start 0x%llx size 0x%llx -> phys_size 0!\n", map, (uint64_t)start, (uint64_t)size);
19397 *phys_size = 0;
19398 return KERN_SUCCESS;
19399 }
19400
19401 adjusted_start = vm_map_trunc_page(start, VM_MAP_PAGE_MASK(map));
19402 adjusted_end = vm_map_round_page(start + size, VM_MAP_PAGE_MASK(map));
19403 if (__improbable(os_add_overflow(start, size, &end) ||
19404 adjusted_end <= adjusted_start)) {
19405 /* wraparound */
19406 printf("%s:%d(start=0x%llx, size=0x%llx) pgmask 0x%x: wraparound\n", __FUNCTION__, __LINE__, (uint64_t)start, (uint64_t)size, VM_MAP_PAGE_MASK(map));
19407 *phys_size = 0;
19408 return KERN_INVALID_ARGUMENT;
19409 }
19410 if (__improbable(vm_map_range_overflows(map, start, size))) {
19411 *phys_size = 0;
19412 return KERN_INVALID_ADDRESS;
19413 }
19414 assert(adjusted_end > adjusted_start);
19415 adjusted_size = adjusted_end - adjusted_start;
19416 *phys_size = adjusted_size;
19417 if (VM_MAP_PAGE_SIZE(map) == PAGE_SIZE) {
19418 return KERN_SUCCESS;
19419 }
19420 if (start == 0) {
19421 adjusted_start = vm_map_trunc_page(start, PAGE_MASK);
19422 adjusted_end = vm_map_round_page(start + size, PAGE_MASK);
19423 if (__improbable(adjusted_end <= adjusted_start)) {
19424 /* wraparound */
19425 printf("%s:%d(start=0x%llx, size=0x%llx) pgmask 0x%x: wraparound\n", __FUNCTION__, __LINE__, (uint64_t)start, (uint64_t)size, PAGE_MASK);
19426 *phys_size = 0;
19427 return KERN_INVALID_ARGUMENT;
19428 }
19429 assert(adjusted_end > adjusted_start);
19430 adjusted_size = adjusted_end - adjusted_start;
19431 *phys_size = adjusted_size;
19432 return KERN_SUCCESS;
19433 }
19434
19435 vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
19436 vmk_flags.vmkf_copy_pageable = TRUE;
19437 vmk_flags.vmkf_copy_same_map = TRUE;
19438 assert(adjusted_size != 0);
19439 cur_prot = VM_PROT_NONE; /* legacy mode */
19440 max_prot = VM_PROT_NONE; /* legacy mode */
19441 vmk_flags.vmkf_remap_legacy_mode = true;
19442 kr = vm_map_copy_extract(map, adjusted_start, adjusted_size,
19443 FALSE /* copy */,
19444 ©_map,
19445 &cur_prot, &max_prot, VM_INHERIT_DEFAULT,
19446 vmk_flags);
19447 if (kr != KERN_SUCCESS) {
19448 DEBUG4K_ERROR("map %p start 0x%llx 0x%llx size 0x%llx 0x%llx kr 0x%x\n", map, (uint64_t)start, (uint64_t)adjusted_start, size, (uint64_t)adjusted_size, kr);
19449 //assert(0);
19450 *phys_size = 0;
19451 return kr;
19452 }
19453 assert(copy_map != VM_MAP_COPY_NULL);
19454 target_copy_map = copy_map;
19455 DEBUG4K_ADJUST("adjusting...\n");
19456 kr = vm_map_copy_adjust_to_target(
19457 copy_map,
19458 start - adjusted_start, /* offset */
19459 size, /* size */
19460 kernel_map,
19461 FALSE, /* copy */
19462 &target_copy_map,
19463 &overmap_start,
19464 &overmap_end,
19465 &trimmed_start);
19466 if (kr == KERN_SUCCESS) {
19467 if (target_copy_map->size != *phys_size) {
19468 DEBUG4K_ADJUST("map %p (%d) start 0x%llx size 0x%llx adjusted_start 0x%llx adjusted_end 0x%llx overmap_start 0x%llx overmap_end 0x%llx trimmed_start 0x%llx phys_size 0x%llx -> 0x%llx\n", map, VM_MAP_PAGE_SHIFT(map), (uint64_t)start, (uint64_t)size, (uint64_t)adjusted_start, (uint64_t)adjusted_end, (uint64_t)overmap_start, (uint64_t)overmap_end, (uint64_t)trimmed_start, (uint64_t)*phys_size, (uint64_t)target_copy_map->size);
19469 }
19470 *phys_size = target_copy_map->size;
19471 } else {
19472 DEBUG4K_ERROR("map %p start 0x%llx 0x%llx size 0x%llx 0x%llx kr 0x%x\n", map, (uint64_t)start, (uint64_t)adjusted_start, size, (uint64_t)adjusted_size, kr);
19473 //assert(0);
19474 *phys_size = 0;
19475 }
19476 vm_map_copy_discard(copy_map);
19477 copy_map = VM_MAP_COPY_NULL;
19478
19479 return kr;
19480}
19481
19482static __attribute__((always_inline, warn_unused_result))
19483kern_return_t
19484vm_map_remap_sanitize(
19485 vm_map_t src_map,
19486 vm_map_t target_map,
19487 vm_map_address_ut address_u,
19488 vm_map_size_ut size_u,
19489 vm_map_offset_ut mask_u,
19490 vm_map_offset_ut memory_address_u,
19491 vm_prot_ut cur_protection_u,
19492 vm_prot_ut max_protection_u,
19493 vm_inherit_ut inheritance_u,
19494 vm_map_kernel_flags_t vmk_flags,
19495 vm_map_address_t *target_addr,
19496 vm_map_address_t *mask,
19497 vm_map_offset_t *memory_address,
19498 vm_map_offset_t *memory_end,
19499 vm_map_size_t *memory_size,
19500 vm_prot_t *cur_protection,
19501 vm_prot_t *max_protection,
19502 vm_inherit_t *inheritance)
19503{
19504 kern_return_t result;
19505 vm_sanitize_flags_t vm_sanitize_flags;
19506
19507 result = vm_sanitize_inherit(inheritance_u, VM_SANITIZE_CALLER_VM_MAP_REMAP,
19508 inheritance);
19509 if (__improbable(result != KERN_SUCCESS)) {
19510 return result;
19511 }
19512
19513 result = vm_sanitize_cur_and_max_prots(cur_protection_u, max_protection_u,
19514 VM_SANITIZE_CALLER_VM_MAP_REMAP, target_map,
19515 cur_protection, max_protection);
19516 if (__improbable(result != KERN_SUCCESS)) {
19517 return result;
19518 }
19519
19520 result = vm_sanitize_mask(mask_u, VM_SANITIZE_CALLER_VM_MAP_REMAP, mask);
19521 if (__improbable(result != KERN_SUCCESS)) {
19522 return result;
19523 }
19524
19525 /*
19526 * If the user is requesting that we return the address of the
19527 * first byte of the data (rather than the base of the page),
19528 * then we use different rounding semantics: specifically,
19529 * we assume that (memory_address, size) describes a region
19530 * all of whose pages we must cover, rather than a base to be truncated
19531 * down and a size to be added to that base. So we figure out
19532 * the highest page that the requested region includes and make
19533 * sure that the size will cover it.
19534 *
19535 * The key example we're worried about it is of the form:
19536 *
19537 * memory_address = 0x1ff0, size = 0x20
19538 *
19539 * With the old semantics, we round down the memory_address to 0x1000
19540 * and round up the size to 0x1000, resulting in our covering *only*
19541 * page 0x1000. With the new semantics, we'd realize that the region covers
19542 * 0x1ff0-0x2010, and compute a size of 0x2000. Thus, we cover both page
19543 * 0x1000 and page 0x2000 in the region we remap.
19544 *
19545 * VM_SANITIZE_FLAGS_REALIGN_START asks for the old (broken) semantics.
19546 */
19547 vm_sanitize_flags = VM_SANITIZE_FLAGS_SIZE_ZERO_FAILS;
19548 if (!vmk_flags.vmf_return_data_addr) {
19549 vm_sanitize_flags |= VM_SANITIZE_FLAGS_REALIGN_START;
19550 }
19551
19552 result = vm_sanitize_addr_size(memory_address_u, size_u,
19553 VM_SANITIZE_CALLER_VM_MAP_REMAP, src_map,
19554 vm_sanitize_flags, memory_address, memory_end,
19555 memory_size);
19556 if (__improbable(result != KERN_SUCCESS)) {
19557 return result;
19558 }
19559
19560 *target_addr = vm_sanitize_addr(target_map, address_u);
19561 return KERN_SUCCESS;
19562}
19563
19564/*
19565 * Routine: vm_remap
19566 *
19567 * Map portion of a task's address space.
19568 * Mapped region must not overlap more than
19569 * one vm memory object. Protections and
19570 * inheritance attributes remain the same
19571 * as in the original task and are out parameters.
19572 * Source and Target task can be identical
19573 * Other attributes are identical as for vm_map()
19574 */
19575kern_return_t
19576vm_map_remap(
19577 vm_map_t target_map,
19578 vm_map_address_ut *address_u,
19579 vm_map_size_ut size_u,
19580 vm_map_offset_ut mask_u,
19581 vm_map_kernel_flags_t vmk_flags,
19582 vm_map_t src_map,
19583 vm_map_offset_ut memory_address_u,
19584 boolean_t copy,
19585 vm_prot_ut *cur_protection_u, /* IN/OUT */
19586 vm_prot_ut *max_protection_u, /* IN/OUT */
19587 vm_inherit_ut inheritance_u)
19588{
19589 vm_map_address_t target_addr, mask;
19590 vm_map_size_t target_size;
19591 vm_map_offset_t memory_address, memory_end;
19592 vm_map_size_t memory_size;
19593 vm_prot_t cur_protection, max_protection;
19594 vm_inherit_t inheritance;
19595 kern_return_t result;
19596 vm_map_entry_t insp_entry = VM_MAP_ENTRY_NULL;
19597 vm_map_copy_t copy_map;
19598 vm_map_offset_t offset_in_mapping;
19599 vm_map_size_t src_page_mask, target_page_mask;
19600 vm_map_size_t initial_size;
19601 VM_MAP_ZAP_DECLARE(zap_list);
19602
19603 vmlp_api_start(VM_MAP_REMAP);
19604
19605 if (target_map == VM_MAP_NULL || src_map == VM_MAP_NULL) {
19606 vmlp_api_end(VM_MAP_REMAP, KERN_INVALID_ARGUMENT);
19607 return KERN_INVALID_ARGUMENT;
19608 }
19609 src_page_mask = VM_MAP_PAGE_MASK(src_map);
19610 target_page_mask = VM_MAP_PAGE_MASK(target_map);
19611
19612 if (src_page_mask != target_page_mask) {
19613 if (copy) {
19614 DEBUG4K_COPY("src_map %p pgsz 0x%x addr 0x%llx size 0x%llx copy %d -> target_map %p pgsz 0x%x\n", src_map, VM_MAP_PAGE_SIZE(src_map), VM_SANITIZE_UNSAFE_UNWRAP(memory_address_u), VM_SANITIZE_UNSAFE_UNWRAP(size_u), copy, target_map, VM_MAP_PAGE_SIZE(target_map));
19615 } else {
19616 DEBUG4K_SHARE("src_map %p pgsz 0x%x addr 0x%llx size 0x%llx copy %d -> target_map %p pgsz 0x%x\n", src_map, VM_MAP_PAGE_SIZE(src_map), VM_SANITIZE_UNSAFE_UNWRAP(memory_address_u), VM_SANITIZE_UNSAFE_UNWRAP(size_u), copy, target_map, VM_MAP_PAGE_SIZE(target_map));
19617 }
19618 }
19619
19620 /*
19621 * Sanitize any input parameters that are addr/size/prot/inherit
19622 */
19623 result = vm_map_remap_sanitize(src_map,
19624 target_map,
19625 *address_u,
19626 size_u,
19627 mask_u,
19628 memory_address_u,
19629 *cur_protection_u,
19630 *max_protection_u,
19631 inheritance_u,
19632 vmk_flags,
19633 &target_addr,
19634 &mask,
19635 &memory_address,
19636 &memory_end,
19637 &memory_size,
19638 &cur_protection,
19639 &max_protection,
19640 &inheritance);
19641 if (__improbable(result != KERN_SUCCESS)) {
19642 result = vm_sanitize_get_kr(result);
19643 vmlp_api_end(VM_MAP_REMAP, result);
19644 return result;
19645 }
19646
19647 vmlp_range_event(target_map, target_addr, memory_size);
19648 vmlp_range_event(src_map, memory_address, memory_size);
19649
19650 if (vmk_flags.vmf_return_data_addr) {
19651 /*
19652 * This is safe to unwrap now that the quantities
19653 * have been validated and rounded up normally.
19654 */
19655 offset_in_mapping = vm_sanitize_offset_in_page(src_map,
19656 memory_address_u);
19657 initial_size = VM_SANITIZE_UNSAFE_UNWRAP(size_u);
19658 } else {
19659 /*
19660 * IMPORTANT:
19661 * This legacy code path is broken: for the range mentioned
19662 * above [ memory_address = 0x1ff0,size = 0x20 ], which spans
19663 * two 4k pages, it yields [ memory_address = 0x1000,
19664 * size = 0x1000 ], which covers only the first 4k page.
19665 * BUT some code unfortunately depends on this bug, so we
19666 * can't fix it without breaking something.
19667 * New code should get automatically opted in the new
19668 * behavior with the new VM_FLAGS_RETURN_DATA_ADDR flags.
19669 */
19670 offset_in_mapping = 0;
19671 initial_size = memory_size;
19672 }
19673
19674 if (vmk_flags.vmf_resilient_media) {
19675 /* must be copy-on-write to be "media resilient" */
19676 if (!copy) {
19677 vmlp_api_end(VM_MAP_REMAP, KERN_INVALID_ARGUMENT);
19678 return KERN_INVALID_ARGUMENT;
19679 }
19680 }
19681
19682 vmk_flags.vmkf_copy_pageable = target_map->hdr.entries_pageable;
19683 vmk_flags.vmkf_copy_same_map = (src_map == target_map);
19684
19685 assert(memory_size != 0);
19686 result = vm_map_copy_extract(src_map,
19687 memory_address,
19688 memory_size,
19689 copy, ©_map,
19690 &cur_protection, /* IN/OUT */
19691 &max_protection, /* IN/OUT */
19692 inheritance,
19693 vmk_flags);
19694 if (result != KERN_SUCCESS) {
19695 vmlp_api_end(VM_MAP_REMAP, result);
19696 return result;
19697 }
19698 assert(copy_map != VM_MAP_COPY_NULL);
19699
19700 /*
19701 * Handle the policy for vm map ranges
19702 *
19703 * If the maps differ, the target_map policy applies like for vm_map()
19704 * For same mapping remaps, we preserve the range.
19705 */
19706 if (vmk_flags.vmkf_copy_same_map) {
19707 vmk_flags.vmkf_range_id = copy_map->orig_range;
19708 } else {
19709 vm_map_kernel_flags_update_range_id(&vmk_flags, target_map, memory_size);
19710 }
19711
19712 target_size = memory_size;
19713 if (src_page_mask != target_page_mask) {
19714 vm_map_copy_t target_copy_map;
19715 vm_map_offset_t overmap_start = 0;
19716 vm_map_offset_t overmap_end = 0;
19717 vm_map_offset_t trimmed_start = 0;
19718
19719 target_copy_map = copy_map; /* can modify "copy_map" itself */
19720 DEBUG4K_ADJUST("adjusting...\n");
19721 result = vm_map_copy_adjust_to_target(
19722 copy_map,
19723 offset_in_mapping, /* offset */
19724 initial_size,
19725 target_map,
19726 copy,
19727 &target_copy_map,
19728 &overmap_start,
19729 &overmap_end,
19730 &trimmed_start);
19731 if (result != KERN_SUCCESS) {
19732 DEBUG4K_COPY("failed to adjust 0x%x\n", result);
19733 vm_map_copy_discard(copy_map);
19734 vmlp_api_end(VM_MAP_REMAP, result);
19735 return result;
19736 }
19737 if (trimmed_start == 0) {
19738 /* nothing trimmed: no adjustment needed */
19739 } else if (trimmed_start >= offset_in_mapping) {
19740 /* trimmed more than offset_in_mapping: nothing left */
19741 assert(overmap_start == 0);
19742 assert(overmap_end == 0);
19743 offset_in_mapping = 0;
19744 } else {
19745 /* trimmed some of offset_in_mapping: adjust */
19746 assert(overmap_start == 0);
19747 assert(overmap_end == 0);
19748 offset_in_mapping -= trimmed_start;
19749 }
19750 offset_in_mapping += overmap_start;
19751 target_size = target_copy_map->size;
19752 }
19753
19754 /*
19755 * Allocate/check a range of free virtual address
19756 * space for the target
19757 */
19758 target_size = vm_map_round_page(target_size, target_page_mask);
19759
19760 if (target_size == 0) {
19761 vm_map_copy_discard(copy_map);
19762 vmlp_api_end(VM_MAP_REMAP, KERN_INVALID_ARGUMENT);
19763 return KERN_INVALID_ARGUMENT;
19764 }
19765
19766 if (__improbable(!vm_map_is_map_size_valid(
19767 target_map, target_size, vmk_flags.vmkf_no_soft_limit))) {
19768 vm_map_copy_discard(copy_map);
19769 return KERN_NO_SPACE;
19770 }
19771
19772 vm_map_lock(target_map);
19773
19774 if (!vmk_flags.vmf_fixed) {
19775 result = vm_map_locate_space_anywhere(target_map, target_size,
19776 mask, vmk_flags, &target_addr, &insp_entry);
19777 } else {
19778 /*
19779 * vm_map_locate_space_fixed will reject overflowing
19780 * target_addr + target_size values
19781 */
19782 result = vm_map_locate_space_fixed(target_map, target_addr,
19783 target_size, mask, vmk_flags, &insp_entry, &zap_list);
19784
19785 if (result == KERN_MEMORY_PRESENT) {
19786 assert(!vmk_flags.vmkf_already);
19787 insp_entry = VM_MAP_ENTRY_NULL;
19788 result = KERN_NO_SPACE;
19789 }
19790 }
19791
19792 if (result == KERN_SUCCESS) {
19793 while (vm_map_copy_first_entry(copy_map) !=
19794 vm_map_copy_to_entry(copy_map)) {
19795 vm_map_entry_t entry = vm_map_copy_first_entry(copy_map);
19796
19797 vm_map_copy_entry_unlink(copy_map, entry);
19798
19799 if (vmk_flags.vmkf_remap_prot_copy) {
19800 /*
19801 * This vm_map_remap() is for a
19802 * vm_protect(VM_PROT_COPY), so the caller
19803 * expects to be allowed to add write access
19804 * to this new mapping. This is done by
19805 * adding VM_PROT_WRITE to each entry's
19806 * max_protection... unless some security
19807 * settings disallow it.
19808 */
19809 bool allow_write = false;
19810 if (entry->vme_permanent) {
19811 /* immutable mapping... */
19812 if ((entry->max_protection & VM_PROT_EXECUTE) &&
19813 developer_mode_state()) {
19814 /*
19815 * ... but executable and
19816 * possibly being debugged,
19817 * so let's allow it to become
19818 * writable, for breakpoints
19819 * and dtrace probes, for
19820 * example.
19821 */
19822 allow_write = true;
19823 } else {
19824 printf("%d[%s] vm_remap(0x%llx,0x%llx) VM_PROT_COPY denied on permanent mapping prot 0x%x/0x%x developer %d\n",
19825 proc_selfpid(),
19826 (get_bsdtask_info(current_task())
19827 ? proc_name_address(get_bsdtask_info(current_task()))
19828 : "?"),
19829 (uint64_t)memory_address,
19830 (uint64_t)memory_size,
19831 entry->protection,
19832 entry->max_protection,
19833 developer_mode_state());
19834 DTRACE_VM6(vm_map_delete_permanent_deny_protcopy,
19835 vm_map_entry_t, entry,
19836 vm_map_offset_t, entry->vme_start,
19837 vm_map_offset_t, entry->vme_end,
19838 vm_prot_t, entry->protection,
19839 vm_prot_t, entry->max_protection,
19840 int, VME_ALIAS(entry));
19841 }
19842 } else {
19843 allow_write = true;
19844 }
19845
19846 /*
19847 * VM_PROT_COPY: allow this mapping to become
19848 * writable, unless it was "permanent".
19849 */
19850 if (allow_write) {
19851 entry->max_protection |= VM_PROT_WRITE;
19852 }
19853 }
19854 if (vmk_flags.vmf_resilient_codesign) {
19855 /* no codesigning -> read-only access */
19856 entry->max_protection = VM_PROT_READ;
19857 entry->protection = VM_PROT_READ;
19858 entry->vme_resilient_codesign = TRUE;
19859 }
19860 entry->vme_start += target_addr;
19861 entry->vme_end += target_addr;
19862 if (vmk_flags.vmf_resilient_media &&
19863 !entry->is_sub_map &&
19864 (VME_OBJECT(entry) == VM_OBJECT_NULL ||
19865 VME_OBJECT(entry)->internal)) {
19866 entry->vme_resilient_media = TRUE;
19867 }
19868 assert(VM_MAP_PAGE_ALIGNED(entry->vme_start, MIN(target_page_mask, PAGE_MASK)));
19869 assert(VM_MAP_PAGE_ALIGNED(entry->vme_end, MIN(target_page_mask, PAGE_MASK)));
19870 assert(VM_MAP_PAGE_ALIGNED(VME_OFFSET(entry), MIN(target_page_mask, PAGE_MASK)));
19871 vm_map_store_entry_link(target_map, insp_entry, entry,
19872 vmk_flags);
19873 insp_entry = entry;
19874 }
19875 }
19876
19877 if (vmk_flags.vmf_resilient_codesign) {
19878 cur_protection = VM_PROT_READ;
19879 max_protection = VM_PROT_READ;
19880 }
19881
19882 if (result == KERN_SUCCESS) {
19883 target_map->size += target_size;
19884 SAVE_HINT_MAP_WRITE(target_map, insp_entry);
19885 }
19886 vm_map_unlock(target_map);
19887
19888 vm_map_zap_dispose(&zap_list);
19889
19890 if (result == KERN_SUCCESS && target_map->wiring_required) {
19891 result = vm_map_wire_nested(target_map, target_addr,
19892 target_addr + target_size, cur_protection, VM_KERN_MEMORY_MLOCK,
19893 TRUE, PMAP_NULL, 0, NULL);
19894 }
19895
19896 if (result == KERN_SUCCESS) {
19897#if KASAN
19898 if (target_map->pmap == kernel_pmap) {
19899 kasan_notify_address(target_addr, target_size);
19900 }
19901#endif
19902 /*
19903 * If requested, return the address of the data pointed to by the
19904 * request, rather than the base of the resulting page.
19905 */
19906 if (vmk_flags.vmf_return_data_addr) {
19907 target_addr += offset_in_mapping;
19908 }
19909
19910 /*
19911 * Update OUT parameters.
19912 */
19913 *address_u = vm_sanitize_wrap_addr(target_addr);
19914
19915 *cur_protection_u = vm_sanitize_wrap_prot(cur_protection);
19916 *max_protection_u = vm_sanitize_wrap_prot(max_protection);
19917 }
19918
19919 if (src_page_mask != target_page_mask) {
19920 DEBUG4K_SHARE("vm_remap(%p 0x%llx 0x%llx copy=%d-> %p 0x%llx 0x%llx result=0x%x\n", src_map, (uint64_t)memory_address, (uint64_t)target_size, copy, target_map, (uint64_t)target_addr, (uint64_t)offset_in_mapping, result);
19921 }
19922 vm_map_copy_discard(copy_map);
19923 copy_map = VM_MAP_COPY_NULL;
19924
19925 vmlp_api_end(VM_MAP_REMAP, result);
19926 return result;
19927}
19928
19929/*
19930 * vm_map_switch_with_sec_override:
19931 *
19932 * Set the address map for the current thread to the specified map.
19933 * Optionally sets the `sec_override` property on the current thread for
19934 * the duration of the switch.
19935 * Returns a struct containing info about the previous map, which should be
19936 * restored with `vm_map_switch_back`
19937 */
19938
19939vm_map_switch_context_t
19940vm_map_switch_with_sec_override(vm_map_t map, boolean_t sec_override)
19941{
19942 thread_t thread = current_thread();
19943 vm_map_t oldmap = thread->map;
19944
19945 /*
19946 * Deactivate the current map and activate the requested map
19947 */
19948 mp_disable_preemption();
19949 PMAP_SWITCH_USER(thread, map, cpu_number());
19950 mp_enable_preemption();
19951
19952 vm_map_lock(map);
19953 task_t task = map->owning_task;
19954 if (task) {
19955 task_reference(task);
19956 }
19957 vm_map_unlock(map);
19958
19959 return (vm_map_switch_context_t) { oldmap, task, sec_override };
19960}
19961
19962void
19963vm_map_switch_back(vm_map_switch_context_t ctx)
19964{
19965 thread_t thread = current_thread();
19966 task_t task = ctx.task;
19967 vm_map_t map = ctx.map;
19968
19969 if (task) {
19970 task_deallocate(task);
19971 } else {
19972 /*
19973 * We want to make sure that vm_map_setup was not called while the
19974 * map was switched. This allows us to guarantee the property that
19975 * we always have a reference on current_map()->owning_task if it is
19976 * not NULL.
19977 */
19978 assert(!thread->map->owning_task);
19979 }
19980
19981 /*
19982 * Restore the original map from prior to vm_map_switch_to
19983 */
19984 mp_disable_preemption();
19985 PMAP_SWITCH_USER(thread, map, cpu_number());
19986 mp_enable_preemption();
19987}
19988
19989static __attribute__((always_inline, warn_unused_result))
19990kern_return_t
19991vm_map_rw_user_sanitize(
19992 vm_map_t map,
19993 vm_map_address_ut addr_u,
19994 vm_size_ut size_u,
19995 vm_sanitize_caller_t vm_sanitize_caller,
19996 vm_map_address_t *addr,
19997 vm_map_address_t *end,
19998 vm_map_size_t *size)
19999{
20000 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH |
20001 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES |
20002 VM_SANITIZE_FLAGS_CHECK_ADDR_RANGE;
20003
20004 return vm_sanitize_addr_size(addr_u, size_u,
20005 vm_sanitize_caller, map,
20006 flags,
20007 addr, end, size);
20008}
20009
20010/*
20011 * Routine: vm_map_write_user
20012 *
20013 * Description:
20014 * Copy out data from a kernel space into space in the
20015 * destination map. The space must already exist in the
20016 * destination map.
20017 * NOTE: This routine should only be called by threads
20018 * which can block on a page fault. i.e. kernel mode user
20019 * threads.
20020 *
20021 */
20022kern_return_t
20023vm_map_write_user(
20024 vm_map_t map,
20025 void *src_p,
20026 vm_map_address_ut dst_addr_u,
20027 vm_size_ut size_u)
20028{
20029 kern_return_t kr;
20030 vm_map_address_t dst_addr, dst_end;
20031 vm_map_size_t size;
20032
20033 /*
20034 * src_p isn't validated: [src_p, src_p + size_u)
20035 * is trusted kernel input.
20036 *
20037 * dst_addr_u and size_u are untrusted and need to be sanitized.
20038 */
20039 kr = vm_map_rw_user_sanitize(map,
20040 dst_addr_u,
20041 size_u,
20042 VM_SANITIZE_CALLER_VM_MAP_WRITE_USER,
20043 &dst_addr,
20044 &dst_end,
20045 &size);
20046 if (__improbable(kr != KERN_SUCCESS)) {
20047 return vm_sanitize_get_kr(kr);
20048 }
20049
20050 if (current_map() == map) {
20051 if (copyout(src_p, dst_addr, size)) {
20052 kr = KERN_INVALID_ADDRESS;
20053 }
20054 } else {
20055 vm_map_switch_context_t switch_ctx;
20056
20057 /* take on the identity of the target map while doing */
20058 /* the transfer */
20059
20060 vm_map_reference(map);
20061 switch_ctx = vm_map_switch_to(map);
20062 if (copyout(src_p, dst_addr, size)) {
20063 kr = KERN_INVALID_ADDRESS;
20064 }
20065 vm_map_switch_back(switch_ctx);
20066 vm_map_deallocate(map);
20067 }
20068 return kr;
20069}
20070
20071/*
20072 * Routine: vm_map_read_user
20073 *
20074 * Description:
20075 * Copy in data from a user space source map into the
20076 * kernel map. The space must already exist in the
20077 * kernel map.
20078 * NOTE: This routine should only be called by threads
20079 * which can block on a page fault. i.e. kernel mode user
20080 * threads.
20081 *
20082 */
20083kern_return_t
20084vm_map_read_user(
20085 vm_map_t map,
20086 vm_map_address_ut src_addr_u,
20087 void *dst_p,
20088 vm_size_ut size_u)
20089{
20090 kern_return_t kr;
20091 vm_map_address_t src_addr, src_end;
20092 vm_map_size_t size;
20093
20094 /*
20095 * dst_p isn't validated: [dst_p, dst_p + size_u)
20096 * is trusted kernel input.
20097 *
20098 * src_addr_u and size_u are untrusted and need to be sanitized.
20099 */
20100 kr = vm_map_rw_user_sanitize(map,
20101 src_addr_u,
20102 size_u,
20103 VM_SANITIZE_CALLER_VM_MAP_READ_USER,
20104 &src_addr,
20105 &src_end,
20106 &size);
20107 if (__improbable(kr != KERN_SUCCESS)) {
20108 return vm_sanitize_get_kr(kr);
20109 }
20110
20111 if (current_map() == map) {
20112 if (copyin(src_addr, dst_p, size)) {
20113 kr = KERN_INVALID_ADDRESS;
20114 }
20115 } else {
20116 vm_map_switch_context_t switch_ctx;
20117
20118 /* take on the identity of the target map while doing */
20119 /* the transfer */
20120
20121 vm_map_reference(map);
20122 switch_ctx = vm_map_switch_to(map);
20123 if (copyin(src_addr, dst_p, size)) {
20124 kr = KERN_INVALID_ADDRESS;
20125 }
20126 vm_map_switch_back(switch_ctx);
20127 vm_map_deallocate(map);
20128 }
20129 return kr;
20130}
20131
20132
20133static __attribute__((always_inline, warn_unused_result))
20134kern_return_t
20135vm_map_check_protection_sanitize(
20136 vm_map_t map,
20137 vm_map_offset_ut start_u,
20138 vm_map_offset_ut end_u,
20139 vm_prot_ut protection_u,
20140 vm_sanitize_caller_t vm_sanitize_caller,
20141 vm_map_offset_t *start,
20142 vm_map_offset_t *end,
20143 vm_prot_t *protection)
20144{
20145 kern_return_t kr;
20146 vm_map_size_t size;
20147
20148 kr = vm_sanitize_addr_end(start_u, end_u, vm_sanitize_caller, map,
20149 VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH, start, end,
20150 &size);
20151 if (__improbable(kr != KERN_SUCCESS)) {
20152 return kr;
20153 }
20154
20155 /*
20156 * Given that the protection is used only for comparisons below
20157 * no sanitization is being applied on it.
20158 */
20159 *protection = VM_SANITIZE_UNSAFE_UNWRAP(protection_u);
20160
20161 return KERN_SUCCESS;
20162}
20163
20164/*
20165 * vm_map_check_protection:
20166 *
20167 * Assert that the target map allows the specified
20168 * privilege on the entire address region given.
20169 * The entire region must be allocated.
20170 */
20171boolean_t
20172vm_map_check_protection(
20173 vm_map_t map,
20174 vm_map_offset_ut start_u,
20175 vm_map_offset_ut end_u,
20176 vm_prot_ut protection_u,
20177 vm_sanitize_caller_t vm_sanitize_caller)
20178{
20179 vm_map_entry_t entry;
20180 vm_map_entry_t tmp_entry;
20181 vm_map_offset_t start;
20182 vm_map_offset_t end;
20183 vm_prot_t protection;
20184 kern_return_t kr;
20185
20186 vmlp_api_start(VM_MAP_CHECK_PROTECTION);
20187
20188 kr = vm_map_check_protection_sanitize(map,
20189 start_u,
20190 end_u,
20191 protection_u,
20192 vm_sanitize_caller,
20193 &start,
20194 &end,
20195 &protection);
20196 if (__improbable(kr != KERN_SUCCESS)) {
20197 kr = vm_sanitize_get_kr(kr);
20198 if (kr == KERN_SUCCESS) {
20199 vmlp_api_end(VM_MAP_CHECK_PROTECTION, 0);
20200 return true;
20201 }
20202 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20203 return false;
20204 }
20205
20206 vm_map_lock(map);
20207 vmlp_range_event(map, start, end - start);
20208
20209 if (start < vm_map_min(map) || end > vm_map_max(map)) {
20210 vm_map_unlock(map);
20211 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20212 return false;
20213 }
20214
20215 if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
20216 vm_map_unlock(map);
20217 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20218 return false;
20219 }
20220
20221 entry = tmp_entry;
20222
20223 while (start < end) {
20224 if (entry == vm_map_to_entry(map)) {
20225 vm_map_unlock(map);
20226 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20227 return false;
20228 }
20229
20230 /*
20231 * No holes allowed!
20232 */
20233
20234 if (start < entry->vme_start) {
20235 vm_map_unlock(map);
20236 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20237 return false;
20238 }
20239
20240 /*
20241 * Check protection associated with entry.
20242 */
20243
20244 if ((entry->protection & protection) != protection) {
20245 vm_map_unlock(map);
20246 vmlp_api_end(VM_MAP_CHECK_PROTECTION, -1);
20247 return false;
20248 }
20249
20250 /* go to next entry */
20251
20252 start = entry->vme_end;
20253 entry = entry->vme_next;
20254 }
20255 vm_map_unlock(map);
20256 vmlp_api_end(VM_MAP_CHECK_PROTECTION, 0);
20257 return true;
20258}
20259
20260kern_return_t
20261vm_map_purgable_control(
20262 vm_map_t map,
20263 vm_map_offset_ut address_u,
20264 vm_purgable_t control,
20265 int *state)
20266{
20267 vm_map_offset_t address;
20268 vm_map_entry_t entry;
20269 vm_object_t object;
20270 kern_return_t kr;
20271 boolean_t was_nonvolatile;
20272
20273 vmlp_api_start(VM_MAP_PURGABLE_CONTROL);
20274
20275 /*
20276 * Vet all the input parameters and current type and state of the
20277 * underlaying object. Return with an error if anything is amiss.
20278 */
20279 if (map == VM_MAP_NULL) {
20280 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_INVALID_ARGUMENT);
20281 return KERN_INVALID_ARGUMENT;
20282 }
20283
20284 if (control != VM_PURGABLE_SET_STATE &&
20285 control != VM_PURGABLE_GET_STATE &&
20286 control != VM_PURGABLE_PURGE_ALL &&
20287 control != VM_PURGABLE_SET_STATE_FROM_KERNEL) {
20288 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_INVALID_ARGUMENT);
20289 return KERN_INVALID_ARGUMENT;
20290 }
20291
20292 if (control == VM_PURGABLE_PURGE_ALL) {
20293 vm_purgeable_object_purge_all();
20294 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_SUCCESS);
20295 return KERN_SUCCESS;
20296 }
20297
20298 if ((control == VM_PURGABLE_SET_STATE ||
20299 control == VM_PURGABLE_SET_STATE_FROM_KERNEL) &&
20300 (((*state & ~(VM_PURGABLE_ALL_MASKS)) != 0) ||
20301 ((*state & VM_PURGABLE_STATE_MASK) > VM_PURGABLE_STATE_MASK))) {
20302 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_INVALID_ARGUMENT);
20303 return KERN_INVALID_ARGUMENT;
20304 }
20305
20306 address = vm_sanitize_addr(map, address_u);
20307
20308 vm_map_lock_read(map);
20309
20310 if (!vm_map_lookup_entry(map, address, &entry) || entry->is_sub_map) {
20311 /*
20312 * Must pass a valid non-submap address.
20313 */
20314 vm_map_unlock_read(map);
20315 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_INVALID_ADDRESS);
20316 return KERN_INVALID_ADDRESS;
20317 }
20318
20319 vmlp_range_event_entry(map, entry);
20320
20321 if ((entry->protection & VM_PROT_WRITE) == 0 &&
20322 control != VM_PURGABLE_GET_STATE) {
20323 /*
20324 * Can't apply purgable controls to something you can't write.
20325 */
20326 vm_map_unlock_read(map);
20327 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_PROTECTION_FAILURE);
20328 return KERN_PROTECTION_FAILURE;
20329 }
20330
20331 object = VME_OBJECT(entry);
20332 if (object == VM_OBJECT_NULL ||
20333 object->purgable == VM_PURGABLE_DENY) {
20334 /*
20335 * Object must already be present and be purgeable.
20336 */
20337 vm_map_unlock_read(map);
20338 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, KERN_INVALID_ARGUMENT);
20339 return KERN_INVALID_ARGUMENT;
20340 }
20341
20342 vm_object_lock(object);
20343
20344#if 00
20345 if (VME_OFFSET(entry) != 0 ||
20346 entry->vme_end - entry->vme_start != object->vo_size) {
20347 /*
20348 * Can only apply purgable controls to the whole (existing)
20349 * object at once.
20350 */
20351 vm_map_unlock_read(map);
20352 vm_object_unlock(object);
20353 return KERN_INVALID_ARGUMENT;
20354 }
20355#endif
20356
20357 assert(!entry->is_sub_map);
20358 assert(!entry->use_pmap); /* purgeable has its own accounting */
20359
20360 vm_map_unlock_read(map);
20361
20362 was_nonvolatile = (object->purgable == VM_PURGABLE_NONVOLATILE);
20363
20364 kr = vm_object_purgable_control(object, control, state);
20365
20366 if (was_nonvolatile &&
20367 object->purgable != VM_PURGABLE_NONVOLATILE &&
20368 map->pmap == kernel_pmap) {
20369#if DEBUG
20370 object->vo_purgeable_volatilizer = kernel_task;
20371#endif /* DEBUG */
20372 }
20373
20374 vm_object_unlock(object);
20375
20376 vmlp_api_end(VM_MAP_PURGABLE_CONTROL, kr);
20377 return kr;
20378}
20379
20380/*
20381 * Query the disposition of a page at the given (entry, offset). Caller must
20382 * hold the map lock exclusively.
20383 */
20384static void
20385vm_map_footprint_query_page_info_exclusive(
20386 vm_map_t map,
20387 vm_map_entry_t map_entry,
20388 vm_map_offset_t curr_s_offset,
20389 int *disposition_p)
20390{
20391 int pmap_disp;
20392 vm_object_t object = VM_OBJECT_NULL;
20393 int disposition;
20394 int effective_page_size;
20395
20396 /*
20397 * XXX: Do *not* assert that the map lock is held. This routine is called
20398 * frequently in a loop and rw-lock assertions have significant overhead
20399 * (rdar://126486334).
20400 */
20401 assert(!map->has_corpse_footprint);
20402 assert(curr_s_offset >= map_entry->vme_start);
20403 assert(curr_s_offset < map_entry->vme_end);
20404
20405 if (map_entry->is_sub_map) {
20406 if (!map_entry->use_pmap) {
20407 /* nested pmap: no footprint */
20408 *disposition_p = 0;
20409 return;
20410 }
20411 } else {
20412 object = VME_OBJECT(map_entry);
20413 if (object == VM_OBJECT_NULL) {
20414 /* nothing mapped here: no need to ask */
20415 *disposition_p = 0;
20416 return;
20417 }
20418 }
20419
20420 effective_page_size = MIN(PAGE_SIZE, VM_MAP_PAGE_SIZE(map));
20421
20422 pmap_disp = 0;
20423
20424 /*
20425 * Query the pmap.
20426 */
20427 pmap_query_page_info(map->pmap, curr_s_offset, &pmap_disp);
20428
20429 /*
20430 * Compute this page's disposition.
20431 */
20432 disposition = 0;
20433
20434 /* deal with "alternate accounting" first */
20435 if (!map_entry->is_sub_map &&
20436 object->vo_no_footprint) {
20437 /* does not count in footprint */
20438// assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20439 } else if (!map_entry->is_sub_map &&
20440 !object->internal &&
20441 object->vo_ledger_tag &&
20442 VM_OBJECT_OWNER(object) != NULL &&
20443 VM_OBJECT_OWNER(object)->map == map) {
20444 /* owned external object: wired pages count in footprint */
20445 assertf(map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20446 if ((((curr_s_offset
20447 - map_entry->vme_start
20448 + VME_OFFSET(map_entry))
20449 / effective_page_size) <
20450 object->wired_page_count)) {
20451 /*
20452 * External object owned by this task: report the first
20453 * "#wired" pages as "resident" (to show that they
20454 * contribute to the footprint) but not "dirty"
20455 * (to avoid double-counting with the fake "owned"
20456 * region we'll report at the end of the address space
20457 * to account for all (mapped or not) owned memory
20458 * owned by this task.
20459 */
20460 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20461 }
20462 } else if (!map_entry->is_sub_map &&
20463 object->internal &&
20464 (object->purgable == VM_PURGABLE_NONVOLATILE ||
20465 (object->purgable == VM_PURGABLE_DENY &&
20466 object->vo_ledger_tag)) &&
20467 VM_OBJECT_OWNER(object) != NULL &&
20468 VM_OBJECT_OWNER(object)->map == map) {
20469 assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20470 if ((((curr_s_offset
20471 - map_entry->vme_start
20472 + VME_OFFSET(map_entry))
20473 / effective_page_size) <
20474 (object->resident_page_count +
20475 vm_compressor_pager_get_count(object->pager)))) {
20476 /*
20477 * Non-volatile purgeable object owned
20478 * by this task: report the first
20479 * "#resident + #compressed" pages as
20480 * "resident" (to show that they
20481 * contribute to the footprint) but not
20482 * "dirty" (to avoid double-counting
20483 * with the fake "non-volatile" region
20484 * we'll report at the end of the
20485 * address space to account for all
20486 * (mapped or not) non-volatile memory
20487 * owned by this task.
20488 */
20489 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20490 }
20491 } else if (!map_entry->is_sub_map &&
20492 object->internal &&
20493 (object->purgable == VM_PURGABLE_VOLATILE ||
20494 object->purgable == VM_PURGABLE_EMPTY) &&
20495 VM_OBJECT_OWNER(object) != NULL &&
20496 VM_OBJECT_OWNER(object)->map == map) {
20497 if (object->internal) {
20498 assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20499 }
20500 if ((((curr_s_offset
20501 - map_entry->vme_start
20502 + VME_OFFSET(map_entry))
20503 / effective_page_size) <
20504 object->wired_page_count)) {
20505 /*
20506 * Volatile|empty purgeable object owned
20507 * by this task: report the first
20508 * "#wired" pages as "resident" (to
20509 * show that they contribute to the
20510 * footprint) but not "dirty" (to avoid
20511 * double-counting with the fake
20512 * "non-volatile" region we'll report
20513 * at the end of the address space to
20514 * account for all (mapped or not)
20515 * non-volatile memory owned by this
20516 * task.
20517 */
20518 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20519 }
20520 } else if (!map_entry->is_sub_map &&
20521 map_entry->iokit_acct &&
20522 object->internal &&
20523 object->purgable == VM_PURGABLE_DENY) {
20524 /*
20525 * Non-purgeable IOKit memory: phys_footprint
20526 * includes the entire virtual mapping.
20527 */
20528 assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20529 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20530 disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
20531 } else if (pmap_disp & (PMAP_QUERY_PAGE_ALTACCT |
20532 PMAP_QUERY_PAGE_COMPRESSED_ALTACCT)) {
20533 /* alternate accounting */
20534#if __arm64__ && (DEVELOPMENT || DEBUG)
20535 if (map->pmap->footprint_was_suspended) {
20536 /*
20537 * The assertion below can fail if dyld
20538 * suspended footprint accounting
20539 * while doing some adjustments to
20540 * this page; the mapping would say
20541 * "use pmap accounting" but the page
20542 * would be marked "alternate
20543 * accounting".
20544 */
20545 } else
20546#endif /* __arm64__ && (DEVELOPMENT || DEBUG) */
20547 {
20548 assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20549 }
20550 disposition = 0;
20551 } else {
20552 if (pmap_disp & PMAP_QUERY_PAGE_PRESENT) {
20553 assertf(map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20554 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20555 disposition |= VM_PAGE_QUERY_PAGE_REF;
20556 if (pmap_disp & PMAP_QUERY_PAGE_INTERNAL) {
20557 disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
20558 } else {
20559 disposition |= VM_PAGE_QUERY_PAGE_EXTERNAL;
20560 }
20561 if (pmap_disp & PMAP_QUERY_PAGE_REUSABLE) {
20562 disposition |= VM_PAGE_QUERY_PAGE_REUSABLE;
20563 }
20564 } else if (pmap_disp & PMAP_QUERY_PAGE_COMPRESSED) {
20565 assertf(map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry);
20566 disposition |= VM_PAGE_QUERY_PAGE_PAGED_OUT;
20567 }
20568 }
20569
20570 *disposition_p = disposition;
20571}
20572
20573kern_return_t
20574vm_map_page_info(
20575 vm_map_t map,
20576 vm_map_offset_ut offset_u,
20577 vm_page_info_flavor_t flavor,
20578 vm_page_info_t info,
20579 mach_msg_type_number_t *count)
20580{
20581 return vm_map_page_range_info_internal(map,
20582 offset_u, /* start of range */
20583 vm_sanitize_compute_ut_end(offset_u, 1), /* this will get rounded in the call to the page boundary */
20584 (int)-1, /* effective_page_shift: unspecified */
20585 flavor,
20586 info,
20587 count);
20588}
20589
20590static __attribute__((always_inline, warn_unused_result))
20591kern_return_t
20592vm_map_page_range_info_sanitize(
20593 vm_map_t map,
20594 vm_map_offset_ut start_offset_u,
20595 vm_map_offset_ut end_offset_u,
20596 vm_map_offset_t effective_page_mask,
20597 vm_map_offset_t *start,
20598 vm_map_offset_t *end,
20599 vm_map_offset_t *offset_in_page)
20600{
20601 kern_return_t retval;
20602 vm_map_size_t size;
20603
20604 /*
20605 * Perform validation against map's mask but don't align start/end,
20606 * as we need for those to be aligned wrt effective_page_mask
20607 */
20608 retval = vm_sanitize_addr_end(start_offset_u, end_offset_u,
20609 VM_SANITIZE_CALLER_VM_MAP_PAGE_RANGE_INFO, map,
20610 VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH |
20611 VM_SANITIZE_FLAGS_GET_UNALIGNED_VALUES, start,
20612 end, &size);
20613 if (retval != KERN_SUCCESS) {
20614 return retval;
20615 }
20616
20617 retval = vm_sanitize_addr_end(start_offset_u, end_offset_u,
20618 VM_SANITIZE_CALLER_VM_MAP_PAGE_RANGE_INFO, effective_page_mask,
20619 VM_SANITIZE_FLAGS_SIZE_ZERO_FALLTHROUGH, start,
20620 end, &size);
20621 if (retval != KERN_SUCCESS) {
20622 return retval;
20623 }
20624
20625 *offset_in_page = vm_sanitize_offset_in_page(effective_page_mask,
20626 start_offset_u);
20627
20628 return KERN_SUCCESS;
20629}
20630
20631kern_return_t
20632vm_map_page_range_info_internal(
20633 vm_map_t map,
20634 vm_map_offset_ut start_offset_u,
20635 vm_map_offset_ut end_offset_u,
20636 int effective_page_shift,
20637 vm_page_info_flavor_t flavor,
20638 vm_page_info_t info,
20639 mach_msg_type_number_t *count)
20640{
20641 vm_map_entry_t map_entry = VM_MAP_ENTRY_NULL;
20642 vm_object_t object = VM_OBJECT_NULL, curr_object = VM_OBJECT_NULL;
20643 vm_page_t m = VM_PAGE_NULL;
20644 kern_return_t retval = KERN_SUCCESS;
20645 int disposition = 0;
20646 int ref_count = 0;
20647 int depth = 0, info_idx = 0;
20648 vm_page_info_basic_t basic_info = 0;
20649 vm_map_offset_t offset_in_page = 0, offset_in_object = 0, curr_offset_in_object = 0;
20650 vm_map_offset_t start = 0, end = 0, curr_s_offset = 0, curr_e_offset = 0;
20651 boolean_t do_region_footprint;
20652 ledger_amount_t ledger_resident = 0, ledger_compressed = 0;
20653 int effective_page_size;
20654 vm_map_offset_t effective_page_mask;
20655
20656 vmlp_api_start(VM_MAP_PAGE_RANGE_INFO_INTERNAL);
20657
20658 switch (flavor) {
20659 case VM_PAGE_INFO_BASIC:
20660 if (*count != VM_PAGE_INFO_BASIC_COUNT) {
20661 /*
20662 * The "vm_page_info_basic_data" structure was not
20663 * properly padded, so allow the size to be off by
20664 * one to maintain backwards binary compatibility...
20665 */
20666 if (*count != VM_PAGE_INFO_BASIC_COUNT - 1) {
20667 vmlp_api_end(VM_MAP_PAGE_RANGE_INFO_INTERNAL, KERN_INVALID_ARGUMENT);
20668 return KERN_INVALID_ARGUMENT;
20669 }
20670 }
20671 break;
20672 default:
20673 vmlp_api_end(VM_MAP_PAGE_RANGE_INFO_INTERNAL, KERN_INVALID_ARGUMENT);
20674 return KERN_INVALID_ARGUMENT;
20675 }
20676
20677 if (effective_page_shift == -1) {
20678 effective_page_shift = vm_self_region_page_shift_safely(map);
20679 if (effective_page_shift == -1) {
20680 vmlp_api_end(VM_MAP_PAGE_RANGE_INFO_INTERNAL, KERN_INVALID_ARGUMENT);
20681 return KERN_INVALID_ARGUMENT;
20682 }
20683 }
20684 effective_page_size = (1 << effective_page_shift);
20685 effective_page_mask = effective_page_size - 1;
20686
20687
20688 retval = vm_map_page_range_info_sanitize(map,
20689 start_offset_u,
20690 end_offset_u,
20691 effective_page_mask,
20692 &start,
20693 &end,
20694 &offset_in_page);
20695 if (retval != KERN_SUCCESS) {
20696 retval = vm_sanitize_get_kr(retval);
20697 vmlp_api_end(VM_MAP_PAGE_RANGE_INFO_INTERNAL, retval);
20698 return retval;
20699 }
20700
20701 assert((end - start) <= MAX_PAGE_RANGE_QUERY);
20702
20703 do_region_footprint = task_self_region_footprint();
20704 disposition = 0;
20705 ref_count = 0;
20706 depth = 0;
20707 info_idx = 0; /* Tracks the next index within the info structure to be filled.*/
20708
20709 vm_map_lock_read(map);
20710 vmlp_range_event(map, start, end - start);
20711 if (__improbable(map->pmap == NULL)) {
20712 /* Some VM tests reach this. (TODO make this more strict, rdar://148290198) */
20713 panic_on_release_builds("null pmap");
20714 } else {
20715 task_ledgers_footprint(map->pmap->ledger, &ledger_resident, &ledger_compressed);
20716 }
20717
20718 for (curr_s_offset = start; curr_s_offset < end;) {
20719 /*
20720 * New lookup needs reset of these variables.
20721 */
20722 curr_object = object = VM_OBJECT_NULL;
20723 offset_in_object = 0;
20724 ref_count = 0;
20725 depth = 0;
20726
20727 if (do_region_footprint &&
20728 curr_s_offset >= vm_map_last_entry(map)->vme_end) {
20729 /*
20730 * Request for "footprint" info about a page beyond
20731 * the end of address space: this must be for
20732 * the fake region vm_map_region_recurse_64()
20733 * reported to account for non-volatile purgeable
20734 * memory owned by this task.
20735 */
20736 disposition = 0;
20737
20738 if (curr_s_offset - vm_map_last_entry(map)->vme_end <=
20739 (unsigned) ledger_compressed) {
20740 /*
20741 * We haven't reported all the "non-volatile
20742 * compressed" pages yet, so report this fake
20743 * page as "compressed".
20744 */
20745 disposition |= VM_PAGE_QUERY_PAGE_PAGED_OUT;
20746 } else {
20747 /*
20748 * We've reported all the non-volatile
20749 * compressed page but not all the non-volatile
20750 * pages , so report this fake page as
20751 * "resident dirty".
20752 */
20753 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20754 disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
20755 disposition |= VM_PAGE_QUERY_PAGE_REF;
20756 }
20757 switch (flavor) {
20758 case VM_PAGE_INFO_BASIC:
20759 basic_info = (vm_page_info_basic_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
20760 basic_info->disposition = disposition;
20761 basic_info->ref_count = 1;
20762 basic_info->object_id = VM_OBJECT_ID_FAKE(map, task_ledgers.purgeable_nonvolatile);
20763 basic_info->offset = 0;
20764 basic_info->depth = 0;
20765
20766 info_idx++;
20767 break;
20768 }
20769 curr_s_offset += effective_page_size;
20770 continue;
20771 }
20772
20773 /*
20774 * First, find the map entry covering "curr_s_offset", going down
20775 * submaps if necessary.
20776 */
20777 if (!vm_map_lookup_entry(map, curr_s_offset, &map_entry)) {
20778 /* no entry -> no object -> no page */
20779
20780 if (curr_s_offset < vm_map_min(map)) {
20781 /*
20782 * Illegal address that falls below map min.
20783 */
20784 curr_e_offset = MIN(end, vm_map_min(map));
20785 } else if (curr_s_offset >= vm_map_max(map)) {
20786 /*
20787 * Illegal address that falls on/after map max.
20788 */
20789 curr_e_offset = end;
20790 } else if (map_entry == vm_map_to_entry(map)) {
20791 /*
20792 * Hit a hole.
20793 */
20794 if (map_entry->vme_next == vm_map_to_entry(map)) {
20795 /*
20796 * Empty map.
20797 */
20798 curr_e_offset = MIN(map->max_offset, end);
20799 } else {
20800 /*
20801 * Hole at start of the map.
20802 */
20803 curr_e_offset = MIN(map_entry->vme_next->vme_start, end);
20804 }
20805 } else {
20806 if (map_entry->vme_next == vm_map_to_entry(map)) {
20807 /*
20808 * Hole at the end of the map.
20809 */
20810 curr_e_offset = MIN(map->max_offset, end);
20811 } else {
20812 curr_e_offset = MIN(map_entry->vme_next->vme_start, end);
20813 }
20814 }
20815
20816 assert(curr_e_offset >= curr_s_offset);
20817
20818 uint64_t num_pages = (curr_e_offset - curr_s_offset) >> effective_page_shift;
20819
20820 void *info_ptr = (void*) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
20821
20822 bzero(info_ptr, num_pages * sizeof(struct vm_page_info_basic));
20823
20824 curr_s_offset = curr_e_offset;
20825
20826 info_idx += num_pages;
20827
20828 continue;
20829 }
20830
20831 /* compute offset from this map entry's start */
20832 offset_in_object = curr_s_offset - map_entry->vme_start;
20833
20834 /* compute offset into this map entry's object (or submap) */
20835 offset_in_object += VME_OFFSET(map_entry);
20836
20837 if (map_entry->is_sub_map) {
20838 vm_map_t sub_map = VM_MAP_NULL;
20839 vm_page_info_t submap_info = 0;
20840 vm_map_offset_t submap_s_offset = 0, submap_e_offset = 0, range_len = 0;
20841
20842 range_len = MIN(map_entry->vme_end, end) - curr_s_offset;
20843
20844 submap_s_offset = offset_in_object;
20845 submap_e_offset = submap_s_offset + range_len;
20846
20847 sub_map = VME_SUBMAP(map_entry);
20848
20849 vm_map_reference(sub_map);
20850 vm_map_unlock_read(map);
20851
20852 submap_info = (vm_page_info_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
20853
20854 assertf(VM_MAP_PAGE_SHIFT(sub_map) >= VM_MAP_PAGE_SHIFT(map),
20855 "Submap page size (%d) differs from current map (%d)\n", VM_MAP_PAGE_SIZE(sub_map), VM_MAP_PAGE_SIZE(map));
20856
20857 retval = vm_map_page_range_info_internal(sub_map,
20858 submap_s_offset,
20859 submap_e_offset,
20860 effective_page_shift,
20861 VM_PAGE_INFO_BASIC,
20862 (vm_page_info_t) submap_info,
20863 count);
20864
20865 assert(retval == KERN_SUCCESS);
20866
20867 vm_map_deallocate(sub_map);
20868 sub_map = VM_MAP_NULL;
20869 vm_map_lock_read(map);
20870
20871 /* Move the "info" index by the number of pages we inspected.*/
20872 info_idx += range_len >> effective_page_shift;
20873
20874 /* Move our current offset by the size of the range we inspected.*/
20875 curr_s_offset += range_len;
20876
20877 continue;
20878 }
20879
20880 object = VME_OBJECT(map_entry);
20881
20882 if (object == VM_OBJECT_NULL) {
20883 /*
20884 * We don't have an object here and, hence,
20885 * no pages to inspect. We'll fill up the
20886 * info structure appropriately.
20887 */
20888
20889 curr_e_offset = MIN(map_entry->vme_end, end);
20890
20891 uint64_t num_pages = (curr_e_offset - curr_s_offset) >> effective_page_shift;
20892
20893 void *info_ptr = (void*) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
20894
20895 bzero(info_ptr, num_pages * sizeof(struct vm_page_info_basic));
20896
20897 curr_s_offset = curr_e_offset;
20898
20899 info_idx += num_pages;
20900
20901 continue;
20902 }
20903
20904 if (do_region_footprint) {
20905 disposition = 0;
20906 if (map->has_corpse_footprint) {
20907 /*
20908 * Query the page info data we saved
20909 * while forking the corpse.
20910 */
20911 vm_map_corpse_footprint_query_page_info(
20912 map,
20913 curr_s_offset,
20914 &disposition);
20915 } else {
20916 /*
20917 * Query the live pmap for footprint info
20918 * about this page.
20919 */
20920 vm_map_footprint_query_page_info_exclusive(
20921 map,
20922 map_entry,
20923 curr_s_offset,
20924 &disposition);
20925 }
20926 switch (flavor) {
20927 case VM_PAGE_INFO_BASIC:
20928 basic_info = (vm_page_info_basic_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
20929 basic_info->disposition = disposition;
20930 basic_info->ref_count = 1;
20931 basic_info->object_id = VM_OBJECT_ID_FAKE(map, task_ledgers.purgeable_nonvolatile);
20932 basic_info->offset = 0;
20933 basic_info->depth = 0;
20934
20935 info_idx++;
20936 break;
20937 }
20938 curr_s_offset += effective_page_size;
20939 continue;
20940 }
20941
20942 vm_object_reference(object);
20943 /*
20944 * Shared mode -- so we can allow other readers
20945 * to grab the lock too.
20946 */
20947 vm_object_lock_shared(object);
20948
20949 curr_e_offset = MIN(map_entry->vme_end, end);
20950
20951 vm_map_unlock_read(map);
20952
20953 map_entry = NULL; /* map is unlocked, the entry is no longer valid. */
20954
20955 curr_object = object;
20956
20957 for (; curr_s_offset < curr_e_offset;) {
20958 if (object == curr_object) {
20959 /* account for our object reference above. */
20960 ref_count = os_ref_get_count_raw(&curr_object->ref_count) - 1;
20961 } else {
20962 ref_count = os_ref_get_count_raw(&curr_object->ref_count);
20963 }
20964
20965 curr_offset_in_object = offset_in_object;
20966
20967 for (;;) {
20968 m = vm_page_lookup(curr_object, vm_object_trunc_page(curr_offset_in_object));
20969
20970 if (m != VM_PAGE_NULL) {
20971 disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
20972 break;
20973 } else {
20974 if (curr_object->internal &&
20975 curr_object->alive &&
20976 !curr_object->terminating &&
20977 curr_object->pager_ready) {
20978 if (vm_object_compressor_pager_state_get(curr_object, vm_object_trunc_page(curr_offset_in_object))
20979 == VM_EXTERNAL_STATE_EXISTS) {
20980 /* the pager has that page */
20981 disposition |= VM_PAGE_QUERY_PAGE_PAGED_OUT;
20982 break;
20983 }
20984 }
20985
20986 /*
20987 * Go down the VM object shadow chain until we find the page
20988 * we're looking for.
20989 */
20990
20991 if (curr_object->shadow != VM_OBJECT_NULL) {
20992 vm_object_t shadow = VM_OBJECT_NULL;
20993
20994 curr_offset_in_object += curr_object->vo_shadow_offset;
20995 shadow = curr_object->shadow;
20996
20997 vm_object_lock_shared(shadow);
20998 vm_object_unlock(curr_object);
20999
21000 curr_object = shadow;
21001 depth++;
21002 continue;
21003 } else {
21004 break;
21005 }
21006 }
21007 }
21008
21009 /* The ref_count is not strictly accurate, it measures the number */
21010 /* of entities holding a ref on the object, they may not be mapping */
21011 /* the object or may not be mapping the section holding the */
21012 /* target page but its still a ball park number and though an over- */
21013 /* count, it picks up the copy-on-write cases */
21014
21015 /* We could also get a picture of page sharing from pmap_attributes */
21016 /* but this would under count as only faulted-in mappings would */
21017 /* show up. */
21018
21019 if ((curr_object == object) && curr_object->shadow) {
21020 disposition |= VM_PAGE_QUERY_PAGE_COPIED;
21021 }
21022
21023 if (!curr_object->internal) {
21024 disposition |= VM_PAGE_QUERY_PAGE_EXTERNAL;
21025 }
21026
21027 if (m != VM_PAGE_NULL) {
21028 if (vm_page_is_fictitious(m)) {
21029 disposition |= VM_PAGE_QUERY_PAGE_FICTITIOUS;
21030 } else {
21031 if (m->vmp_dirty || pmap_is_modified(VM_PAGE_GET_PHYS_PAGE(m))) {
21032 disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
21033 }
21034
21035 if (m->vmp_reference || pmap_is_referenced(VM_PAGE_GET_PHYS_PAGE(m))) {
21036 disposition |= VM_PAGE_QUERY_PAGE_REF;
21037 }
21038
21039 if (m->vmp_q_state == VM_PAGE_ON_SPECULATIVE_Q) {
21040 disposition |= VM_PAGE_QUERY_PAGE_SPECULATIVE;
21041 }
21042
21043 /*
21044 * XXX TODO4K:
21045 * when this routine deals with 4k
21046 * pages, check the appropriate CS bit
21047 * here.
21048 */
21049 if (m->vmp_cs_validated) {
21050 disposition |= VM_PAGE_QUERY_PAGE_CS_VALIDATED;
21051 }
21052 if (m->vmp_cs_tainted) {
21053 disposition |= VM_PAGE_QUERY_PAGE_CS_TAINTED;
21054 }
21055 if (m->vmp_cs_nx) {
21056 disposition |= VM_PAGE_QUERY_PAGE_CS_NX;
21057 }
21058 if (m->vmp_reusable || curr_object->all_reusable) {
21059 disposition |= VM_PAGE_QUERY_PAGE_REUSABLE;
21060 }
21061 }
21062 }
21063
21064 switch (flavor) {
21065 case VM_PAGE_INFO_BASIC:
21066 basic_info = (vm_page_info_basic_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic)));
21067 basic_info->disposition = disposition;
21068 basic_info->ref_count = ref_count;
21069 basic_info->object_id = (vm_object_id_t) (uintptr_t)
21070 VM_KERNEL_ADDRHASH(curr_object);
21071 basic_info->offset =
21072 (memory_object_offset_t) curr_offset_in_object + offset_in_page;
21073 basic_info->depth = depth;
21074
21075 info_idx++;
21076 break;
21077 }
21078
21079 disposition = 0;
21080 offset_in_page = 0; // This doesn't really make sense for any offset other than the starting offset.
21081
21082 /*
21083 * Move to next offset in the range and in our object.
21084 */
21085 curr_s_offset += effective_page_size;
21086 offset_in_object += effective_page_size;
21087 curr_offset_in_object = offset_in_object;
21088
21089 if (curr_object != object) {
21090 vm_object_unlock(curr_object);
21091
21092 curr_object = object;
21093
21094 vm_object_lock_shared(curr_object);
21095 } else {
21096 vm_object_lock_yield_shared(curr_object);
21097 }
21098 }
21099
21100 vm_object_unlock(curr_object);
21101 vm_object_deallocate(curr_object);
21102
21103 vm_map_lock_read(map);
21104 }
21105
21106 vm_map_unlock_read(map);
21107 vmlp_api_end(VM_MAP_PAGE_RANGE_INFO_INTERNAL, retval);
21108 return retval;
21109}
21110
21111static __attribute__((always_inline, warn_unused_result))
21112kern_return_t
21113vm_map_msync_sanitize(
21114 vm_map_t map,
21115 vm_map_address_ut address_u,
21116 vm_map_size_ut size_u,
21117 vm_object_offset_t *address,
21118 vm_map_size_t *size)
21119{
21120 vm_object_offset_t end;
21121 vm_sanitize_flags_t flags = VM_SANITIZE_FLAGS_SIZE_ZERO_SUCCEEDS;
21122
21123
21124 return vm_sanitize_addr_size(address_u, size_u,
21125 VM_SANITIZE_CALLER_VM_MAP_MSYNC,
21126 map, flags, address, &end, size);
21127}
21128
21129/*
21130 * vm_map_msync
21131 *
21132 * Synchronises the memory range specified with its backing store
21133 * image by either flushing or cleaning the contents to the appropriate
21134 * memory manager engaging in a memory object synchronize dialog with
21135 * the manager. The client doesn't return until the manager issues
21136 * m_o_s_completed message. MIG Magically converts user task parameter
21137 * to the task's address map.
21138 *
21139 * interpretation of sync_flags
21140 * VM_SYNC_INVALIDATE - discard pages, only return precious
21141 * pages to manager.
21142 *
21143 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
21144 * - discard pages, write dirty or precious
21145 * pages back to memory manager.
21146 *
21147 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
21148 * - write dirty or precious pages back to
21149 * the memory manager.
21150 *
21151 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
21152 * is a hole in the region, and we would
21153 * have returned KERN_SUCCESS, return
21154 * KERN_INVALID_ADDRESS instead.
21155 *
21156 * NOTE
21157 * The memory object attributes have not yet been implemented, this
21158 * function will have to deal with the invalidate attribute
21159 *
21160 * RETURNS
21161 * KERN_INVALID_TASK Bad task parameter
21162 * KERN_INVALID_ARGUMENT both sync and async were specified.
21163 * KERN_SUCCESS The usual.
21164 * KERN_INVALID_ADDRESS There was a hole in the region.
21165 */
21166
21167kern_return_t
21168vm_map_msync(
21169 vm_map_t map,
21170 vm_map_address_ut address_u,
21171 vm_map_size_ut size_u,
21172 vm_sync_t sync_flags)
21173{
21174 vm_map_entry_t entry;
21175 vm_map_size_t size, amount_left;
21176 vm_object_offset_t address, offset;
21177 vm_object_offset_t start_offset, end_offset;
21178 boolean_t do_sync_req;
21179 boolean_t had_hole = FALSE;
21180 vm_map_offset_t pmap_offset;
21181 kern_return_t kr;
21182
21183 vmlp_api_start(VM_MAP_MSYNC);
21184
21185 if ((sync_flags & VM_SYNC_ASYNCHRONOUS) &&
21186 (sync_flags & VM_SYNC_SYNCHRONOUS)) {
21187 vmlp_api_end(VM_MAP_MSYNC, KERN_INVALID_ARGUMENT);
21188 return KERN_INVALID_ARGUMENT;
21189 }
21190
21191 if (map == VM_MAP_NULL) {
21192 vmlp_api_end(VM_MAP_MSYNC, KERN_INVALID_TASK);
21193 return KERN_INVALID_TASK;
21194 }
21195
21196 kr = vm_map_msync_sanitize(map,
21197 address_u,
21198 size_u,
21199 &address,
21200 &size);
21201 if (VM_MAP_PAGE_MASK(map) < PAGE_MASK) {
21202 DEBUG4K_SHARE("map %p address 0x%llx size 0x%llx flags 0x%x\n", map, (uint64_t)address, (uint64_t)size, sync_flags);
21203 }
21204 if (__improbable(kr != KERN_SUCCESS)) {
21205 kr = vm_sanitize_get_kr(kr);
21206 vmlp_api_end(VM_MAP_MSYNC, kr);
21207 return kr;
21208 }
21209
21210 amount_left = size;
21211
21212 while (amount_left > 0) {
21213 vm_object_size_t flush_size;
21214 vm_object_t object;
21215
21216 vm_map_lock(map);
21217 if (!vm_map_lookup_entry(map,
21218 address,
21219 &entry)) {
21220 vm_map_size_t skip;
21221
21222 /*
21223 * hole in the address map.
21224 */
21225 had_hole = TRUE;
21226
21227 if (sync_flags & VM_SYNC_KILLPAGES) {
21228 /*
21229 * For VM_SYNC_KILLPAGES, there should be
21230 * no holes in the range, since we couldn't
21231 * prevent someone else from allocating in
21232 * that hole and we wouldn't want to "kill"
21233 * their pages.
21234 */
21235 vm_map_unlock(map);
21236 break;
21237 }
21238
21239 /*
21240 * Check for empty map.
21241 */
21242 if (entry == vm_map_to_entry(map) &&
21243 entry->vme_next == entry) {
21244 vm_map_unlock(map);
21245 break;
21246 }
21247 /*
21248 * Check that we don't wrap and that
21249 * we have at least one real map entry.
21250 */
21251 if ((map->hdr.nentries == 0) ||
21252 (entry->vme_next->vme_start < address)) {
21253 vm_map_unlock(map);
21254 break;
21255 }
21256 /*
21257 * Move up to the next entry if needed
21258 */
21259 skip = (entry->vme_next->vme_start - address);
21260 if (skip >= amount_left) {
21261 amount_left = 0;
21262 } else {
21263 amount_left -= skip;
21264 }
21265 address = entry->vme_next->vme_start;
21266 vm_map_unlock(map);
21267 continue;
21268 }
21269
21270 offset = address - entry->vme_start;
21271 pmap_offset = address;
21272
21273 /*
21274 * do we have more to flush than is contained in this
21275 * entry ?
21276 */
21277 if (amount_left + entry->vme_start + offset > entry->vme_end) {
21278 flush_size = entry->vme_end -
21279 (entry->vme_start + offset);
21280 } else {
21281 flush_size = amount_left;
21282 }
21283 amount_left -= flush_size;
21284 address += flush_size;
21285
21286 if (entry->is_sub_map == TRUE) {
21287 vm_map_t local_map;
21288 vm_map_offset_t local_offset;
21289
21290 local_map = VME_SUBMAP(entry);
21291 if (vm_map_is_sealed(local_map)) {
21292 /*
21293 * We could do most of the work with a READER lock on the
21294 * map but we might do some pmap operations which might
21295 * need to be serialized by the WRITER lock.
21296 * Since we can't take a WRITER lock on a sealed map,
21297 * let's just skip this range.
21298 */
21299 vm_map_unlock(map);
21300 continue;
21301 }
21302 local_offset = VME_OFFSET(entry);
21303 vm_map_reference(local_map);
21304 vm_map_unlock(map);
21305 if (vm_map_msync(
21306 local_map,
21307 local_offset,
21308 flush_size,
21309 sync_flags) == KERN_INVALID_ADDRESS) {
21310 had_hole = TRUE;
21311 }
21312 vm_map_deallocate(local_map);
21313 local_map = VM_MAP_NULL;
21314 continue;
21315 }
21316
21317 vmlp_range_event_entry(map, entry);
21318
21319 object = VME_OBJECT(entry);
21320
21321 /*
21322 * We can't sync this object if the object has not been
21323 * created yet
21324 */
21325 if (object == VM_OBJECT_NULL) {
21326 vm_map_unlock(map);
21327 continue;
21328 }
21329 offset += VME_OFFSET(entry);
21330
21331 vm_object_lock(object);
21332
21333 if (sync_flags & (VM_SYNC_KILLPAGES | VM_SYNC_DEACTIVATE)) {
21334 int kill_pages = 0;
21335
21336 if (VM_MAP_PAGE_MASK(map) < PAGE_MASK) {
21337 /*
21338 * This is a destructive operation and so we
21339 * err on the side of limiting the range of
21340 * the operation.
21341 */
21342 start_offset = vm_object_round_page(offset);
21343 end_offset = vm_object_trunc_page(offset + flush_size);
21344
21345 if (end_offset <= start_offset) {
21346 vm_object_unlock(object);
21347 vm_map_unlock(map);
21348 continue;
21349 }
21350
21351 pmap_offset += start_offset - offset;
21352 } else {
21353 start_offset = offset;
21354 end_offset = offset + flush_size;
21355 }
21356
21357 if (sync_flags & VM_SYNC_KILLPAGES) {
21358 if (((os_ref_get_count_raw(&object->ref_count) == 1) ||
21359 ((object->copy_strategy !=
21360 MEMORY_OBJECT_COPY_SYMMETRIC) &&
21361 (object->vo_copy == VM_OBJECT_NULL))) &&
21362 (object->shadow == VM_OBJECT_NULL)) {
21363 if (os_ref_get_count_raw(&object->ref_count) != 1) {
21364 vm_page_stats_reusable.free_shared++;
21365 }
21366 kill_pages = 1;
21367 } else {
21368 kill_pages = -1;
21369 }
21370 }
21371 if (kill_pages != -1) {
21372 boolean_t kill_no_write = FALSE;
21373
21374 if ((entry->protection & VM_PROT_EXECUTE) ||
21375 entry->vme_xnu_user_debug) {
21376 /*
21377 * Executable or user debug pages might be write-protected by
21378 * hardware, so do not attempt to write to these pages.
21379 */
21380 kill_no_write = TRUE;
21381 }
21382 vm_object_deactivate_pages(
21383 object,
21384 start_offset,
21385 (vm_object_size_t) (end_offset - start_offset),
21386 kill_pages,
21387 FALSE, /* reusable_pages */
21388 kill_no_write,
21389 map->pmap,
21390 pmap_offset);
21391 }
21392 vm_object_unlock(object);
21393 vm_map_unlock(map);
21394 continue;
21395 }
21396 /*
21397 * We can't sync this object if there isn't a pager.
21398 * Don't bother to sync internal objects, since there can't
21399 * be any "permanent" storage for these objects anyway.
21400 */
21401 if ((object->pager == MEMORY_OBJECT_NULL) ||
21402 (object->internal) || (object->private)) {
21403 vm_object_unlock(object);
21404 vm_map_unlock(map);
21405 continue;
21406 }
21407 /*
21408 * keep reference on the object until syncing is done
21409 */
21410 vm_object_reference_locked(object);
21411 vm_object_unlock(object);
21412
21413 vm_map_unlock(map);
21414
21415 if (VM_MAP_PAGE_MASK(map) < PAGE_MASK) {
21416 start_offset = vm_object_trunc_page(offset);
21417 end_offset = vm_object_round_page(offset + flush_size);
21418 } else {
21419 start_offset = offset;
21420 end_offset = offset + flush_size;
21421 }
21422
21423 do_sync_req = vm_object_sync(object,
21424 start_offset,
21425 (end_offset - start_offset),
21426 sync_flags & VM_SYNC_INVALIDATE,
21427 ((sync_flags & VM_SYNC_SYNCHRONOUS) ||
21428 (sync_flags & VM_SYNC_ASYNCHRONOUS)),
21429 sync_flags & VM_SYNC_SYNCHRONOUS);
21430
21431 if ((sync_flags & VM_SYNC_INVALIDATE) && object->resident_page_count == 0) {
21432 /*
21433 * clear out the clustering and read-ahead hints
21434 */
21435 vm_object_lock(object);
21436
21437 object->pages_created = 0;
21438 object->pages_used = 0;
21439 object->sequential = 0;
21440 object->last_alloc = 0;
21441
21442 vm_object_unlock(object);
21443 }
21444 vm_object_deallocate(object);
21445 } /* while */
21446
21447 /* for proper msync() behaviour */
21448 if (had_hole == TRUE && (sync_flags & VM_SYNC_CONTIGUOUS)) {
21449 vmlp_api_end(VM_MAP_MSYNC, KERN_INVALID_ADDRESS);
21450 return KERN_INVALID_ADDRESS;
21451 }
21452
21453 vmlp_api_end(VM_MAP_MSYNC, KERN_SUCCESS);
21454 return KERN_SUCCESS;
21455}/* vm_msync */
21456
21457void
21458vm_named_entry_associate_vm_object(
21459 vm_named_entry_t named_entry,
21460 vm_object_t object,
21461 vm_object_offset_t offset,
21462 vm_object_size_t size,
21463 vm_prot_t prot)
21464{
21465 vm_map_copy_t copy;
21466 vm_map_entry_t copy_entry;
21467
21468 assert(!named_entry->is_sub_map);
21469 assert(!named_entry->is_copy);
21470 assert(!named_entry->is_object);
21471 assert(!named_entry->internal);
21472 assert(named_entry->backing.copy == VM_MAP_COPY_NULL);
21473
21474 copy = vm_map_copy_allocate(VM_MAP_COPY_ENTRY_LIST);
21475 copy->offset = offset;
21476 copy->size = size;
21477 copy->cpy_hdr.page_shift = (uint16_t)PAGE_SHIFT;
21478
21479 copy_entry = vm_map_copy_entry_create(copy);
21480 copy_entry->protection = prot;
21481 copy_entry->max_protection = prot;
21482 copy_entry->use_pmap = TRUE;
21483 copy_entry->vme_start = VM_MAP_TRUNC_PAGE(offset, PAGE_MASK);
21484 copy_entry->vme_end = VM_MAP_ROUND_PAGE(offset + size, PAGE_MASK);
21485 VME_OBJECT_SET(copy_entry, object, false, 0);
21486 VME_OFFSET_SET(copy_entry, vm_object_trunc_page(offset));
21487 vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy), copy_entry);
21488
21489 named_entry->backing.copy = copy;
21490 named_entry->is_object = TRUE;
21491 if (object->internal) {
21492 named_entry->internal = TRUE;
21493 }
21494
21495 DEBUG4K_MEMENTRY("named_entry %p copy %p object %p offset 0x%llx size 0x%llx prot 0x%x\n",
21496 named_entry, copy, object, offset, size, prot);
21497}
21498
21499vm_object_t
21500vm_named_entry_to_vm_object(
21501 vm_named_entry_t named_entry)
21502{
21503 vm_map_copy_t copy;
21504 vm_map_entry_t copy_entry;
21505 vm_object_t object;
21506
21507 assert(!named_entry->is_sub_map);
21508 assert(!named_entry->is_copy);
21509 assert(named_entry->is_object);
21510 copy = named_entry->backing.copy;
21511 assert(copy != VM_MAP_COPY_NULL);
21512 /*
21513 * Assert that the vm_map_copy is coming from the right
21514 * zone and hasn't been forged
21515 */
21516 vm_map_copy_require(copy);
21517 assert(copy->cpy_hdr.nentries == 1);
21518 copy_entry = vm_map_copy_first_entry(copy);
21519 object = VME_OBJECT(copy_entry);
21520
21521 DEBUG4K_MEMENTRY("%p -> %p -> %p [0x%llx 0x%llx 0x%llx 0x%x/0x%x ] -> %p offset 0x%llx size 0x%llx prot 0x%x\n", named_entry, copy, copy_entry, (uint64_t)copy_entry->vme_start, (uint64_t)copy_entry->vme_end, copy_entry->vme_offset, copy_entry->protection, copy_entry->max_protection, object, named_entry->offset, named_entry->size, named_entry->protection);
21522
21523 return object;
21524}
21525
21526/*
21527 * Routine: convert_port_entry_to_map
21528 * Purpose:
21529 * Convert from a port specifying an entry or a task
21530 * to a map. Doesn't consume the port ref; produces a map ref,
21531 * which may be null. Unlike convert_port_to_map, the
21532 * port may be task or a named entry backed.
21533 * Conditions:
21534 * Nothing locked.
21535 */
21536
21537vm_map_t
21538convert_port_entry_to_map(
21539 ipc_port_t port)
21540{
21541 vm_map_t map = VM_MAP_NULL;
21542 vm_named_entry_t named_entry;
21543
21544 if (!IP_VALID(port)) {
21545 return VM_MAP_NULL;
21546 }
21547
21548 if (ip_type(port) != IKOT_NAMED_ENTRY) {
21549 return convert_port_to_map(port);
21550 }
21551
21552 named_entry = mach_memory_entry_from_port(port);
21553
21554 if ((named_entry->is_sub_map) &&
21555 (named_entry->protection & VM_PROT_WRITE)) {
21556 map = named_entry->backing.map;
21557 if (map->pmap != PMAP_NULL) {
21558 if (map->pmap == kernel_pmap) {
21559 panic("userspace has access "
21560 "to a kernel map %p", map);
21561 }
21562 pmap_require(map->pmap);
21563 }
21564 vm_map_reference(map);
21565 }
21566
21567 return map;
21568}
21569
21570/*
21571 * Export routines to other components for the things we access locally through
21572 * macros.
21573 */
21574#undef current_map
21575vm_map_t
21576current_map(void)
21577{
21578 return current_map_fast();
21579}
21580
21581/*
21582 * vm_map_reference:
21583 *
21584 * Takes a reference on the specified map.
21585 */
21586void
21587vm_map_reference(
21588 vm_map_t map)
21589{
21590 if (__probable(map != VM_MAP_NULL)) {
21591 vm_map_require(map);
21592 os_ref_retain_raw(&map->map_refcnt, &map_refgrp);
21593 }
21594}
21595
21596/*
21597 * vm_map_deallocate:
21598 *
21599 * Removes a reference from the specified map,
21600 * destroying it if no references remain.
21601 * The map should not be locked.
21602 */
21603void
21604vm_map_deallocate(
21605 vm_map_t map)
21606{
21607 if (__probable(map != VM_MAP_NULL)) {
21608 vm_map_require(map);
21609 if (os_ref_release_raw(&map->map_refcnt, &map_refgrp) == 0) {
21610 vm_map_destroy(map);
21611 }
21612 }
21613}
21614
21615void
21616vm_map_inspect_deallocate(
21617 vm_map_inspect_t map)
21618{
21619 vm_map_deallocate((vm_map_t)map);
21620}
21621
21622void
21623vm_map_read_deallocate(
21624 vm_map_read_t map)
21625{
21626 vm_map_deallocate((vm_map_t)map);
21627}
21628
21629
21630void
21631vm_map_disable_NX(vm_map_t map)
21632{
21633 if (map == NULL) {
21634 return;
21635 }
21636 if (map->pmap == NULL) {
21637 return;
21638 }
21639
21640 pmap_disable_NX(map->pmap);
21641}
21642
21643void
21644vm_map_disallow_data_exec(vm_map_t map)
21645{
21646 if (map == NULL) {
21647 return;
21648 }
21649
21650 map->map_disallow_data_exec = TRUE;
21651}
21652
21653/* XXX Consider making these constants (VM_MAX_ADDRESS and MACH_VM_MAX_ADDRESS)
21654 * more descriptive.
21655 */
21656void
21657vm_map_set_32bit(vm_map_t map)
21658{
21659#if defined(__arm64__)
21660 map->max_offset = pmap_max_offset(FALSE, ARM_PMAP_MAX_OFFSET_DEVICE);
21661#else
21662 map->max_offset = (vm_map_offset_t)VM_MAX_ADDRESS;
21663#endif
21664}
21665
21666
21667void
21668vm_map_set_64bit(vm_map_t map)
21669{
21670#if defined(__arm64__)
21671 map->max_offset = pmap_max_offset(TRUE, ARM_PMAP_MAX_OFFSET_DEVICE);
21672#else
21673 map->max_offset = (vm_map_offset_t)MACH_VM_MAX_ADDRESS;
21674#endif
21675}
21676
21677/*
21678 * Expand the maximum size of an existing map to 64GB.
21679 */
21680void
21681vm_map_set_jumbo(vm_map_t map)
21682{
21683#if defined (__arm64__) && !XNU_TARGET_OS_OSX
21684 vm_map_set_max_addr(map, ~0, false);
21685#else /* arm64 */
21686 (void) map;
21687#endif
21688}
21689
21690#if XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT
21691/*
21692 * Expand the maximum size of an existing map to the maximum supported.
21693 */
21694void
21695vm_map_set_extra_jumbo(vm_map_t map)
21696{
21697#if defined (__arm64__) && !XNU_TARGET_OS_OSX
21698 vm_map_set_max_addr(map, ~0, true);
21699#else /* arm64 */
21700 (void) map;
21701#endif
21702}
21703#endif /* XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT */
21704
21705/*
21706 * This map has a JIT entitlement
21707 */
21708void
21709vm_map_set_jit_entitled(vm_map_t map)
21710{
21711#if defined (__arm64__)
21712 pmap_set_jit_entitled(map->pmap);
21713#else /* arm64 */
21714 (void) map;
21715#endif
21716}
21717
21718void
21719vm_map_set_platform_binary(
21720 vm_map_t map,
21721 bool is_platform_binary)
21722{
21723 /* map should be locked by caller, unless still private */
21724 map->cs_platform_binary = is_platform_binary;
21725}
21726
21727bool
21728vm_map_is_platform_binary(
21729 vm_map_t map)
21730{
21731 /* map should be locked by caller, unless still private */
21732 return map->cs_platform_binary;
21733}
21734
21735/*
21736 * Get status of this maps TPRO flag
21737 */
21738boolean_t
21739vm_map_tpro(vm_map_t map)
21740{
21741#if defined (__arm64e__)
21742 return pmap_get_tpro(map->pmap);
21743#else /* arm64e */
21744 (void) map;
21745 return FALSE;
21746#endif
21747}
21748
21749/*
21750 * This map has TPRO enabled
21751 */
21752void
21753vm_map_set_tpro(vm_map_t map)
21754{
21755#if defined (__arm64e__)
21756 pmap_set_tpro(map->pmap);
21757#else /* arm64e */
21758 (void) map;
21759#endif
21760}
21761
21762
21763
21764/*
21765 * Does this map have TPRO enforcement enabled
21766 */
21767boolean_t
21768vm_map_tpro_enforcement(vm_map_t map)
21769{
21770 return map->tpro_enforcement;
21771}
21772
21773/*
21774 * Set TPRO enforcement for this map
21775 */
21776void
21777vm_map_set_tpro_enforcement(vm_map_t map)
21778{
21779 vmlp_api_start(VM_MAP_SET_TPRO_ENFORCEMENT);
21780 vmlp_range_event_none(map);
21781 if (vm_map_tpro(map)) {
21782 vm_map_lock(map);
21783 map->tpro_enforcement = TRUE;
21784 vm_map_unlock(map);
21785 }
21786 vmlp_api_end(VM_MAP_SET_TPRO_ENFORCEMENT, 0);
21787}
21788
21789/*
21790 * Enable TPRO on the requested region
21791 *
21792 * Note:
21793 * This routine is primarily intended to be called during/soon after map
21794 * creation before the associated task has been released to run. It is only
21795 * currently safe when we have no resident pages.
21796 */
21797boolean_t
21798vm_map_set_tpro_range(
21799 __unused vm_map_t map,
21800 __unused vm_map_address_t start,
21801 __unused vm_map_address_t end)
21802{
21803 vmlp_api_start(VM_MAP_SET_TPRO_RANGE);
21804
21805 vmlp_api_end(VM_MAP_SET_TPRO_RANGE, 0);
21806 return TRUE;
21807}
21808
21809/*
21810 * Expand the maximum size of an existing map.
21811 */
21812void
21813vm_map_set_max_addr(
21814 vm_map_t map,
21815 vm_map_offset_t new_max_offset,
21816 __unused bool extra_jumbo)
21817{
21818 vmlp_api_start(VM_MAP_SET_MAX_ADDR);
21819
21820#if defined(__arm64__)
21821 vm_map_offset_t max_supported_offset;
21822 vm_map_offset_t old_max_offset;
21823 unsigned int option = ARM_PMAP_MAX_OFFSET_JUMBO;
21824
21825 vm_map_lock(map);
21826
21827 vmlp_range_event_none(map);
21828
21829 old_max_offset = map->max_offset;
21830#if XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT
21831 if (extra_jumbo) {
21832 option = ARM_PMAP_MAX_OFFSET_EXTRA_JUMBO;
21833 }
21834#endif /* XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT */
21835 max_supported_offset = pmap_max_offset(vm_map_is_64bit(map), option);
21836
21837 new_max_offset = trunc_page(new_max_offset);
21838
21839 /* The address space cannot be shrunk using this routine. */
21840 if (old_max_offset >= new_max_offset) {
21841 vm_map_unlock(map);
21842 vmlp_api_end(VM_MAP_SET_MAX_ADDR, 0);
21843 return;
21844 }
21845
21846 if (max_supported_offset < new_max_offset) {
21847 new_max_offset = max_supported_offset;
21848 }
21849
21850 map->max_offset = new_max_offset;
21851
21852 /*
21853 * Disable the following chunk of code that extends the "holes" list
21854 * to accomodate a larger VM map.
21855 * In `vm_map_create_options()`, we now set the end of the "holes" list to
21856 * max(map->max_offset, MACH_VM_MAX_ADDRESS) for all platforms.
21857 * MACH_VM_MAX_ADDRESS is the largest virtual address a userspace process
21858 * can map, so any `new_max_offset` value will be <= MACH_VM_MAX_ADDRESS.
21859 * The "holes" list does not need to be adjusted.
21860 */
21861#if 0
21862 if (map->holelistenabled) {
21863 if (map->holes_list->prev->vme_end == old_max_offset) {
21864 /*
21865 * There is already a hole at the end of the map; simply make it bigger.
21866 */
21867 map->holes_list->prev->vme_end = map->max_offset;
21868 } else {
21869 /*
21870 * There is no hole at the end, so we need to create a new hole
21871 * for the new empty space we're creating.
21872 */
21873 struct vm_map_links *new_hole;
21874
21875 new_hole = zalloc_id(ZONE_ID_VM_MAP_HOLES, Z_WAITOK | Z_NOFAIL);
21876 new_hole->start = old_max_offset;
21877 new_hole->end = map->max_offset;
21878 new_hole->prev = map->holes_list->prev;
21879 new_hole->next = (struct vm_map_entry *)map->holes_list;
21880 map->holes_list->prev->vme_next = (struct vm_map_entry *)new_hole;
21881 map->holes_list->prev = (struct vm_map_entry *)new_hole;
21882 }
21883 }
21884#endif
21885
21886 vm_map_unlock(map);
21887#else
21888 (void)map;
21889 (void)new_max_offset;
21890#endif
21891 vmlp_api_end(VM_MAP_SET_MAX_ADDR, 0);
21892}
21893
21894vm_map_offset_t
21895vm_compute_max_offset(boolean_t is64)
21896{
21897#if defined(__arm64__)
21898 return pmap_max_offset(is64, ARM_PMAP_MAX_OFFSET_DEVICE);
21899#else
21900 return is64 ? (vm_map_offset_t)MACH_VM_MAX_ADDRESS : (vm_map_offset_t)VM_MAX_ADDRESS;
21901#endif
21902}
21903
21904void
21905vm_map_get_max_aslr_slide_section(
21906 vm_map_t map __unused,
21907 int64_t *max_sections,
21908 int64_t *section_size)
21909{
21910#if defined(__arm64__)
21911 *max_sections = 3;
21912 *section_size = ARM_TT_TWIG_SIZE;
21913#else
21914 *max_sections = 1;
21915 *section_size = 0;
21916#endif
21917}
21918
21919uint64_t
21920vm_map_get_max_aslr_slide_pages(vm_map_t map)
21921{
21922#if defined(__arm64__)
21923 /* Limit arm64 slide to 16MB to conserve contiguous VA space in the more
21924 * limited embedded address space; this is also meant to minimize pmap
21925 * memory usage on 16KB page systems.
21926 */
21927 return 1 << (24 - VM_MAP_PAGE_SHIFT(map));
21928#else
21929 return 1 << (vm_map_is_64bit(map) ? 16 : 8);
21930#endif
21931}
21932
21933uint64_t
21934vm_map_get_max_loader_aslr_slide_pages(vm_map_t map)
21935{
21936#if defined(__arm64__)
21937 /* We limit the loader slide to 4MB, in order to ensure at least 8 bits
21938 * of independent entropy on 16KB page systems.
21939 */
21940 return 1 << (22 - VM_MAP_PAGE_SHIFT(map));
21941#else
21942 return 1 << (vm_map_is_64bit(map) ? 16 : 8);
21943#endif
21944}
21945
21946boolean_t
21947vm_map_is_64bit(
21948 vm_map_t map)
21949{
21950 return map->max_offset > ((vm_map_offset_t)VM_MAX_ADDRESS);
21951}
21952
21953boolean_t
21954vm_map_has_hard_pagezero(
21955 vm_map_t map,
21956 vm_map_offset_t pagezero_size)
21957{
21958 /*
21959 * XXX FBDP
21960 * We should lock the VM map (for read) here but we can get away
21961 * with it for now because there can't really be any race condition:
21962 * the VM map's min_offset is changed only when the VM map is created
21963 * and when the zero page is established (when the binary gets loaded),
21964 * and this routine gets called only when the task terminates and the
21965 * VM map is being torn down, and when a new map is created via
21966 * load_machfile()/execve().
21967 */
21968 return map->min_offset >= pagezero_size;
21969}
21970
21971/*
21972 * Raise a VM map's maximun offset.
21973 */
21974kern_return_t
21975vm_map_raise_max_offset(
21976 vm_map_t map,
21977 vm_map_offset_t new_max_offset)
21978{
21979 kern_return_t ret;
21980
21981 vmlp_api_start(VM_MAP_RAISE_MAX_OFFSET);
21982
21983 vm_map_lock(map);
21984
21985 vmlp_range_event_none(map);
21986
21987 ret = KERN_INVALID_ADDRESS;
21988
21989 if (new_max_offset >= map->max_offset) {
21990 if (!vm_map_is_64bit(map)) {
21991 if (new_max_offset <= (vm_map_offset_t)VM_MAX_ADDRESS) {
21992 map->max_offset = new_max_offset;
21993 ret = KERN_SUCCESS;
21994 }
21995 } else {
21996 if (new_max_offset <= (vm_map_offset_t)MACH_VM_MAX_ADDRESS) {
21997 map->max_offset = new_max_offset;
21998 ret = KERN_SUCCESS;
21999 }
22000 }
22001 }
22002
22003 vm_map_unlock(map);
22004 vmlp_api_end(VM_MAP_RAISE_MAX_OFFSET, ret);
22005 return ret;
22006}
22007
22008
22009/*
22010 * Raise a VM map's minimum offset.
22011 * To strictly enforce "page zero" reservation.
22012 */
22013kern_return_t
22014vm_map_raise_min_offset(
22015 vm_map_t map,
22016 vm_map_offset_t new_min_offset)
22017{
22018 vm_map_entry_t first_entry;
22019
22020 vmlp_api_start(VM_MAP_RAISE_MIN_OFFSET);
22021
22022 new_min_offset = vm_map_round_page(new_min_offset,
22023 VM_MAP_PAGE_MASK(map));
22024
22025 vm_map_lock(map);
22026
22027 if (new_min_offset < map->min_offset) {
22028 /*
22029 * Can't move min_offset backwards, as that would expose
22030 * a part of the address space that was previously, and for
22031 * possibly good reasons, inaccessible.
22032 */
22033 vm_map_unlock(map);
22034 vmlp_api_end(VM_MAP_RAISE_MIN_OFFSET, KERN_INVALID_ADDRESS);
22035 return KERN_INVALID_ADDRESS;
22036 }
22037 if (new_min_offset >= map->max_offset) {
22038 /* can't go beyond the end of the address space */
22039 vm_map_unlock(map);
22040 vmlp_api_end(VM_MAP_RAISE_MIN_OFFSET, KERN_INVALID_ADDRESS);
22041 return KERN_INVALID_ADDRESS;
22042 }
22043
22044 first_entry = vm_map_first_entry(map);
22045
22046 if (!first_entry->is_sub_map) {
22047 vmlp_range_event_entry(map, first_entry);
22048 }
22049
22050 if (first_entry != vm_map_to_entry(map) &&
22051 first_entry->vme_start < new_min_offset) {
22052 /*
22053 * Some memory was already allocated below the new
22054 * minimun offset. It's too late to change it now...
22055 */
22056 vm_map_unlock(map);
22057 vmlp_api_end(VM_MAP_RAISE_MIN_OFFSET, KERN_NO_SPACE);
22058 return KERN_NO_SPACE;
22059 }
22060
22061 map->min_offset = new_min_offset;
22062
22063 if (map->holelistenabled) {
22064 assert(map->holes_list);
22065 map->holes_list->start = new_min_offset;
22066 assert(new_min_offset < map->holes_list->end);
22067 }
22068
22069 vm_map_unlock(map);
22070
22071 vmlp_api_end(VM_MAP_RAISE_MIN_OFFSET, KERN_SUCCESS);
22072 return KERN_SUCCESS;
22073}
22074
22075/*
22076 * Set the limit on the maximum amount of address space and user wired memory allowed for this map.
22077 * This is basically a copy of the RLIMIT_AS and RLIMIT_MEMLOCK rlimit value maintained by the BSD
22078 * side of the kernel. The limits are checked in the mach VM side, so we keep a copy so we don't
22079 * have to reach over to the BSD data structures.
22080 */
22081
22082uint64_t vm_map_set_size_limit_count = 0;
22083kern_return_t
22084vm_map_set_size_limit(vm_map_t map, uint64_t new_size_limit)
22085{
22086 kern_return_t kr;
22087
22088 vmlp_api_start(VM_MAP_SET_SIZE_LIMIT);
22089
22090 vm_map_lock(map);
22091
22092 vmlp_range_event_none(map);
22093
22094 if (new_size_limit < map->size) {
22095 /* new limit should not be lower than its current size */
22096 DTRACE_VM2(vm_map_set_size_limit_fail,
22097 vm_map_size_t, map->size,
22098 uint64_t, new_size_limit);
22099 kr = KERN_FAILURE;
22100 } else if (new_size_limit == map->size_limit) {
22101 /* no change */
22102 kr = KERN_SUCCESS;
22103 } else {
22104 /* set new limit */
22105 DTRACE_VM2(vm_map_set_size_limit,
22106 vm_map_size_t, map->size,
22107 uint64_t, new_size_limit);
22108 if (new_size_limit != RLIM_INFINITY) {
22109 vm_map_set_size_limit_count++;
22110 }
22111 map->size_limit = new_size_limit;
22112 kr = KERN_SUCCESS;
22113 }
22114 vm_map_unlock(map);
22115 vmlp_api_end(VM_MAP_SET_SIZE_LIMIT, kr);
22116 return kr;
22117}
22118
22119uint64_t vm_map_set_data_limit_count = 0;
22120kern_return_t
22121vm_map_set_data_limit(vm_map_t map, uint64_t new_data_limit)
22122{
22123 kern_return_t kr;
22124
22125 vmlp_api_start(VM_MAP_SET_DATA_LIMIT);
22126
22127 vm_map_lock(map);
22128
22129 vmlp_range_event_none(map);
22130
22131 if (new_data_limit < map->size) {
22132 /* new limit should not be lower than its current size */
22133 DTRACE_VM2(vm_map_set_data_limit_fail,
22134 vm_map_size_t, map->size,
22135 uint64_t, new_data_limit);
22136 kr = KERN_FAILURE;
22137 } else if (new_data_limit == map->data_limit) {
22138 /* no change */
22139 kr = KERN_SUCCESS;
22140 } else {
22141 /* set new limit */
22142 DTRACE_VM2(vm_map_set_data_limit,
22143 vm_map_size_t, map->size,
22144 uint64_t, new_data_limit);
22145 if (new_data_limit != RLIM_INFINITY) {
22146 vm_map_set_data_limit_count++;
22147 }
22148 map->data_limit = new_data_limit;
22149 kr = KERN_SUCCESS;
22150 }
22151 vm_map_unlock(map);
22152 vmlp_api_end(VM_MAP_SET_DATA_LIMIT, kr);
22153 return kr;
22154}
22155
22156void
22157vm_map_set_user_wire_limit(vm_map_t map,
22158 vm_size_t limit)
22159{
22160 vmlp_api_start(VM_MAP_SET_USER_WIRE_LIMIT);
22161 vm_map_lock(map);
22162 vmlp_range_event_none(map);
22163 map->user_wire_limit = limit;
22164 vm_map_unlock(map);
22165 vmlp_api_end(VM_MAP_SET_USER_WIRE_LIMIT, 0);
22166}
22167
22168
22169void
22170vm_map_switch_protect(vm_map_t map,
22171 boolean_t val)
22172{
22173 vmlp_api_start(VM_MAP_SWITCH_PROTECT);
22174 vmlp_range_event_none(map);
22175 vm_map_lock(map);
22176 map->switch_protect = val;
22177 vm_map_unlock(map);
22178 vmlp_api_end(VM_MAP_SWITCH_PROTECT, 0);
22179}
22180
22181extern int cs_process_enforcement_enable;
22182boolean_t
22183vm_map_cs_enforcement(
22184 vm_map_t map)
22185{
22186 if (cs_process_enforcement_enable) {
22187 return TRUE;
22188 }
22189 return map->cs_enforcement;
22190}
22191
22192kern_return_t
22193vm_map_cs_wx_enable(
22194 __unused vm_map_t map)
22195{
22196#if CODE_SIGNING_MONITOR
22197 kern_return_t ret = csm_allow_invalid_code(vm_map_pmap(map));
22198 if ((ret == KERN_SUCCESS) || (ret == KERN_NOT_SUPPORTED)) {
22199 return KERN_SUCCESS;
22200 }
22201 return ret;
22202#else
22203 /* The VM manages WX memory entirely on its own */
22204 return KERN_SUCCESS;
22205#endif
22206}
22207
22208kern_return_t
22209vm_map_csm_allow_jit(
22210 __unused vm_map_t map)
22211{
22212#if CODE_SIGNING_MONITOR
22213 return csm_allow_jit_region(vm_map_pmap(map));
22214#else
22215 /* No code signing monitor to enforce JIT policy */
22216 return KERN_SUCCESS;
22217#endif
22218}
22219
22220void
22221vm_map_cs_debugged_set(
22222 vm_map_t map,
22223 boolean_t val)
22224{
22225 vmlp_api_start(VM_MAP_CS_DEBUGGED_SET);
22226 vm_map_lock(map);
22227 vmlp_range_event_none(map);
22228 map->cs_debugged = val;
22229 vm_map_unlock(map);
22230 vmlp_api_end(VM_MAP_CS_DEBUGGED_SET, 0);
22231}
22232
22233void
22234vm_map_cs_enforcement_set(
22235 vm_map_t map,
22236 boolean_t val)
22237{
22238 vmlp_api_start(VM_MAP_CS_ENFORCEMENT_SET);
22239 vm_map_lock(map);
22240 vmlp_range_event_none(map);
22241 map->cs_enforcement = val;
22242 pmap_set_vm_map_cs_enforced(map->pmap, val);
22243 vm_map_unlock(map);
22244 vmlp_api_end(VM_MAP_CS_ENFORCEMENT_SET, 0);
22245}
22246
22247/*
22248 * IOKit has mapped a region into this map; adjust the pmap's ledgers appropriately.
22249 * phys_footprint is a composite limit consisting of iokit + physmem, so we need to
22250 * bump both counters.
22251 */
22252void
22253vm_map_iokit_mapped_region(vm_map_t map, vm_size_t bytes)
22254{
22255 pmap_t pmap = vm_map_pmap(map);
22256
22257 ledger_credit(pmap->ledger, task_ledgers.iokit_mapped, bytes);
22258 ledger_credit(pmap->ledger, task_ledgers.phys_footprint, bytes);
22259}
22260
22261void
22262vm_map_iokit_unmapped_region(vm_map_t map, vm_size_t bytes)
22263{
22264 pmap_t pmap = vm_map_pmap(map);
22265
22266 ledger_debit(pmap->ledger, task_ledgers.iokit_mapped, bytes);
22267 ledger_debit(pmap->ledger, task_ledgers.phys_footprint, bytes);
22268}
22269
22270/* Add (generate) code signature for memory range */
22271#if CONFIG_DYNAMIC_CODE_SIGNING
22272kern_return_t
22273vm_map_sign(vm_map_t map,
22274 vm_map_offset_t start,
22275 vm_map_offset_t end)
22276{
22277 vm_map_entry_t entry;
22278 vm_map_offset_t entry_start;
22279 vm_object_offset_t entry_offset;
22280 vm_page_t m;
22281 vm_object_t object;
22282
22283 vmlp_api_start(VM_MAP_SIGN);
22284
22285 /*
22286 * Vet all the input parameters and current type and state of the
22287 * underlaying object. Return with an error if anything is amiss.
22288 */
22289 if (map == VM_MAP_NULL) {
22290 vmlp_api_end(VM_MAP_SIGN, KERN_INVALID_ARGUMENT);
22291 return KERN_INVALID_ARGUMENT;
22292 }
22293
22294 if (__improbable(vm_map_range_overflows(map, start, end - start))) {
22295 vmlp_api_end(VM_MAP_SIGN, KERN_INVALID_ADDRESS);
22296 return KERN_INVALID_ADDRESS;
22297 }
22298
22299 vm_map_lock_read(map);
22300
22301 vmlp_range_event(map, start, end - start);
22302
22303 if (!vm_map_lookup_entry(map, start, &entry) || entry->is_sub_map) {
22304 /*
22305 * Must pass a valid non-submap address.
22306 */
22307 vm_map_unlock_read(map);
22308 vmlp_api_end(VM_MAP_SIGN, KERN_INVALID_ADDRESS);
22309 return KERN_INVALID_ADDRESS;
22310 }
22311
22312 if ((entry->vme_start > start) || (entry->vme_end < end)) {
22313 /*
22314 * Map entry doesn't cover the requested range. Not handling
22315 * this situation currently.
22316 */
22317 vm_map_unlock_read(map);
22318 vmlp_api_end(VM_MAP_SIGN, KERN_INVALID_ARGUMENT);
22319 return KERN_INVALID_ARGUMENT;
22320 }
22321
22322 object = VME_OBJECT(entry);
22323 if (object == VM_OBJECT_NULL) {
22324 /*
22325 * Object must already be present or we can't sign.
22326 */
22327 vm_map_unlock_read(map);
22328 vmlp_api_end(VM_MAP_SIGN, KERN_INVALID_ARGUMENT);
22329 return KERN_INVALID_ARGUMENT;
22330 }
22331
22332 vm_object_lock(object);
22333
22334 entry_start = entry->vme_start;
22335 entry_offset = VME_OFFSET(entry);
22336 vm_map_unlock_read(map);
22337 entry = VM_MAP_ENTRY_NULL; /* no longer valid after unlocking map */
22338
22339 while (start < end) {
22340 uint32_t refmod;
22341
22342 m = vm_page_lookup(object,
22343 start - entry_start + entry_offset);
22344 if (m == VM_PAGE_NULL) {
22345 /* shoud we try to fault a page here? we can probably
22346 * demand it exists and is locked for this request */
22347 vm_object_unlock(object);
22348 vmlp_api_end(VM_MAP_SIGN, KERN_FAILURE);
22349 return KERN_FAILURE;
22350 }
22351 /* deal with special page status */
22352 if (m->vmp_busy ||
22353 (m->vmp_unusual && (VMP_ERROR_GET(m) || m->vmp_restart ||
22354 vm_page_is_private(m) || m->vmp_absent))) {
22355 vm_object_unlock(object);
22356 vmlp_api_end(VM_MAP_SIGN, KERN_FAILURE);
22357 return KERN_FAILURE;
22358 }
22359
22360 /* Page is OK... now "validate" it */
22361 /* This is the place where we'll call out to create a code
22362 * directory, later */
22363 /* XXX TODO4K: deal with 4k subpages individually? */
22364 m->vmp_cs_validated = VMP_CS_ALL_TRUE;
22365
22366 /* The page is now "clean" for codesigning purposes. That means
22367 * we don't consider it as modified (wpmapped) anymore. But
22368 * we'll disconnect the page so we note any future modification
22369 * attempts. */
22370 m->vmp_wpmapped = FALSE;
22371 refmod = pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(m));
22372
22373 /* Pull the dirty status from the pmap, since we cleared the
22374 * wpmapped bit */
22375 if ((refmod & VM_MEM_MODIFIED) && !m->vmp_dirty) {
22376 SET_PAGE_DIRTY(m, FALSE);
22377 }
22378
22379 /* On to the next page */
22380 start += PAGE_SIZE;
22381 }
22382 vm_object_unlock(object);
22383
22384 vmlp_api_end(VM_MAP_SIGN, KERN_SUCCESS);
22385 return KERN_SUCCESS;
22386}
22387#endif
22388
22389kern_return_t
22390vm_map_partial_reap(vm_map_t map, unsigned int *reclaimed_resident, unsigned int *reclaimed_compressed)
22391{
22392 vm_map_entry_t entry = VM_MAP_ENTRY_NULL;
22393 vm_map_entry_t next_entry;
22394 kern_return_t kr = KERN_SUCCESS;
22395 VM_MAP_ZAP_DECLARE(zap_list);
22396
22397 vmlp_api_start(VM_MAP_PARTIAL_REAP);
22398
22399 vm_map_lock(map);
22400
22401 for (entry = vm_map_first_entry(map);
22402 entry != vm_map_to_entry(map);
22403 entry = next_entry) {
22404 next_entry = entry->vme_next;
22405
22406 if (!entry->is_sub_map) {
22407 vmlp_range_event_entry(map, entry);
22408 }
22409
22410 if (!entry->is_sub_map &&
22411 VME_OBJECT(entry) &&
22412 (VME_OBJECT(entry)->internal == TRUE) &&
22413 (os_ref_get_count_raw(&VME_OBJECT(entry)->ref_count) == 1)) {
22414 *reclaimed_resident += VME_OBJECT(entry)->resident_page_count;
22415 *reclaimed_compressed += vm_compressor_pager_get_count(VME_OBJECT(entry)->pager);
22416
22417 (void)vm_map_delete(map, entry->vme_start,
22418 entry->vme_end, VM_MAP_REMOVE_NO_YIELD,
22419 KMEM_GUARD_NONE, &zap_list);
22420 }
22421 }
22422
22423 vm_map_unlock(map);
22424
22425 vm_map_zap_dispose(&zap_list);
22426
22427 vmlp_api_end(VM_MAP_PARTIAL_REAP, kr);
22428 return kr;
22429}
22430
22431
22432#if DEVELOPMENT || DEBUG
22433
22434int
22435vm_map_disconnect_page_mappings(
22436 vm_map_t map,
22437 boolean_t do_unnest)
22438{
22439 vm_map_entry_t entry;
22440 ledger_amount_t byte_count = 0;
22441
22442 vmlp_api_start(VM_MAP_DISCONNECT_PAGE_MAPPINGS);
22443
22444 if (do_unnest == TRUE) {
22445#ifndef NO_NESTED_PMAP
22446 vm_map_lock(map);
22447
22448 for (entry = vm_map_first_entry(map);
22449 entry != vm_map_to_entry(map);
22450 entry = entry->vme_next) {
22451 if (entry->is_sub_map && entry->use_pmap) {
22452 /*
22453 * Make sure the range between the start of this entry and
22454 * the end of this entry is no longer nested, so that
22455 * we will only remove mappings from the pmap in use by this
22456 * this task
22457 */
22458 vm_map_clip_unnest(map, entry, entry->vme_start, entry->vme_end);
22459 }
22460 }
22461 vm_map_unlock(map);
22462#endif
22463 }
22464 vm_map_lock_read(map);
22465
22466 ledger_get_balance(map->pmap->ledger, task_ledgers.phys_mem, &byte_count);
22467
22468 for (entry = vm_map_first_entry(map);
22469 entry != vm_map_to_entry(map);
22470 entry = entry->vme_next) {
22471 vmlp_range_event_entry(map, entry);
22472 if (!entry->is_sub_map && ((VME_OBJECT(entry) == 0) ||
22473 (VME_OBJECT(entry)->phys_contiguous))) {
22474 continue;
22475 }
22476 if (entry->is_sub_map) {
22477 assert(!entry->use_pmap);
22478 }
22479
22480 pmap_remove_options(map->pmap, entry->vme_start, entry->vme_end, 0);
22481 }
22482 vm_map_unlock_read(map);
22483
22484 vmlp_api_end(VM_MAP_DISCONNECT_PAGE_MAPPINGS, (int) (byte_count / VM_MAP_PAGE_SIZE(map)));
22485 return (int) (byte_count / VM_MAP_PAGE_SIZE(map));
22486}
22487
22488kern_return_t
22489vm_map_inject_error(vm_map_t map, vm_map_offset_t vaddr)
22490{
22491 vm_object_t object = NULL;
22492 vm_object_offset_t offset;
22493 vm_prot_t prot;
22494 boolean_t wired;
22495 vm_map_version_t version;
22496 vm_map_t real_map;
22497 int result = KERN_FAILURE;
22498
22499 vmlp_api_start(VM_MAP_INJECT_ERROR);
22500
22501 vaddr = vm_map_trunc_page(vaddr, PAGE_MASK);
22502 vm_map_lock(map);
22503
22504 result = vm_map_lookup_and_lock_object(&map, vaddr, VM_PROT_READ,
22505 OBJECT_LOCK_EXCLUSIVE, &version, &object, &offset, &prot, &wired,
22506 NULL, &real_map, NULL);
22507 if (object == NULL) {
22508 result = KERN_MEMORY_ERROR;
22509 } else if (object->pager) {
22510 result = vm_compressor_pager_inject_error(object->pager,
22511 offset);
22512 } else {
22513 result = KERN_MEMORY_PRESENT;
22514 }
22515
22516 if (object != NULL) {
22517 vm_object_unlock(object);
22518 }
22519
22520 if (real_map != map) {
22521 vm_map_unlock(real_map);
22522 }
22523 vm_map_unlock(map);
22524
22525 vmlp_api_end(VM_MAP_INJECT_ERROR, result);
22526 return result;
22527}
22528
22529/* iterate over map entries. Call the first argument block for the number of entries and the second for every entry
22530 * returns: KERN_SUCCESS if iteration completed ok,
22531 * error code if callback returned an error
22532 * KERN_FAILURE if there was a race of adding/removing entries during the iteration and the number of entries
22533 * iterated is different from the number in the first call
22534 */
22535static kern_return_t
22536vm_map_entries_foreach_locked(vm_map_t map, kern_return_t (^count_handler)(int nentries),
22537 kern_return_t (^entry_handler)(void* entry))
22538{
22539 vm_map_lock_assert_held(map);
22540 int nentries = map->hdr.nentries;
22541 kern_return_t error = count_handler(nentries);
22542 if (error) {
22543 return error;
22544 }
22545
22546 /* iterate until we loop back to the map, see get_vmmap_entries() */
22547 vm_map_entry_t entry = vm_map_first_entry(map);
22548 int count = 0;
22549 while (entry != vm_map_to_entry(map)) {
22550 error = entry_handler(entry);
22551 if (error != KERN_SUCCESS) {
22552 return error;
22553 }
22554 entry = entry->vme_next;
22555 ++count;
22556 if (count > nentries) {
22557 /* nentries and entries iteration don't agree on how many entries there are, shouldn't really happen */
22558 return KERN_FAILURE;
22559 }
22560 }
22561 if (count < nentries) {
22562 return KERN_FAILURE;
22563 }
22564 return KERN_SUCCESS;
22565}
22566
22567kern_return_t
22568vm_map_entries_foreach(vm_map_t map, kern_return_t (^count_handler)(int nentries),
22569 kern_return_t (^entry_handler)(void* entry))
22570{
22571 vm_map_lock_read(map);
22572 kern_return_t error = vm_map_entries_foreach_locked(map, count_handler, entry_handler);
22573 vm_map_unlock_read(map);
22574 return error;
22575}
22576
22577/*
22578 * Dump info about the entry into the given buffer.
22579 * return true on success, false if there was not enough space in the give buffer
22580 * argument size in: bytes free in the given buffer, out: bytes written
22581 */
22582kern_return_t
22583vm_map_dump_entry_and_compressor_pager(void* pentry, char *buf, size_t *size)
22584{
22585 size_t insize = *size;
22586 kern_return_t kr;
22587 size_t offset = 0;
22588
22589 *size = 0;
22590 if (sizeof(struct vm_map_entry_info) > insize) {
22591 return KERN_NO_SPACE;
22592 }
22593
22594 vm_map_entry_t entry = (vm_map_entry_t)pentry;
22595 struct vm_map_entry_info *out_entry = (struct vm_map_entry_info*)buf;
22596 out_entry->vmei_start = entry->vme_start;
22597 out_entry->vmei_end = entry->vme_end;
22598 out_entry->vmei_alias = VME_ALIAS(entry);
22599 out_entry->vmei_offset = VME_OFFSET(entry);
22600 out_entry->vmei_is_sub_map = entry->is_sub_map;
22601 out_entry->vmei_protection = entry->protection;
22602 offset += sizeof(struct vm_map_entry_info);
22603
22604 out_entry->vmei_slot_mapping_count = 0;
22605 out_entry->vmei_is_compressor_pager = false;
22606 *size = offset;
22607 if (out_entry->vmei_is_sub_map) {
22608 return KERN_SUCCESS; // TODO: sub_map interrogation not supported yet
22609 }
22610 /* have a vm_object? */
22611 vm_object_t object = VME_OBJECT(entry);
22612 if (object == VM_OBJECT_NULL || !object->internal) {
22613 return KERN_SUCCESS;
22614 }
22615 /* objects has a pager? */
22616 memory_object_t pager = object->pager;
22617 if (pager != MEMORY_OBJECT_NULL) {
22618 return KERN_SUCCESS;
22619 }
22620 bool is_compressor = false;
22621 unsigned int slot_mapping_count = 0;
22622 size_t pager_info_size = insize - offset;
22623 kr = vm_compressor_pager_dump(pager, buf + offset, &pager_info_size, &is_compressor, &slot_mapping_count);
22624 if (kr != KERN_SUCCESS) {
22625 /* didn't have enough space for everything we want to write, caller needs to retry */
22626 return kr;
22627 }
22628 offset += pager_info_size;
22629 /* if we got here, is_compressor should be true due to the object->internal check above, so this assignment
22630 * is just for sanity sake */
22631 out_entry->vmei_is_compressor_pager = is_compressor;
22632 out_entry->vmei_slot_mapping_count = slot_mapping_count;
22633 *size = offset;
22634 return KERN_SUCCESS;
22635}
22636
22637
22638#endif
22639
22640
22641#if CONFIG_FREEZE
22642
22643
22644extern struct freezer_context freezer_context_global;
22645AbsoluteTime c_freezer_last_yield_ts = 0;
22646
22647extern unsigned int memorystatus_freeze_private_shared_pages_ratio;
22648extern unsigned int memorystatus_freeze_shared_mb_per_process_max;
22649
22650kern_return_t
22651vm_map_freeze(
22652 task_t task,
22653 unsigned int *purgeable_count,
22654 unsigned int *wired_count,
22655 unsigned int *clean_count,
22656 unsigned int *dirty_count,
22657 unsigned int dirty_budget,
22658 unsigned int *shared_count,
22659 int *freezer_error_code,
22660 boolean_t eval_only)
22661{
22662 vm_map_entry_t entry2 = VM_MAP_ENTRY_NULL;
22663 kern_return_t kr = KERN_SUCCESS;
22664 boolean_t evaluation_phase = TRUE;
22665 vm_object_t cur_shared_object = NULL;
22666 int cur_shared_obj_ref_cnt = 0;
22667 unsigned int dirty_private_count = 0, dirty_shared_count = 0, obj_pages_snapshot = 0;
22668
22669 vmlp_api_start(VM_MAP_FREEZE);
22670
22671 *purgeable_count = *wired_count = *clean_count = *dirty_count = *shared_count = 0;
22672
22673 /*
22674 * We need the exclusive lock here so that we can
22675 * block any page faults or lookups while we are
22676 * in the middle of freezing this vm map.
22677 */
22678 vm_map_t map = task->map;
22679
22680 vm_map_lock(map);
22681
22682 assert(VM_CONFIG_COMPRESSOR_IS_PRESENT);
22683
22684 if (vm_compressor_low_on_space() || vm_swap_low_on_space()) {
22685 if (vm_compressor_low_on_space()) {
22686 *freezer_error_code = FREEZER_ERROR_NO_COMPRESSOR_SPACE;
22687 }
22688
22689 if (vm_swap_low_on_space()) {
22690 *freezer_error_code = FREEZER_ERROR_NO_SWAP_SPACE;
22691 }
22692
22693 kr = KERN_NO_SPACE;
22694 goto done;
22695 }
22696
22697 if (VM_CONFIG_FREEZER_SWAP_IS_ACTIVE == FALSE) {
22698 /*
22699 * In-memory compressor backing the freezer. No disk.
22700 * So no need to do the evaluation phase.
22701 */
22702 evaluation_phase = FALSE;
22703
22704 if (eval_only == TRUE) {
22705 /*
22706 * We don't support 'eval_only' mode
22707 * in this non-swap config.
22708 */
22709 *freezer_error_code = FREEZER_ERROR_GENERIC;
22710 kr = KERN_INVALID_ARGUMENT;
22711 goto done;
22712 }
22713
22714 freezer_context_global.freezer_ctx_uncompressed_pages = 0;
22715 clock_get_uptime(&c_freezer_last_yield_ts);
22716 }
22717again:
22718
22719 for (entry2 = vm_map_first_entry(map);
22720 entry2 != vm_map_to_entry(map);
22721 entry2 = entry2->vme_next) {
22722 vm_object_t src_object;
22723
22724 if (entry2->is_sub_map) {
22725 continue;
22726 }
22727
22728 vmlp_range_event_entry(map, entry2);
22729
22730 src_object = VME_OBJECT(entry2);
22731 if (!src_object ||
22732 src_object->phys_contiguous ||
22733 !src_object->internal) {
22734 continue;
22735 }
22736
22737 /* If eligible, scan the entry, moving eligible pages over to our parent object */
22738
22739 if (VM_CONFIG_FREEZER_SWAP_IS_ACTIVE) {
22740 /*
22741 * We skip purgeable objects during evaluation phase only.
22742 * If we decide to freeze this process, we'll explicitly
22743 * purge these objects before we go around again with
22744 * 'evaluation_phase' set to FALSE.
22745 */
22746
22747 if ((src_object->purgable == VM_PURGABLE_EMPTY) || (src_object->purgable == VM_PURGABLE_VOLATILE)) {
22748 /*
22749 * We want to purge objects that may not belong to this task but are mapped
22750 * in this task alone. Since we already purged this task's purgeable memory
22751 * at the end of a successful evaluation phase, we want to avoid doing no-op calls
22752 * on this task's purgeable objects. Hence the check for only volatile objects.
22753 */
22754 if (evaluation_phase ||
22755 src_object->purgable != VM_PURGABLE_VOLATILE ||
22756 os_ref_get_count_raw(&src_object->ref_count) != 1) {
22757 continue;
22758 }
22759 vm_object_lock(src_object);
22760 if (src_object->purgable == VM_PURGABLE_VOLATILE &&
22761 os_ref_get_count_raw(&src_object->ref_count) == 1) {
22762 purgeable_q_t old_queue;
22763
22764 /* object should be on a purgeable queue */
22765 assert(src_object->objq.next != NULL &&
22766 src_object->objq.prev != NULL);
22767 /* move object from its volatile queue to the nonvolatile queue */
22768 old_queue = vm_purgeable_object_remove(src_object);
22769 assert(old_queue);
22770 if (src_object->purgeable_when_ripe) {
22771 /* remove a token from that volatile queue */
22772 vm_page_lock_queues();
22773 vm_purgeable_token_delete_first(old_queue);
22774 vm_page_unlock_queues();
22775 }
22776 /* purge the object */
22777 vm_object_purge(src_object, 0);
22778 }
22779 vm_object_unlock(src_object);
22780 continue;
22781 }
22782
22783 /*
22784 * Pages belonging to this object could be swapped to disk.
22785 * Make sure it's not a shared object because we could end
22786 * up just bringing it back in again.
22787 *
22788 * We try to optimize somewhat by checking for objects that are mapped
22789 * more than once within our own map. But we don't do full searches,
22790 * we just look at the entries following our current entry.
22791 */
22792
22793 if (os_ref_get_count_raw(&src_object->ref_count) > 1) {
22794 if (src_object != cur_shared_object) {
22795 obj_pages_snapshot = (src_object->resident_page_count - src_object->wired_page_count) + vm_compressor_pager_get_count(src_object->pager);
22796 dirty_shared_count += obj_pages_snapshot;
22797
22798 cur_shared_object = src_object;
22799 cur_shared_obj_ref_cnt = 1;
22800 continue;
22801 } else {
22802 cur_shared_obj_ref_cnt++;
22803 if (os_ref_get_count_raw(&src_object->ref_count) == cur_shared_obj_ref_cnt) {
22804 /*
22805 * Fall through to below and treat this object as private.
22806 * So deduct its pages from our shared total and add it to the
22807 * private total.
22808 */
22809
22810 dirty_shared_count -= obj_pages_snapshot;
22811 dirty_private_count += obj_pages_snapshot;
22812 } else {
22813 continue;
22814 }
22815 }
22816 }
22817
22818
22819 if (os_ref_get_count_raw(&src_object->ref_count) == 1) {
22820 dirty_private_count += (src_object->resident_page_count - src_object->wired_page_count) + vm_compressor_pager_get_count(src_object->pager);
22821 }
22822
22823 if (evaluation_phase == TRUE) {
22824 continue;
22825 }
22826 }
22827
22828 uint32_t paged_out_count = vm_object_compressed_freezer_pageout(src_object, dirty_budget);
22829 *wired_count += src_object->wired_page_count;
22830
22831 if (vm_compressor_low_on_space() || vm_swap_low_on_space()) {
22832 if (vm_compressor_low_on_space()) {
22833 *freezer_error_code = FREEZER_ERROR_NO_COMPRESSOR_SPACE;
22834 }
22835
22836 if (vm_swap_low_on_space()) {
22837 *freezer_error_code = FREEZER_ERROR_NO_SWAP_SPACE;
22838 }
22839
22840 kr = KERN_NO_SPACE;
22841 break;
22842 }
22843 if (paged_out_count >= dirty_budget) {
22844 break;
22845 }
22846 dirty_budget -= paged_out_count;
22847 }
22848
22849 *shared_count = (unsigned int) ((dirty_shared_count * PAGE_SIZE_64) / (1024 * 1024ULL));
22850 if (evaluation_phase) {
22851 if (memorystatus_freeze_shared_mb_per_process_max) {
22852 unsigned int shared_pages_threshold = (memorystatus_freeze_shared_mb_per_process_max * 1024 * 1024ULL) / PAGE_SIZE_64;
22853 if (dirty_shared_count > shared_pages_threshold) {
22854 *freezer_error_code = FREEZER_ERROR_EXCESS_SHARED_MEMORY;
22855 kr = KERN_FAILURE;
22856 goto done;
22857 }
22858 }
22859
22860 if (dirty_shared_count &&
22861 ((dirty_private_count / dirty_shared_count) < memorystatus_freeze_private_shared_pages_ratio)) {
22862 *freezer_error_code = FREEZER_ERROR_LOW_PRIVATE_SHARED_RATIO;
22863 kr = KERN_FAILURE;
22864 goto done;
22865 }
22866
22867 evaluation_phase = FALSE;
22868 dirty_shared_count = dirty_private_count = 0;
22869
22870 freezer_context_global.freezer_ctx_uncompressed_pages = 0;
22871 clock_get_uptime(&c_freezer_last_yield_ts);
22872
22873 if (eval_only) {
22874 kr = KERN_SUCCESS;
22875 goto done;
22876 }
22877
22878 vm_purgeable_purge_task_owned(task);
22879
22880 goto again;
22881 } else {
22882 kr = KERN_SUCCESS;
22883 }
22884
22885done:
22886 vm_map_unlock(map);
22887
22888 if ((eval_only == FALSE) && (kr == KERN_SUCCESS)) {
22889 vm_object_compressed_freezer_done();
22890 }
22891 vmlp_api_end(VM_MAP_FREEZE, kr);
22892 return kr;
22893}
22894
22895#endif
22896
22897/*
22898 * vm_map_entry_should_cow_for_true_share:
22899 *
22900 * Determines if the map entry should be clipped and setup for copy-on-write
22901 * to avoid applying "true_share" to a large VM object when only a subset is
22902 * targeted.
22903 *
22904 * For now, we target only the map entries created for the Objective C
22905 * Garbage Collector, which initially have the following properties:
22906 * - alias == VM_MEMORY_MALLOC
22907 * - wired_count == 0
22908 * - !needs_copy
22909 * and a VM object with:
22910 * - internal
22911 * - copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC
22912 * - !true_share
22913 * - vo_size == ANON_CHUNK_SIZE
22914 *
22915 * Only non-kernel map entries.
22916 */
22917boolean_t
22918vm_map_entry_should_cow_for_true_share(
22919 vm_map_entry_t entry)
22920{
22921 vm_object_t object;
22922
22923 if (entry->is_sub_map) {
22924 /* entry does not point at a VM object */
22925 return FALSE;
22926 }
22927
22928 if (entry->needs_copy) {
22929 /* already set for copy_on_write: done! */
22930 return FALSE;
22931 }
22932
22933 if (VME_ALIAS(entry) != VM_MEMORY_MALLOC &&
22934 VME_ALIAS(entry) != VM_MEMORY_MALLOC_SMALL) {
22935 /* not a malloc heap or Obj-C Garbage Collector heap */
22936 return FALSE;
22937 }
22938
22939 if (entry->wired_count) {
22940 /* wired: can't change the map entry... */
22941 vm_counters.should_cow_but_wired++;
22942 return FALSE;
22943 }
22944
22945 object = VME_OBJECT(entry);
22946
22947 if (object == VM_OBJECT_NULL) {
22948 /* no object yet... */
22949 return FALSE;
22950 }
22951
22952 if (!object->internal) {
22953 /* not an internal object */
22954 return FALSE;
22955 }
22956
22957 if (object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) {
22958 /* not the default copy strategy */
22959 return FALSE;
22960 }
22961
22962 if (object->true_share) {
22963 /* already true_share: too late to avoid it */
22964 return FALSE;
22965 }
22966
22967 if (VME_ALIAS(entry) == VM_MEMORY_MALLOC &&
22968 object->vo_size != ANON_CHUNK_SIZE) {
22969 /* ... not an object created for the ObjC Garbage Collector */
22970 return FALSE;
22971 }
22972
22973 if (VME_ALIAS(entry) == VM_MEMORY_MALLOC_SMALL &&
22974 object->vo_size != 2048 * 4096) {
22975 /* ... not a "MALLOC_SMALL" heap */
22976 return FALSE;
22977 }
22978
22979 /*
22980 * All the criteria match: we have a large object being targeted for "true_share".
22981 * To limit the adverse side-effects linked with "true_share", tell the caller to
22982 * try and avoid setting up the entire object for "true_share" by clipping the
22983 * targeted range and setting it up for copy-on-write.
22984 */
22985 return TRUE;
22986}
22987
22988uint64_t vm_map_range_overflows_count = 0;
22989TUNABLE_WRITEABLE(boolean_t, vm_map_range_overflows_log, "vm_map_range_overflows_log", FALSE);
22990bool
22991vm_map_range_overflows(
22992 vm_map_t map,
22993 vm_map_offset_t addr,
22994 vm_map_size_t size)
22995{
22996 vm_map_offset_t start, end, sum;
22997 vm_map_offset_t pgmask;
22998
22999 if (size == 0) {
23000 /* empty range -> no overflow */
23001 return false;
23002 }
23003 pgmask = vm_map_page_mask(map);
23004 start = vm_map_trunc_page_mask(addr, pgmask);
23005 end = vm_map_round_page_mask(addr + size, pgmask);
23006 if (__improbable(os_add_overflow(addr, size, &sum) || end <= start)) {
23007 vm_map_range_overflows_count++;
23008 if (vm_map_range_overflows_log) {
23009 printf("%d[%s] vm_map_range_overflows addr 0x%llx size 0x%llx pgmask 0x%llx\n",
23010 proc_selfpid(),
23011 proc_best_name(current_proc()),
23012 (uint64_t)addr,
23013 (uint64_t)size,
23014 (uint64_t)pgmask);
23015 }
23016 DTRACE_VM4(vm_map_range_overflows,
23017 vm_map_t, map,
23018 uint32_t, pgmask,
23019 uint64_t, (uint64_t)addr,
23020 uint64_t, (uint64_t)size);
23021 return true;
23022 }
23023 return false;
23024}
23025
23026vm_map_offset_t
23027vm_map_round_page_mask(
23028 vm_map_offset_t offset,
23029 vm_map_offset_t mask)
23030{
23031 return VM_MAP_ROUND_PAGE(offset, mask);
23032}
23033
23034vm_map_offset_t
23035vm_map_trunc_page_mask(
23036 vm_map_offset_t offset,
23037 vm_map_offset_t mask)
23038{
23039 return VM_MAP_TRUNC_PAGE(offset, mask);
23040}
23041
23042boolean_t
23043vm_map_page_aligned(
23044 vm_map_offset_t offset,
23045 vm_map_offset_t mask)
23046{
23047 return ((offset) & mask) == 0;
23048}
23049
23050int
23051vm_map_page_shift(
23052 vm_map_t map)
23053{
23054 return VM_MAP_PAGE_SHIFT(map);
23055}
23056
23057int
23058vm_map_page_size(
23059 vm_map_t map)
23060{
23061 return VM_MAP_PAGE_SIZE(map);
23062}
23063
23064vm_map_offset_t
23065vm_map_page_mask(
23066 vm_map_t map)
23067{
23068 return VM_MAP_PAGE_MASK(map);
23069}
23070
23071kern_return_t
23072vm_map_set_page_shift(
23073 vm_map_t map,
23074 int pageshift)
23075{
23076 if (map->hdr.nentries != 0) {
23077 /* too late to change page size */
23078 return KERN_FAILURE;
23079 }
23080
23081 map->hdr.page_shift = (uint16_t)pageshift;
23082
23083 return KERN_SUCCESS;
23084}
23085
23086kern_return_t
23087vm_map_query_volatile(
23088 vm_map_t map,
23089 mach_vm_size_t *volatile_virtual_size_p,
23090 mach_vm_size_t *volatile_resident_size_p,
23091 mach_vm_size_t *volatile_compressed_size_p,
23092 mach_vm_size_t *volatile_pmap_size_p,
23093 mach_vm_size_t *volatile_compressed_pmap_size_p)
23094{
23095 mach_vm_size_t volatile_virtual_size;
23096 mach_vm_size_t volatile_resident_count;
23097 mach_vm_size_t volatile_compressed_count;
23098 mach_vm_size_t volatile_pmap_count;
23099 mach_vm_size_t volatile_compressed_pmap_count;
23100 mach_vm_size_t resident_count;
23101 vm_map_entry_t entry;
23102 vm_object_t object;
23103
23104 /* map should be locked by caller */
23105
23106 volatile_virtual_size = 0;
23107 volatile_resident_count = 0;
23108 volatile_compressed_count = 0;
23109 volatile_pmap_count = 0;
23110 volatile_compressed_pmap_count = 0;
23111
23112 for (entry = vm_map_first_entry(map);
23113 entry != vm_map_to_entry(map);
23114 entry = entry->vme_next) {
23115 mach_vm_size_t pmap_resident_bytes, pmap_compressed_bytes;
23116
23117 if (entry->is_sub_map) {
23118 continue;
23119 }
23120 if (!(entry->protection & VM_PROT_WRITE)) {
23121 continue;
23122 }
23123 object = VME_OBJECT(entry);
23124 if (object == VM_OBJECT_NULL) {
23125 continue;
23126 }
23127 if (object->purgable != VM_PURGABLE_VOLATILE &&
23128 object->purgable != VM_PURGABLE_EMPTY) {
23129 continue;
23130 }
23131 if (VME_OFFSET(entry)) {
23132 /*
23133 * If the map entry has been split and the object now
23134 * appears several times in the VM map, we don't want
23135 * to count the object's resident_page_count more than
23136 * once. We count it only for the first one, starting
23137 * at offset 0 and ignore the other VM map entries.
23138 */
23139 continue;
23140 }
23141 resident_count = object->resident_page_count;
23142 if ((VME_OFFSET(entry) / PAGE_SIZE) >= resident_count) {
23143 resident_count = 0;
23144 } else {
23145 resident_count -= (VME_OFFSET(entry) / PAGE_SIZE);
23146 }
23147
23148 volatile_virtual_size += entry->vme_end - entry->vme_start;
23149 volatile_resident_count += resident_count;
23150 if (object->pager) {
23151 volatile_compressed_count +=
23152 vm_compressor_pager_get_count(object->pager);
23153 }
23154 pmap_compressed_bytes = 0;
23155 pmap_resident_bytes =
23156 pmap_query_resident(map->pmap,
23157 entry->vme_start,
23158 entry->vme_end,
23159 &pmap_compressed_bytes);
23160 volatile_pmap_count += (pmap_resident_bytes / PAGE_SIZE);
23161 volatile_compressed_pmap_count += (pmap_compressed_bytes
23162 / PAGE_SIZE);
23163 }
23164
23165 /* map is still locked on return */
23166
23167 *volatile_virtual_size_p = volatile_virtual_size;
23168 *volatile_resident_size_p = volatile_resident_count * PAGE_SIZE;
23169 *volatile_compressed_size_p = volatile_compressed_count * PAGE_SIZE;
23170 *volatile_pmap_size_p = volatile_pmap_count * PAGE_SIZE;
23171 *volatile_compressed_pmap_size_p = volatile_compressed_pmap_count * PAGE_SIZE;
23172
23173 return KERN_SUCCESS;
23174}
23175
23176void
23177vm_map_sizes(vm_map_t map,
23178 vm_map_size_t * psize,
23179 vm_map_size_t * pfree,
23180 vm_map_size_t * plargest_free)
23181{
23182 vm_map_entry_t entry;
23183 vm_map_offset_t prev;
23184 vm_map_size_t free, total_free, largest_free;
23185 boolean_t end;
23186
23187 vmlp_api_start(VM_MAP_SIZES);
23188
23189 if (!map) {
23190 *psize = *pfree = *plargest_free = 0;
23191 vmlp_api_end(VM_MAP_SIZES, 0);
23192 return;
23193 }
23194 total_free = largest_free = 0;
23195
23196 vm_map_lock_read(map);
23197 if (psize) {
23198 *psize = map->max_offset - map->min_offset;
23199 }
23200
23201 prev = map->min_offset;
23202 for (entry = vm_map_first_entry(map);; entry = entry->vme_next) {
23203 end = (entry == vm_map_to_entry(map));
23204
23205 if (!entry->is_sub_map) {
23206 vmlp_range_event_entry(map, entry);
23207 }
23208
23209 if (end) {
23210 free = entry->vme_end - prev;
23211 } else {
23212 free = entry->vme_start - prev;
23213 }
23214
23215 total_free += free;
23216 if (free > largest_free) {
23217 largest_free = free;
23218 }
23219
23220 if (end) {
23221 break;
23222 }
23223 prev = entry->vme_end;
23224 }
23225 vm_map_unlock_read(map);
23226 if (pfree) {
23227 *pfree = total_free;
23228 }
23229 if (plargest_free) {
23230 *plargest_free = largest_free;
23231 }
23232 vmlp_api_end(VM_MAP_SIZES, 0);
23233}
23234
23235#if VM_SCAN_FOR_SHADOW_CHAIN
23236int
23237vm_map_shadow_max(
23238 vm_map_t map)
23239{
23240 int shadows, shadows_max;
23241 vm_map_entry_t entry;
23242 vm_object_t object, next_object;
23243
23244 vmlp_api_start(VM_MAP_SHADOW_MAX);
23245
23246 if (map == NULL) {
23247 vmlp_api_end(VM_MAP_SHADOW_MAX, 0);
23248 return 0;
23249 }
23250
23251 shadows_max = 0;
23252
23253 vm_map_lock_read(map);
23254
23255 for (entry = vm_map_first_entry(map);
23256 entry != vm_map_to_entry(map);
23257 entry = entry->vme_next) {
23258 if (entry->is_sub_map) {
23259 continue;
23260 }
23261
23262 vmlp_range_event_entry(map, entry);
23263
23264 object = VME_OBJECT(entry);
23265 if (object == NULL) {
23266 continue;
23267 }
23268 vm_object_lock_shared(object);
23269 for (shadows = 0;
23270 object->shadow != NULL;
23271 shadows++, object = next_object) {
23272 next_object = object->shadow;
23273 vm_object_lock_shared(next_object);
23274 vm_object_unlock(object);
23275 }
23276 vm_object_unlock(object);
23277 if (shadows > shadows_max) {
23278 shadows_max = shadows;
23279 }
23280 }
23281
23282 vm_map_unlock_read(map);
23283
23284 vmlp_api_end(VM_MAP_SHADOW_MAX, shadows_max);
23285 return shadows_max;
23286}
23287#endif /* VM_SCAN_FOR_SHADOW_CHAIN */
23288
23289void
23290vm_commit_pagezero_status(vm_map_t lmap)
23291{
23292 pmap_advise_pagezero_range(lmap->pmap, lmap->min_offset);
23293}
23294
23295#if __x86_64__
23296void
23297vm_map_set_high_start(
23298 vm_map_t map,
23299 vm_map_offset_t high_start)
23300{
23301 map->vmmap_high_start = high_start;
23302}
23303#endif /* __x86_64__ */
23304
23305#if CODE_SIGNING_MONITOR
23306
23307kern_return_t
23308vm_map_entry_cs_associate(
23309 vm_map_t map,
23310 vm_map_entry_t entry,
23311 vm_map_kernel_flags_t vmk_flags)
23312{
23313 vm_object_t cs_object, cs_shadow, backing_object;
23314 vm_object_offset_t cs_offset, backing_offset;
23315 void *cs_blobs;
23316 struct vnode *cs_vnode;
23317 kern_return_t cs_ret;
23318
23319 if (map->pmap == NULL ||
23320 entry->is_sub_map || /* XXX FBDP: recurse on sub-range? */
23321 (csm_address_space_exempt(map->pmap) == KERN_SUCCESS) ||
23322 VME_OBJECT(entry) == VM_OBJECT_NULL) {
23323 return KERN_SUCCESS;
23324 }
23325
23326 if (!(entry->protection & VM_PROT_EXECUTE)) {
23327 /*
23328 * This memory region is not executable, so the code-signing
23329 * monitor would usually not care about it...
23330 */
23331 if (vmk_flags.vmkf_remap_prot_copy &&
23332 (entry->max_protection & VM_PROT_EXECUTE)) {
23333 /*
23334 * ... except if the memory region is being remapped
23335 * from r-x/r-x to rw-/rwx via vm_protect(VM_PROT_COPY)
23336 * which is what a debugger or dtrace would be doing
23337 * to prepare to modify an executable page to insert
23338 * a breakpoint or activate a probe.
23339 * In that case, fall through so that we can mark
23340 * this region as being "debugged" and no longer
23341 * strictly code-signed.
23342 */
23343 } else {
23344 /*
23345 * Really not executable, so no need to tell the
23346 * code-signing monitor.
23347 */
23348 return KERN_SUCCESS;
23349 }
23350 }
23351
23352 vm_map_lock_assert_exclusive(map);
23353
23354 /*
23355 * Check for a debug association mapping before we check for used_for_jit. This
23356 * allows non-RWX JIT on macOS systems to masquerade their mappings as USER_DEBUG
23357 * pages instead of USER_JIT. These non-RWX JIT pages cannot be marked as USER_JIT
23358 * since they are mapped with RW or RX permissions, which the page table monitor
23359 * denies on USER_JIT pages. Given that, if they're not mapped as USER_DEBUG,
23360 * they will be mapped as USER_EXEC, and that will cause another page table monitor
23361 * violation when those USER_EXEC pages are mapped as RW.
23362 *
23363 * Since these pages switch between RW and RX through mprotect, they mimic what
23364 * we expect a debugger to do. As the code signing monitor does not enforce mappings
23365 * on macOS systems, this works in our favor here and allows us to continue to
23366 * support these legacy-programmed applications without sacrificing security on
23367 * the page table or the code signing monitor. We don't need to explicitly check
23368 * for entry_for_jit here and the mapping permissions. If the initial mapping is
23369 * created with RX, then the application must map it as RW in order to first write
23370 * to the page (MAP_JIT mappings must be private and anonymous). The switch to
23371 * RX will cause vm_map_protect to mark the entry as vmkf_remap_prot_copy.
23372 * Similarly, if the mapping was created as RW, and then switched to RX,
23373 * vm_map_protect will again mark the entry as a copy, and both these cases
23374 * lead to this if-statement being entered.
23375 *
23376 * For more information: rdar://115313336.
23377 */
23378 if (vmk_flags.vmkf_remap_prot_copy) {
23379 cs_ret = csm_associate_debug_region(
23380 map->pmap,
23381 entry->vme_start,
23382 entry->vme_end - entry->vme_start);
23383
23384 /*
23385 * csm_associate_debug_region returns not supported when the code signing
23386 * monitor is disabled. This is intentional, since cs_ret is checked towards
23387 * the end of the function, and if it is not supported, then we still want the
23388 * VM to perform code-signing enforcement on this entry. That said, if we don't
23389 * mark this as a xnu_user_debug page when the code-signing monitor is disabled,
23390 * then it never gets retyped to XNU_USER_DEBUG frame type, which then causes
23391 * an issue with debugging (since it'll be mapped in as XNU_USER_EXEC in some
23392 * cases, which will cause a violation when attempted to be mapped as writable).
23393 */
23394 if ((cs_ret == KERN_SUCCESS) || (cs_ret == KERN_NOT_SUPPORTED)) {
23395 entry->vme_xnu_user_debug = TRUE;
23396 }
23397#if DEVELOPMENT || DEBUG
23398 if (vm_log_xnu_user_debug) {
23399 printf("FBDP %d[%s] %s:%d map %p entry %p [ 0x%llx 0x%llx ] vme_xnu_user_debug=%d cs_ret %d\n",
23400 proc_selfpid(),
23401 (get_bsdtask_info(current_task()) ? proc_name_address(get_bsdtask_info(current_task())) : "?"),
23402 __FUNCTION__, __LINE__,
23403 map, entry,
23404 (uint64_t)entry->vme_start, (uint64_t)entry->vme_end,
23405 entry->vme_xnu_user_debug,
23406 cs_ret);
23407 }
23408#endif /* DEVELOPMENT || DEBUG */
23409 goto done;
23410 }
23411
23412 if (entry->used_for_jit) {
23413 cs_ret = csm_associate_jit_region(
23414 map->pmap,
23415 entry->vme_start,
23416 entry->vme_end - entry->vme_start);
23417 goto done;
23418 }
23419
23420 cs_object = VME_OBJECT(entry);
23421 vm_object_lock_shared(cs_object);
23422 cs_offset = VME_OFFSET(entry);
23423
23424 /* find the VM object backed by the code-signed vnode */
23425 for (;;) {
23426 /* go to the bottom of cs_object's shadow chain */
23427 for (;
23428 cs_object->shadow != VM_OBJECT_NULL;
23429 cs_object = cs_shadow) {
23430 cs_shadow = cs_object->shadow;
23431 cs_offset += cs_object->vo_shadow_offset;
23432 vm_object_lock_shared(cs_shadow);
23433 vm_object_unlock(cs_object);
23434 }
23435 if (cs_object->internal ||
23436 cs_object->pager == MEMORY_OBJECT_NULL) {
23437 vm_object_unlock(cs_object);
23438 return KERN_SUCCESS;
23439 }
23440
23441 cs_offset += cs_object->paging_offset;
23442
23443 /*
23444 * cs_object could be backed by a:
23445 * vnode_pager
23446 * apple_protect_pager
23447 * shared_region_pager
23448 * fourk_pager (multiple backing objects -> fail?)
23449 * ask the pager if it has a backing VM object
23450 */
23451 if (!memory_object_backing_object(cs_object->pager,
23452 cs_offset,
23453 &backing_object,
23454 &backing_offset)) {
23455 /* no backing object: cs_object is it */
23456 break;
23457 }
23458
23459 /* look down the backing object's shadow chain */
23460 vm_object_lock_shared(backing_object);
23461 vm_object_unlock(cs_object);
23462 cs_object = backing_object;
23463 cs_offset = backing_offset;
23464 }
23465
23466 cs_vnode = vnode_pager_lookup_vnode(cs_object->pager);
23467 if (cs_vnode == NULL) {
23468 /* no vnode, no code signatures to associate */
23469 cs_ret = KERN_SUCCESS;
23470 } else {
23471 cs_ret = vnode_pager_get_cs_blobs(cs_vnode,
23472 &cs_blobs);
23473 assert(cs_ret == KERN_SUCCESS);
23474 cs_ret = cs_associate_blob_with_mapping(map->pmap,
23475 entry->vme_start,
23476 (entry->vme_end - entry->vme_start),
23477 cs_offset,
23478 cs_blobs);
23479 }
23480 vm_object_unlock(cs_object);
23481 cs_object = VM_OBJECT_NULL;
23482
23483done:
23484 if (cs_ret == KERN_SUCCESS) {
23485 DTRACE_VM2(vm_map_entry_cs_associate_success,
23486 vm_map_offset_t, entry->vme_start,
23487 vm_map_offset_t, entry->vme_end);
23488 if (vm_map_executable_immutable) {
23489 /*
23490 * Prevent this executable
23491 * mapping from being unmapped
23492 * or modified.
23493 */
23494 entry->vme_permanent = TRUE;
23495 }
23496 /*
23497 * pmap says it will validate the
23498 * code-signing validity of pages
23499 * faulted in via this mapping, so
23500 * this map entry should be marked so
23501 * that vm_fault() bypasses code-signing
23502 * validation for faults coming through
23503 * this mapping.
23504 */
23505 entry->csm_associated = TRUE;
23506 } else if (cs_ret == KERN_NOT_SUPPORTED) {
23507 /*
23508 * pmap won't check the code-signing
23509 * validity of pages faulted in via
23510 * this mapping, so VM should keep
23511 * doing it.
23512 */
23513 DTRACE_VM3(vm_map_entry_cs_associate_off,
23514 vm_map_offset_t, entry->vme_start,
23515 vm_map_offset_t, entry->vme_end,
23516 int, cs_ret);
23517 } else {
23518 /*
23519 * A real error: do not allow
23520 * execution in this mapping.
23521 */
23522 DTRACE_VM3(vm_map_entry_cs_associate_failure,
23523 vm_map_offset_t, entry->vme_start,
23524 vm_map_offset_t, entry->vme_end,
23525 int, cs_ret);
23526 if (vmk_flags.vmkf_overwrite_immutable) {
23527 /*
23528 * We can get here when we remap an apple_protect pager
23529 * on top of an already cs_associated executable mapping
23530 * with the same code signatures, so we don't want to
23531 * lose VM_PROT_EXECUTE in that case...
23532 */
23533 } else {
23534 entry->protection &= ~VM_PROT_ALLEXEC;
23535 entry->max_protection &= ~VM_PROT_ALLEXEC;
23536 }
23537 }
23538
23539 return cs_ret;
23540}
23541
23542#endif /* CODE_SIGNING_MONITOR */
23543
23544inline bool
23545vm_map_is_corpse_source(vm_map_t map)
23546{
23547 bool status = false;
23548 vmlp_api_start(VM_MAP_IS_CORPSE_SOURCE);
23549 vmlp_range_event_none(map);
23550 if (map) {
23551 vm_map_lock_read(map);
23552 status = map->corpse_source;
23553 vm_map_unlock_read(map);
23554 }
23555 vmlp_api_end(VM_MAP_IS_CORPSE_SOURCE, status);
23556 return status;
23557}
23558
23559inline void
23560vm_map_set_corpse_source(vm_map_t map)
23561{
23562 vmlp_api_start(VM_MAP_SET_CORPSE_SOURCE);
23563 vmlp_range_event_none(map);
23564 if (map) {
23565 vm_map_lock(map);
23566 map->corpse_source = true;
23567 vm_map_unlock(map);
23568 }
23569 vmlp_api_end(VM_MAP_SET_CORPSE_SOURCE, 0);
23570}
23571
23572inline void
23573vm_map_unset_corpse_source(vm_map_t map)
23574{
23575 vmlp_api_start(VM_MAP_UNSET_CORPSE_SOURCE);
23576 vmlp_range_event_none(map);
23577 if (map) {
23578 vm_map_lock(map);
23579 map->corpse_source = false;
23580 vm_map_unlock(map);
23581 }
23582 vmlp_api_end(VM_MAP_UNSET_CORPSE_SOURCE, 0);
23583}
23584/*
23585 * FORKED CORPSE FOOTPRINT
23586 *
23587 * A forked corpse gets a copy of the original VM map but its pmap is mostly
23588 * empty since it never ran and never got to fault in any pages.
23589 * Collecting footprint info (via "sysctl vm.self_region_footprint") for
23590 * a forked corpse would therefore return very little information.
23591 *
23592 * When forking a corpse, we can pass the VM_MAP_FORK_CORPSE_FOOTPRINT option
23593 * to vm_map_fork() to collect footprint information from the original VM map
23594 * and its pmap, and store it in the forked corpse's VM map. That information
23595 * is stored in place of the VM map's "hole list" since we'll never need to
23596 * lookup for holes in the corpse's map.
23597 *
23598 * The corpse's footprint info looks like this:
23599 *
23600 * vm_map->vmmap_corpse_footprint points to pageable kernel memory laid out
23601 * as follows:
23602 * +---------------------------------------+
23603 * header-> | cf_size |
23604 * +-------------------+-------------------+
23605 * | cf_last_region | cf_last_zeroes |
23606 * +-------------------+-------------------+
23607 * region1-> | cfr_vaddr |
23608 * +-------------------+-------------------+
23609 * | cfr_num_pages | d0 | d1 | d2 | d3 |
23610 * +---------------------------------------+
23611 * | d4 | d5 | ... |
23612 * +---------------------------------------+
23613 * | ... |
23614 * +-------------------+-------------------+
23615 * | dy | dz | na | na | cfr_vaddr... | <-region2
23616 * +-------------------+-------------------+
23617 * | cfr_vaddr (ctd) | cfr_num_pages |
23618 * +---------------------------------------+
23619 * | d0 | d1 ... |
23620 * +---------------------------------------+
23621 * ...
23622 * +---------------------------------------+
23623 * last region-> | cfr_vaddr |
23624 * +---------------------------------------+
23625 * + cfr_num_pages | d0 | d1 | d2 | d3 |
23626 * +---------------------------------------+
23627 * ...
23628 * +---------------------------------------+
23629 * | dx | dy | dz | na | na | na | na | na |
23630 * +---------------------------------------+
23631 *
23632 * where:
23633 * cf_size: total size of the buffer (rounded to page size)
23634 * cf_last_region: offset in the buffer of the last "region" sub-header
23635 * cf_last_zeroes: number of trailing "zero" dispositions at the end
23636 * of last region
23637 * cfr_vaddr: virtual address of the start of the covered "region"
23638 * cfr_num_pages: number of pages in the covered "region"
23639 * d*: disposition of the page at that virtual address
23640 * Regions in the buffer are word-aligned.
23641 *
23642 * We estimate the size of the buffer based on the number of memory regions
23643 * and the virtual size of the address space. While copying each memory region
23644 * during vm_map_fork(), we also collect the footprint info for that region
23645 * and store it in the buffer, packing it as much as possible (coalescing
23646 * contiguous memory regions to avoid having too many region headers and
23647 * avoiding long streaks of "zero" page dispositions by splitting footprint
23648 * "regions", so the number of regions in the footprint buffer might not match
23649 * the number of memory regions in the address space.
23650 *
23651 * We also have to copy the original task's "nonvolatile" ledgers since that's
23652 * part of the footprint and will need to be reported to any tool asking for
23653 * the footprint information of the forked corpse.
23654 */
23655
23656uint64_t vm_map_corpse_footprint_count = 0;
23657uint64_t vm_map_corpse_footprint_size_avg = 0;
23658uint64_t vm_map_corpse_footprint_size_max = 0;
23659uint64_t vm_map_corpse_footprint_full = 0;
23660uint64_t vm_map_corpse_footprint_no_buf = 0;
23661
23662struct vm_map_corpse_footprint_header {
23663 vm_size_t cf_size; /* allocated buffer size */
23664 uint32_t cf_last_region; /* offset of last region in buffer */
23665 union {
23666 uint32_t cfu_last_zeroes; /* during creation:
23667 * number of "zero" dispositions at
23668 * end of last region */
23669 uint32_t cfu_hint_region; /* during lookup:
23670 * offset of last looked up region */
23671#define cf_last_zeroes cfu.cfu_last_zeroes
23672#define cf_hint_region cfu.cfu_hint_region
23673 } cfu;
23674};
23675typedef uint8_t cf_disp_t;
23676struct vm_map_corpse_footprint_region {
23677 vm_map_offset_t cfr_vaddr; /* region start virtual address */
23678 uint32_t cfr_num_pages; /* number of pages in this "region" */
23679 cf_disp_t cfr_disposition[] __counted_by(cfr_num_pages); /* disposition of each page */
23680} __attribute__((packed));
23681
23682static cf_disp_t
23683vm_page_disposition_to_cf_disp(
23684 int disposition)
23685{
23686 assert(sizeof(cf_disp_t) == 1);
23687 /* relocate bits that don't fit in a "uint8_t" */
23688 if (disposition & VM_PAGE_QUERY_PAGE_REUSABLE) {
23689 disposition |= VM_PAGE_QUERY_PAGE_FICTITIOUS;
23690 }
23691 /* cast gets rid of extra bits */
23692 return (cf_disp_t) disposition;
23693}
23694
23695static int
23696vm_page_cf_disp_to_disposition(
23697 cf_disp_t cf_disp)
23698{
23699 int disposition;
23700
23701 assert(sizeof(cf_disp_t) == 1);
23702 disposition = (int) cf_disp;
23703 /* move relocated bits back in place */
23704 if (cf_disp & VM_PAGE_QUERY_PAGE_FICTITIOUS) {
23705 disposition |= VM_PAGE_QUERY_PAGE_REUSABLE;
23706 disposition &= ~VM_PAGE_QUERY_PAGE_FICTITIOUS;
23707 }
23708 return disposition;
23709}
23710
23711static kmem_guard_t
23712vm_map_corpse_footprint_guard(vm_map_t map)
23713{
23714 return (kmem_guard_t){
23715 .kmg_atomic = true,
23716 .kmg_tag = VM_KERN_MEMORY_DIAG,
23717 .kmg_context = os_hash_kernel_pointer(&map->vmmap_corpse_footprint),
23718 };
23719}
23720
23721/*
23722 * vm_map_corpse_footprint_new_region:
23723 * closes the current footprint "region" and creates a new one
23724 *
23725 * Returns NULL if there's not enough space in the buffer for a new region.
23726 */
23727static struct vm_map_corpse_footprint_region *
23728vm_map_corpse_footprint_new_region(
23729 struct vm_map_corpse_footprint_header *footprint_header)
23730{
23731 uintptr_t footprint_edge;
23732 uint32_t new_region_offset;
23733 struct vm_map_corpse_footprint_region *footprint_region;
23734 struct vm_map_corpse_footprint_region *new_footprint_region;
23735
23736 footprint_edge = ((uintptr_t)footprint_header +
23737 footprint_header->cf_size);
23738 footprint_region = ((struct vm_map_corpse_footprint_region *)
23739 ((char *)footprint_header +
23740 footprint_header->cf_last_region));
23741 assert((uintptr_t)footprint_region + sizeof(*footprint_region) <=
23742 footprint_edge);
23743
23744 /* get rid of trailing zeroes in the last region */
23745 assert(footprint_region->cfr_num_pages >=
23746 footprint_header->cf_last_zeroes);
23747 footprint_region->cfr_num_pages -=
23748 footprint_header->cf_last_zeroes;
23749 footprint_header->cf_last_zeroes = 0;
23750
23751 /* reuse this region if it's now empty */
23752 if (footprint_region->cfr_num_pages == 0) {
23753 return footprint_region;
23754 }
23755
23756 /* compute offset of new region */
23757 new_region_offset = footprint_header->cf_last_region;
23758 new_region_offset += sizeof(*footprint_region);
23759 new_region_offset += (footprint_region->cfr_num_pages * sizeof(cf_disp_t));
23760 new_region_offset = roundup(new_region_offset, sizeof(int));
23761
23762 /* check if we're going over the edge */
23763 if (((uintptr_t)footprint_header +
23764 new_region_offset +
23765 sizeof(*footprint_region)) >=
23766 footprint_edge) {
23767 /* over the edge: no new region */
23768 return NULL;
23769 }
23770
23771 /* adjust offset of last region in header */
23772 footprint_header->cf_last_region = new_region_offset;
23773
23774 new_footprint_region = (struct vm_map_corpse_footprint_region *)
23775 ((char *)footprint_header +
23776 footprint_header->cf_last_region);
23777 new_footprint_region->cfr_vaddr = 0;
23778 new_footprint_region->cfr_num_pages = 0;
23779 /* caller needs to initialize new region */
23780
23781 return new_footprint_region;
23782}
23783
23784TUNABLE(vm_size_t, vm_map_corpse_footprint_max_buffer_size, "vm_cf_max_buf_size",
23785#if XNU_TARGET_OS_OSX
23786 MiB(8));
23787#else /* !XNU_TARGET_OS_OSX */
23788 KiB(512));
23789#endif /* XNU_TARGET_OS_OSX */
23790
23791/*
23792 * vm_map_corpse_footprint_collect:
23793 * collect footprint information for "old_entry" in "old_map" and
23794 * stores it in "new_map"'s vmmap_footprint_info.
23795 */
23796kern_return_t
23797vm_map_corpse_footprint_collect(
23798 vm_map_t old_map,
23799 vm_map_entry_t old_entry,
23800 vm_map_t new_map)
23801{
23802 vm_map_offset_t va;
23803 kmem_return_t kmr;
23804 struct vm_map_corpse_footprint_header *footprint_header;
23805 struct vm_map_corpse_footprint_region *footprint_region;
23806 struct vm_map_corpse_footprint_region *new_footprint_region;
23807 cf_disp_t *next_disp_p;
23808 uintptr_t footprint_edge;
23809 uint32_t num_pages_tmp;
23810 int effective_page_size;
23811
23812 effective_page_size = MIN(PAGE_SIZE, VM_MAP_PAGE_SIZE(old_map));
23813
23814 va = old_entry->vme_start;
23815
23816 vm_map_lock_assert_exclusive(old_map);
23817 vm_map_lock_assert_exclusive(new_map);
23818
23819 assert(new_map->has_corpse_footprint);
23820 assert(!old_map->has_corpse_footprint);
23821 if (!new_map->has_corpse_footprint ||
23822 old_map->has_corpse_footprint) {
23823 /*
23824 * This can only transfer footprint info from a
23825 * map with a live pmap to a map with a corpse footprint.
23826 */
23827 return KERN_NOT_SUPPORTED;
23828 }
23829
23830 if (new_map->vmmap_corpse_footprint == NULL) {
23831 vm_size_t buf_size;
23832
23833 buf_size = (sizeof(*footprint_header) +
23834 (old_map->hdr.nentries
23835 *
23836 (sizeof(*footprint_region) +
23837 +3)) /* potential alignment for each region */
23838 +
23839 ((old_map->size / effective_page_size)
23840 *
23841 sizeof(cf_disp_t))); /* disposition for each page */
23842 vm_log_debug("corpse map %p guestimate footprint size 0x%llx\n", new_map, (uint64_t)buf_size);
23843 buf_size = round_page(buf_size);
23844
23845 /* limit size to a somewhat sane amount */
23846 if (buf_size > vm_map_corpse_footprint_max_buffer_size) {
23847 vm_log("WARNING truncating corpse footprint buffer (%lu KiB) to maximum "
23848 "size (%lu KiB) -- footprint data may be lost\n",
23849 buf_size >> 10, vm_map_corpse_footprint_max_buffer_size >> 10);
23850 buf_size = vm_map_corpse_footprint_max_buffer_size;
23851 }
23852 kmem_guard_t guard = vm_map_corpse_footprint_guard(new_map);
23853 kmr = kmem_alloc_guard(kernel_map, buf_size + PAGE_SIZE, 0,
23854 KMA_DATA | KMA_GUARD_LAST | KMA_KOBJECT | KMA_ZERO,
23855 guard);
23856 if (kmr.kmr_return != KERN_SUCCESS) {
23857 vm_map_corpse_footprint_no_buf++;
23858 return kmr.kmr_return;
23859 }
23860
23861 /* initialize header and 1st region */
23862 footprint_header = (struct vm_map_corpse_footprint_header *)kmr.kmr_ptr;
23863 assert3p(footprint_header, !=, NULL);
23864 new_map->vmmap_corpse_footprint = footprint_header;
23865
23866 footprint_header->cf_size = buf_size;
23867 footprint_header->cf_last_region =
23868 sizeof(*footprint_header);
23869 footprint_header->cf_last_zeroes = 0;
23870
23871 footprint_region = (struct vm_map_corpse_footprint_region *)
23872 ((char *)footprint_header +
23873 footprint_header->cf_last_region);
23874 footprint_region->cfr_vaddr = 0;
23875 footprint_region->cfr_num_pages = 0;
23876 } else {
23877 /* retrieve header and last region */
23878 footprint_header = (struct vm_map_corpse_footprint_header *)
23879 new_map->vmmap_corpse_footprint;
23880 footprint_region = (struct vm_map_corpse_footprint_region *)
23881 ((char *)footprint_header +
23882 footprint_header->cf_last_region);
23883 }
23884 footprint_edge = ((uintptr_t)footprint_header +
23885 footprint_header->cf_size);
23886
23887 if ((!old_entry->is_sub_map && VME_OBJECT(old_entry) == VM_OBJECT_NULL) ||
23888 (old_entry->is_sub_map && !old_entry->use_pmap)) {
23889 /*
23890 * This entry has no vm-object or is a nested pmap and therefore no page
23891 * dispositions to record.
23892 */
23893 return KERN_SUCCESS;
23894 }
23895
23896 if ((footprint_region->cfr_vaddr +
23897 (((vm_map_offset_t)footprint_region->cfr_num_pages) *
23898 effective_page_size))
23899 != old_entry->vme_start) {
23900 uint64_t num_pages_delta, num_pages_delta_size;
23901 uint32_t region_offset_delta_size;
23902
23903 /*
23904 * Not the next contiguous virtual address:
23905 * start a new region or store "zero" dispositions for
23906 * the missing pages?
23907 */
23908 /* size of gap in actual page dispositions */
23909 num_pages_delta = ((old_entry->vme_start -
23910 footprint_region->cfr_vaddr) / effective_page_size)
23911 - footprint_region->cfr_num_pages;
23912 num_pages_delta_size = num_pages_delta * sizeof(cf_disp_t);
23913 /* size of gap as a new footprint region header */
23914 region_offset_delta_size =
23915 (sizeof(*footprint_region) +
23916 roundup(((footprint_region->cfr_num_pages -
23917 footprint_header->cf_last_zeroes) * sizeof(cf_disp_t)),
23918 sizeof(int)) -
23919 ((footprint_region->cfr_num_pages -
23920 footprint_header->cf_last_zeroes) * sizeof(cf_disp_t)));
23921 DTRACE_VM5(corpse_footprint_collect,
23922 uint32_t, footprint_header->cf_last_region,
23923 vm_map_offset_t, footprint_region->cfr_vaddr,
23924 uint32_t, footprint_region->cfr_num_pages,
23925 vm_map_offset_t, old_entry->vme_start,
23926 uin64_t, num_pages_delta);
23927 if (region_offset_delta_size < num_pages_delta_size ||
23928 os_add3_overflow(footprint_region->cfr_num_pages,
23929 (uint32_t) num_pages_delta,
23930 1,
23931 &num_pages_tmp)) {
23932 /*
23933 * Storing data for this gap would take more space
23934 * than inserting a new footprint region header:
23935 * let's start a new region and save space. If it's a
23936 * tie, let's avoid using a new region, since that
23937 * would require more region hops to find the right
23938 * range during lookups.
23939 *
23940 * If the current region's cfr_num_pages would overflow
23941 * if we added "zero" page dispositions for the gap,
23942 * no choice but to start a new region.
23943 */
23944 DTRACE_VM3(corpse_footprint_collect_new_region,
23945 vm_map_offset_t, old_entry->vme_start,
23946 vm_map_offset_t, footprint_region->cfr_vaddr,
23947 uint64_t, num_pages_delta);
23948 new_footprint_region =
23949 vm_map_corpse_footprint_new_region(footprint_header);
23950 /* check that we're not going over the edge */
23951 if (new_footprint_region == NULL) {
23952 goto over_the_edge;
23953 }
23954 footprint_region = new_footprint_region;
23955 /* initialize new region as empty */
23956 footprint_region->cfr_vaddr = old_entry->vme_start;
23957 footprint_region->cfr_num_pages = 0;
23958 } else {
23959 /*
23960 * Store "zero" page dispositions for the missing
23961 * pages.
23962 */
23963 DTRACE_VM3(corpse_footprint_collect_zero_gap,
23964 vm_map_offset_t, old_entry->vme_start,
23965 vm_map_offset_t, footprint_region->cfr_vaddr,
23966 uint64_t, num_pages_delta);
23967 for (; num_pages_delta > 0; num_pages_delta--) {
23968 next_disp_p = (cf_disp_t *)
23969 ((uintptr_t) footprint_region +
23970 sizeof(*footprint_region));
23971 next_disp_p += footprint_region->cfr_num_pages;
23972 /* check that we're not going over the edge */
23973 if ((uintptr_t)next_disp_p >= footprint_edge) {
23974 goto over_the_edge;
23975 }
23976 /* store "zero" disposition for this gap page */
23977 footprint_region->cfr_num_pages++;
23978 *next_disp_p = (cf_disp_t) 0;
23979 footprint_header->cf_last_zeroes++;
23980 }
23981 }
23982 }
23983
23984 for (va = old_entry->vme_start;
23985 va < old_entry->vme_end;
23986 va += effective_page_size) {
23987 int disposition;
23988 cf_disp_t cf_disp;
23989
23990 vm_map_footprint_query_page_info_exclusive(old_map,
23991 old_entry,
23992 va,
23993 &disposition);
23994 cf_disp = vm_page_disposition_to_cf_disp(disposition);
23995
23996 DTRACE_VM2(corpse_footprint_collect_page_info,
23997 vm_map_offset_t, va,
23998 cf_disp_t, cf_disp);
23999
24000 if (cf_disp == 0 && footprint_region->cfr_num_pages == 0) {
24001 /*
24002 * Ignore "zero" dispositions at start of
24003 * region: just move start of region.
24004 */
24005 footprint_region->cfr_vaddr += effective_page_size;
24006 continue;
24007 }
24008
24009 /* would region's cfr_num_pages overflow? */
24010 if (os_add_overflow(footprint_region->cfr_num_pages, 1,
24011 &num_pages_tmp)) {
24012 /* overflow: create a new region */
24013 new_footprint_region =
24014 vm_map_corpse_footprint_new_region(
24015 footprint_header);
24016 if (new_footprint_region == NULL) {
24017 goto over_the_edge;
24018 }
24019 footprint_region = new_footprint_region;
24020 footprint_region->cfr_vaddr = va;
24021 footprint_region->cfr_num_pages = 0;
24022 }
24023
24024 next_disp_p = (cf_disp_t *) ((uintptr_t) footprint_region +
24025 sizeof(*footprint_region));
24026 next_disp_p += footprint_region->cfr_num_pages;
24027 /* check that we're not going over the edge */
24028 if ((uintptr_t)next_disp_p >= footprint_edge) {
24029 goto over_the_edge;
24030 }
24031 /* store this dispostion */
24032 *next_disp_p = cf_disp;
24033 footprint_region->cfr_num_pages++;
24034
24035 if (cf_disp != 0) {
24036 /* non-zero disp: break the current zero streak */
24037 footprint_header->cf_last_zeroes = 0;
24038 /* done */
24039 continue;
24040 }
24041
24042 /* zero disp: add to the current streak of zeroes */
24043 footprint_header->cf_last_zeroes++;
24044 if ((footprint_header->cf_last_zeroes +
24045 roundup(((footprint_region->cfr_num_pages -
24046 footprint_header->cf_last_zeroes) * sizeof(cf_disp_t)) &
24047 (sizeof(int) - 1),
24048 sizeof(int))) <
24049 (sizeof(*footprint_header))) {
24050 /*
24051 * There are not enough trailing "zero" dispositions
24052 * (+ the extra padding we would need for the previous
24053 * region); creating a new region would not save space
24054 * at this point, so let's keep this "zero" disposition
24055 * in this region and reconsider later.
24056 */
24057 continue;
24058 }
24059 /*
24060 * Create a new region to avoid having too many consecutive
24061 * "zero" dispositions.
24062 */
24063 new_footprint_region =
24064 vm_map_corpse_footprint_new_region(footprint_header);
24065 if (new_footprint_region == NULL) {
24066 goto over_the_edge;
24067 }
24068 footprint_region = new_footprint_region;
24069 /* initialize the new region as empty ... */
24070 footprint_region->cfr_num_pages = 0;
24071 /* ... and skip this "zero" disp */
24072 footprint_region->cfr_vaddr = va + effective_page_size;
24073 }
24074 return KERN_SUCCESS;
24075
24076over_the_edge:
24077 vm_log_error("corpse footprint buffer was exhausted at 0x%llx -- footprint "
24078 "data may be lost\n", va);
24079 vm_map_corpse_footprint_full++;
24080 return KERN_RESOURCE_SHORTAGE;
24081}
24082
24083/*
24084 * vm_map_corpse_footprint_collect_done:
24085 * completes the footprint collection by getting rid of any remaining
24086 * trailing "zero" dispositions and trimming the unused part of the
24087 * kernel buffer
24088 */
24089void
24090vm_map_corpse_footprint_collect_done(
24091 vm_map_t new_map)
24092{
24093 struct vm_map_corpse_footprint_header *footprint_header;
24094 struct vm_map_corpse_footprint_region *footprint_region;
24095 vm_size_t buf_size, actual_size;
24096
24097 assert(new_map->has_corpse_footprint);
24098 if (!new_map->has_corpse_footprint ||
24099 new_map->vmmap_corpse_footprint == NULL) {
24100 return;
24101 }
24102
24103 footprint_header = (struct vm_map_corpse_footprint_header *)
24104 new_map->vmmap_corpse_footprint;
24105 buf_size = footprint_header->cf_size;
24106
24107 footprint_region = (struct vm_map_corpse_footprint_region *)
24108 ((char *)footprint_header +
24109 footprint_header->cf_last_region);
24110
24111 /* get rid of trailing zeroes in last region */
24112 assert(footprint_region->cfr_num_pages >= footprint_header->cf_last_zeroes);
24113 footprint_region->cfr_num_pages -= footprint_header->cf_last_zeroes;
24114 footprint_header->cf_last_zeroes = 0;
24115
24116 actual_size = (vm_size_t)(footprint_header->cf_last_region +
24117 sizeof(*footprint_region) +
24118 (footprint_region->cfr_num_pages * sizeof(cf_disp_t)));
24119
24120// printf("FBDP map %p buf_size 0x%llx actual_size 0x%llx\n", new_map, (uint64_t) buf_size, (uint64_t) actual_size);
24121 vm_map_corpse_footprint_size_avg =
24122 (((vm_map_corpse_footprint_size_avg *
24123 vm_map_corpse_footprint_count) +
24124 actual_size) /
24125 (vm_map_corpse_footprint_count + 1));
24126 vm_map_corpse_footprint_count++;
24127 if (actual_size > vm_map_corpse_footprint_size_max) {
24128 vm_map_corpse_footprint_size_max = actual_size;
24129 }
24130
24131 actual_size = round_page(actual_size);
24132 assert3u(buf_size, >=, actual_size);
24133 if (buf_size > actual_size) {
24134 /*
24135 * Free unused space at the end of the buffer
24136 */
24137 kmem_guard_t guard = vm_map_corpse_footprint_guard(new_map);
24138 kmem_return_t kmr = kmem_realloc_guard(kernel_map,
24139 (vm_offset_t)footprint_header,
24140 /* Account for guard page */
24141 buf_size + PAGE_SIZE,
24142 actual_size + PAGE_SIZE,
24143 KMR_DATA | KMR_GUARD_LAST | KMR_FREEOLD | KMR_KOBJECT,
24144 guard);
24145 assertf(kmr.kmr_return == KERN_SUCCESS,
24146 "trim: footprint_header %p buf_size 0x%llx actual_size 0x%llx kr=0x%x\n",
24147 footprint_header,
24148 (uint64_t) buf_size,
24149 (uint64_t) actual_size,
24150 kmr.kmr_return);
24151 footprint_header = (struct vm_map_corpse_footprint_header *)kmr.kmr_ptr;
24152 assert3p(footprint_header, !=, NULL);
24153 new_map->vmmap_corpse_footprint = footprint_header;
24154 footprint_region = NULL;
24155 }
24156
24157 footprint_header->cf_size = actual_size;
24158}
24159
24160/*
24161 * vm_map_corpse_footprint_query_page_info:
24162 * retrieves the disposition of the page at virtual address "vaddr"
24163 * in the forked corpse's VM map
24164 *
24165 * This is the equivalent of vm_map_footprint_query_page_info() for a forked corpse.
24166 */
24167kern_return_t
24168vm_map_corpse_footprint_query_page_info(
24169 vm_map_t map,
24170 vm_map_offset_t va,
24171 int *disposition_p)
24172{
24173 struct vm_map_corpse_footprint_header *footprint_header;
24174 struct vm_map_corpse_footprint_region *footprint_region;
24175 uint32_t footprint_region_offset;
24176 vm_map_offset_t region_start, region_end;
24177 int disp_idx;
24178 kern_return_t kr;
24179 int effective_page_size;
24180 cf_disp_t cf_disp;
24181
24182 if (!map->has_corpse_footprint) {
24183 *disposition_p = 0;
24184 kr = KERN_INVALID_ARGUMENT;
24185 goto done;
24186 }
24187
24188 footprint_header = map->vmmap_corpse_footprint;
24189 if (footprint_header == NULL) {
24190 *disposition_p = 0;
24191// if (va < SHARED_REGION_BASE_ARM64) printf("FBDP %d query map %p va 0x%llx disp 0x%x\n", __LINE__, map, va, *disposition_p);
24192 kr = KERN_INVALID_ARGUMENT;
24193 goto done;
24194 }
24195
24196 /* start looking at the hint ("cf_hint_region") */
24197 footprint_region_offset = footprint_header->cf_hint_region;
24198
24199 effective_page_size = MIN(PAGE_SIZE, VM_MAP_PAGE_SIZE(map));
24200
24201lookup_again:
24202 if (footprint_region_offset < sizeof(*footprint_header)) {
24203 /* hint too low: start from 1st region */
24204 footprint_region_offset = sizeof(*footprint_header);
24205 }
24206 if (footprint_region_offset > footprint_header->cf_last_region) {
24207 /* hint too high: re-start from 1st region */
24208 footprint_region_offset = sizeof(*footprint_header);
24209 }
24210 footprint_region = (struct vm_map_corpse_footprint_region *)
24211 ((char *)footprint_header + footprint_region_offset);
24212 region_start = footprint_region->cfr_vaddr;
24213 region_end = (region_start +
24214 ((vm_map_offset_t)(footprint_region->cfr_num_pages) *
24215 effective_page_size));
24216 if (va < region_start &&
24217 footprint_region_offset != sizeof(*footprint_header)) {
24218 /* our range starts before the hint region */
24219
24220 /* reset the hint (in a racy way...) */
24221 footprint_header->cf_hint_region = sizeof(*footprint_header);
24222 /* lookup "va" again from 1st region */
24223 footprint_region_offset = sizeof(*footprint_header);
24224 goto lookup_again;
24225 }
24226
24227 while (va >= region_end) {
24228 if (footprint_region_offset >= footprint_header->cf_last_region) {
24229 break;
24230 }
24231 /* skip the region's header */
24232 footprint_region_offset += sizeof(*footprint_region);
24233 /* skip the region's page dispositions */
24234 footprint_region_offset += (footprint_region->cfr_num_pages * sizeof(cf_disp_t));
24235 /* align to next word boundary */
24236 footprint_region_offset =
24237 roundup(footprint_region_offset,
24238 sizeof(int));
24239 footprint_region = (struct vm_map_corpse_footprint_region *)
24240 ((char *)footprint_header + footprint_region_offset);
24241 region_start = footprint_region->cfr_vaddr;
24242 region_end = (region_start +
24243 ((vm_map_offset_t)(footprint_region->cfr_num_pages) *
24244 effective_page_size));
24245 }
24246 if (va < region_start || va >= region_end) {
24247 /* page not found */
24248 *disposition_p = 0;
24249// if (va < SHARED_REGION_BASE_ARM64) printf("FBDP %d query map %p va 0x%llx disp 0x%x\n", __LINE__, map, va, *disposition_p);
24250 kr = KERN_SUCCESS;
24251 goto done;
24252 }
24253
24254 /* "va" found: set the lookup hint for next lookup (in a racy way...) */
24255 footprint_header->cf_hint_region = footprint_region_offset;
24256
24257 /* get page disposition for "va" in this region */
24258 disp_idx = (int) ((va - footprint_region->cfr_vaddr) / effective_page_size);
24259 cf_disp = footprint_region->cfr_disposition[disp_idx];
24260 *disposition_p = vm_page_cf_disp_to_disposition(cf_disp);
24261 kr = KERN_SUCCESS;
24262done:
24263// if (va < SHARED_REGION_BASE_ARM64) printf("FBDP %d query map %p va 0x%llx disp 0x%x\n", __LINE__, map, va, *disposition_p);
24264 /* dtrace -n 'vminfo:::footprint_query_page_info { printf("map 0x%p va 0x%llx disp 0x%x kr 0x%x", arg0, arg1, arg2, arg3); }' */
24265 DTRACE_VM4(footprint_query_page_info,
24266 vm_map_t, map,
24267 vm_map_offset_t, va,
24268 int, *disposition_p,
24269 kern_return_t, kr);
24270
24271 return kr;
24272}
24273
24274void
24275vm_map_corpse_footprint_destroy(
24276 vm_map_t map)
24277{
24278 if (map->has_corpse_footprint &&
24279 map->vmmap_corpse_footprint != NULL) {
24280 struct vm_map_corpse_footprint_header *footprint_header;
24281 vm_size_t buf_size;
24282
24283 footprint_header = map->vmmap_corpse_footprint;
24284 buf_size = footprint_header->cf_size;
24285 kmem_guard_t guard = vm_map_corpse_footprint_guard(map);
24286 kmem_free_guard(kernel_map, (vm_offset_t)footprint_header,
24287 buf_size + PAGE_SIZE,
24288 KMF_GUARD_LAST, guard);
24289 map->vmmap_corpse_footprint = NULL;
24290 map->has_corpse_footprint = FALSE;
24291 }
24292}
24293
24294/*
24295 * vm_map_copy_footprint_ledgers:
24296 * copies any ledger that's relevant to the memory footprint of "old_task"
24297 * into the forked corpse's task ("new_task")
24298 */
24299void
24300vm_map_copy_footprint_ledgers(
24301 task_t old_task,
24302 task_t new_task)
24303{
24304 vm_map_copy_ledger(old_task, new_task, task_ledgers.phys_footprint);
24305 vm_map_copy_ledger(old_task, new_task, task_ledgers.purgeable_nonvolatile);
24306 vm_map_copy_ledger(old_task, new_task, task_ledgers.purgeable_nonvolatile_compressed);
24307 vm_map_copy_ledger(old_task, new_task, task_ledgers.internal);
24308 vm_map_copy_ledger(old_task, new_task, task_ledgers.internal_compressed);
24309 vm_map_copy_ledger(old_task, new_task, task_ledgers.iokit_mapped);
24310 vm_map_copy_ledger(old_task, new_task, task_ledgers.alternate_accounting);
24311 vm_map_copy_ledger(old_task, new_task, task_ledgers.alternate_accounting_compressed);
24312 vm_map_copy_ledger(old_task, new_task, task_ledgers.page_table);
24313 vm_map_copy_ledger(old_task, new_task, task_ledgers.tagged_footprint);
24314 vm_map_copy_ledger(old_task, new_task, task_ledgers.tagged_footprint_compressed);
24315 vm_map_copy_ledger(old_task, new_task, task_ledgers.network_nonvolatile);
24316 vm_map_copy_ledger(old_task, new_task, task_ledgers.network_nonvolatile_compressed);
24317 vm_map_copy_ledger(old_task, new_task, task_ledgers.media_footprint);
24318 vm_map_copy_ledger(old_task, new_task, task_ledgers.media_footprint_compressed);
24319 vm_map_copy_ledger(old_task, new_task, task_ledgers.graphics_footprint);
24320 vm_map_copy_ledger(old_task, new_task, task_ledgers.graphics_footprint_compressed);
24321 vm_map_copy_ledger(old_task, new_task, task_ledgers.neural_footprint);
24322 vm_map_copy_ledger(old_task, new_task, task_ledgers.neural_footprint_compressed);
24323 vm_map_copy_ledger(old_task, new_task, task_ledgers.wired_mem);
24324 vm_map_copy_ledger(old_task, new_task, task_ledgers.neural_nofootprint_total);
24325}
24326
24327/*
24328 * vm_map_copy_ledger:
24329 * copy a single ledger from "old_task" to "new_task"
24330 */
24331void
24332vm_map_copy_ledger(
24333 task_t old_task,
24334 task_t new_task,
24335 int ledger_entry)
24336{
24337 ledger_amount_t old_balance, new_balance, delta;
24338
24339 assert(new_task->map->has_corpse_footprint);
24340 if (!new_task->map->has_corpse_footprint) {
24341 return;
24342 }
24343
24344 /* turn off sanity checks for the ledger we're about to mess with */
24345 ledger_disable_panic_on_negative(new_task->ledger,
24346 ledger_entry);
24347
24348 /* adjust "new_task" to match "old_task" */
24349 ledger_get_balance(old_task->ledger,
24350 ledger_entry,
24351 &old_balance);
24352 ledger_get_balance(new_task->ledger,
24353 ledger_entry,
24354 &new_balance);
24355 if (new_balance == old_balance) {
24356 /* new == old: done */
24357 } else if (new_balance > old_balance) {
24358 /* new > old ==> new -= new - old */
24359 delta = new_balance - old_balance;
24360 ledger_debit(new_task->ledger,
24361 ledger_entry,
24362 delta);
24363 } else {
24364 /* new < old ==> new += old - new */
24365 delta = old_balance - new_balance;
24366 ledger_credit(new_task->ledger,
24367 ledger_entry,
24368 delta);
24369 }
24370}
24371
24372/*
24373 * vm_map_get_pmap:
24374 * returns the pmap associated with the vm_map
24375 */
24376pmap_t
24377vm_map_get_pmap(vm_map_t map)
24378{
24379 return vm_map_pmap(map);
24380}
24381
24382ppnum_t
24383vm_map_get_phys_page(
24384 vm_map_t map,
24385 vm_offset_t addr)
24386{
24387 vm_object_offset_t offset;
24388 vm_object_t object;
24389 vm_map_offset_t map_offset;
24390 vm_map_entry_t entry;
24391 ppnum_t phys_page = 0;
24392
24393 vmlp_api_start(VM_MAP_GET_PHYS_PAGE);
24394
24395 map_offset = vm_map_trunc_page(addr, PAGE_MASK);
24396
24397 vm_map_lock(map);
24398 while (vm_map_lookup_entry(map, map_offset, &entry)) {
24399 if (entry->is_sub_map) {
24400 vm_map_t old_map;
24401 vm_map_lock(VME_SUBMAP(entry));
24402 old_map = map;
24403 map = VME_SUBMAP(entry);
24404 map_offset = (VME_OFFSET(entry) +
24405 (map_offset - entry->vme_start));
24406 vm_map_unlock(old_map);
24407 continue;
24408 }
24409
24410 vmlp_range_event_entry(map, entry);
24411
24412 if (VME_OBJECT(entry) == VM_OBJECT_NULL) {
24413 vm_map_unlock(map);
24414 vmlp_api_end(VM_MAP_GET_PHYS_PAGE, 0);
24415 return (ppnum_t) 0;
24416 }
24417 if (VME_OBJECT(entry)->phys_contiguous) {
24418 /* These are not standard pageable memory mappings */
24419 /* If they are not present in the object they will */
24420 /* have to be picked up from the pager through the */
24421 /* fault mechanism. */
24422 if (VME_OBJECT(entry)->vo_shadow_offset == 0) {
24423 /* need to call vm_fault */
24424 vm_map_unlock(map);
24425 vm_fault(map, map_offset, VM_PROT_NONE,
24426 FALSE /* change_wiring */, VM_KERN_MEMORY_NONE,
24427 THREAD_UNINT, NULL, 0);
24428 vm_map_lock(map);
24429 continue;
24430 }
24431 offset = (VME_OFFSET(entry) +
24432 (map_offset - entry->vme_start));
24433 phys_page = (ppnum_t)
24434 ((VME_OBJECT(entry)->vo_shadow_offset
24435 + offset) >> PAGE_SHIFT);
24436 break;
24437 }
24438 offset = (VME_OFFSET(entry) + (map_offset - entry->vme_start));
24439 object = VME_OBJECT(entry);
24440 vm_object_lock(object);
24441 while (TRUE) {
24442 vm_page_t dst_page = vm_page_lookup(object, offset);
24443 if (dst_page == VM_PAGE_NULL) {
24444 if (object->shadow) {
24445 vm_object_t old_object;
24446 vm_object_lock(object->shadow);
24447 old_object = object;
24448 offset = offset + object->vo_shadow_offset;
24449 object = object->shadow;
24450 vm_object_unlock(old_object);
24451 } else {
24452 vm_object_unlock(object);
24453 break;
24454 }
24455 } else {
24456 phys_page = (ppnum_t)(VM_PAGE_GET_PHYS_PAGE(dst_page));
24457 vm_object_unlock(object);
24458 break;
24459 }
24460 }
24461 break;
24462 }
24463
24464 vm_map_unlock(map);
24465 vmlp_api_end(VM_MAP_GET_PHYS_PAGE, phys_page);
24466 return phys_page;
24467}
24468
24469#if CONFIG_MAP_RANGES
24470static bitmap_t vm_map_user_range_heap_map[BITMAP_LEN(VM_MEMORY_COUNT)];
24471static bitmap_t vm_map_user_range_large_file_map[BITMAP_LEN(VM_MEMORY_COUNT)];
24472
24473static_assert((int)UMEM_RANGE_ID_DEFAULT == MACH_VM_RANGE_DEFAULT);
24474static_assert((int)UMEM_RANGE_ID_HEAP == MACH_VM_RANGE_DATA);
24475
24476/*
24477 * vm_map_range_map_init:
24478 * initializes the VM range ID map to enable index lookup
24479 * of user VM ranges based on VM tag from userspace.
24480 */
24481static void
24482vm_map_range_map_init(void)
24483{
24484 /*
24485 * VM_MEMORY_MALLOC{,_NANO} are skipped on purpose:
24486 * - the former is malloc metadata which should be kept separate
24487 * - the latter has its own ranges
24488 */
24489 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_HUGE);
24490 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_LARGE);
24491 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_LARGE_REUSED);
24492 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_MEDIUM);
24493 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_PROB_GUARD);
24494 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_SMALL);
24495 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_MALLOC_TINY);
24496 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_TCMALLOC);
24497 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_LIBNETWORK);
24498 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_IOACCELERATOR);
24499 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_IOSURFACE);
24500 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_IMAGEIO);
24501 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_COREGRAPHICS);
24502 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_CORESERVICES);
24503 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_COREDATA);
24504 bitmap_set(vm_map_user_range_heap_map, VM_MEMORY_LAYERKIT);
24505 bitmap_set(vm_map_user_range_large_file_map, VM_MEMORY_IOACCELERATOR);
24506 bitmap_set(vm_map_user_range_large_file_map, VM_MEMORY_IOSURFACE);
24507}
24508
24509static struct mach_vm_range
24510vm_map_range_random_uniform(
24511 vm_map_size_t req_size,
24512 vm_map_offset_t min_addr,
24513 vm_map_offset_t max_addr,
24514 vm_map_offset_t offmask)
24515{
24516 vm_map_offset_t random_addr;
24517 struct mach_vm_range alloc;
24518
24519 req_size = (req_size + offmask) & ~offmask;
24520 min_addr = (min_addr + offmask) & ~offmask;
24521 max_addr = max_addr & ~offmask;
24522
24523 read_random(&random_addr, sizeof(random_addr));
24524 random_addr %= (max_addr - req_size - min_addr);
24525 random_addr &= ~offmask;
24526
24527 alloc.min_address = min_addr + random_addr;
24528 alloc.max_address = min_addr + random_addr + req_size;
24529 return alloc;
24530}
24531
24532static vm_map_offset_t
24533vm_map_range_offmask(void)
24534{
24535 uint32_t pte_depth;
24536
24537 /*
24538 * PTE optimizations
24539 *
24540 *
24541 * 16k pages systems
24542 * ~~~~~~~~~~~~~~~~~
24543 *
24544 * A single L1 (sub-)page covers the address space.
24545 * - L2 pages cover 64G,
24546 * - L3 pages cover 32M.
24547 *
24548 * On embedded, the dynamic VA range is 64G and uses a single L2 page.
24549 * As a result, we really only need to align the ranges to 32M to avoid
24550 * partial L3 pages.
24551 *
24552 * On macOS, the usage of L2 pages will increase, so as a result we will
24553 * want to align ranges to 64G in order to utilize them fully.
24554 *
24555 *
24556 * 4k pages systems
24557 * ~~~~~~~~~~~~~~~~
24558 *
24559 * A single L0 (sub-)page covers the address space.
24560 * - L1 pages cover 512G,
24561 * - L2 pages cover 1G,
24562 * - L3 pages cover 2M.
24563 *
24564 * The long tail of processes on a system will tend to have a VA usage
24565 * (ignoring the shared regions) in the 100s of MB order of magnitnude.
24566 * This is achievable with a single L1 and a few L2s without
24567 * randomization.
24568 *
24569 * However once randomization is introduced, the system will immediately
24570 * need several L1s and many more L2s. As a result:
24571 *
24572 * - on embedded devices, the cost of these extra pages isn't
24573 * sustainable, and we just disable the feature entirely,
24574 *
24575 * - on macOS we align ranges to a 512G boundary so that the extra L1
24576 * pages can be used to their full potential.
24577 */
24578
24579 /*
24580 * note, this function assumes _non exotic mappings_
24581 * which is why it uses the native kernel's PAGE_SHIFT.
24582 */
24583#if XNU_PLATFORM_MacOSX
24584 pte_depth = PAGE_SHIFT > 12 ? 2 : 3;
24585#else /* !XNU_PLATFORM_MacOSX */
24586 pte_depth = PAGE_SHIFT > 12 ? 1 : 0;
24587#endif /* !XNU_PLATFORM_MacOSX */
24588
24589 if (pte_depth == 0) {
24590 return 0;
24591 }
24592
24593 return (1ull << ((PAGE_SHIFT - 3) * pte_depth + PAGE_SHIFT)) - 1;
24594}
24595
24596/*
24597 * vm_map_range_configure:
24598 * configures the user vm_map ranges by increasing the maximum VA range of
24599 * the map and carving out a range at the end of VA space (searching backwards
24600 * in the newly expanded map).
24601 */
24602kern_return_t
24603vm_map_range_configure(vm_map_t map, __unused bool needs_extra_jumbo_va)
24604{
24605 const vm_map_offset_t offmask = vm_map_range_offmask();
24606 struct mach_vm_range data_range;
24607 vm_map_offset_t default_end;
24608 kern_return_t kr;
24609
24610 vmlp_api_start(VM_MAP_RANGE_CONFIGURE);
24611
24612 if (!vm_map_is_64bit(map) || vm_map_is_exotic(map) || offmask == 0) {
24613 /*
24614 * No point doing vm ranges in a 32bit address space.
24615 */
24616 vmlp_api_end(VM_MAP_RANGE_CONFIGURE, KERN_NOT_SUPPORTED);
24617 return KERN_NOT_SUPPORTED;
24618 }
24619
24620 /* Should not be applying ranges to kernel map or kernel map submaps */
24621 assert(vm_map_pmap(map) != kernel_pmap);
24622
24623#if XNU_PLATFORM_MacOSX
24624
24625 /*
24626 * on macOS, the address space is a massive 47 bits (128T),
24627 * with several carve outs that processes can't use:
24628 * - the shared region
24629 * - the commpage region
24630 * - the GPU carve out (if applicable)
24631 *
24632 * and when nano-malloc is in use it desires memory at the 96T mark.
24633 *
24634 * However, their location is architecture dependent:
24635 * - On intel, the shared region and commpage are
24636 * at the very end of the usable address space (above +127T),
24637 * and there is no GPU carve out, and pthread wants to place
24638 * threads at the 112T mark (0x70T).
24639 *
24640 * - On arm64, these are in the same spot as on embedded devices:
24641 * o shared region: [ 6G, 10G) [ will likely grow over time ]
24642 * o commpage region: [63G, 64G)
24643 * o GPU carve out: [64G, 448G)
24644 *
24645 * This is conveninent because the mappings at the end of the address
24646 * space (when they exist) are made by the kernel.
24647 *
24648 * The policy is to allocate a random 1T for the data heap
24649 * in the end of the address-space in the:
24650 * - [0x71, 0x7f) range on Intel (to leave space for pthread stacks)
24651 * - [0x61, 0x7f) range on ASM (to leave space for Nano malloc).
24652 */
24653
24654 /* see NANOZONE_SIGNATURE in libmalloc */
24655#if __x86_64__
24656 default_end = 0x71ull << 40;
24657#else
24658 default_end = 0x61ull << 40;
24659#endif
24660 data_range = vm_map_range_random_uniform(1ull << 40,
24661 default_end, 0x7full << 40, offmask);
24662
24663#else /* !XNU_PLATFORM_MacOSX */
24664
24665 /*
24666 * Embedded devices:
24667 *
24668 * The default VA Size scales with the device physical memory.
24669 *
24670 * Out of that:
24671 * - the "zero" page typically uses 4G + some slide
24672 * - the shared region uses SHARED_REGION_SIZE bytes (4G)
24673 *
24674 * Without the use of jumbo or any adjustment to the address space,
24675 * a default VM map typically looks like this:
24676 *
24677 * 0G -->╒════════════╕
24678 * │ pagezero │
24679 * │ + slide │
24680 * ~4G -->╞════════════╡<-- vm_map_min(map)
24681 * │ │
24682 * 6G -->├────────────┤
24683 * │ shared │
24684 * │ region │
24685 * 10G -->├────────────┤
24686 * │ │
24687 * max_va -->├────────────┤<-- vm_map_max(map)
24688 * │ │
24689 * ╎ jumbo ╎
24690 * ╎ ╎
24691 * │ │
24692 * 63G -->╞════════════╡<-- MACH_VM_MAX_ADDRESS
24693 * │ commpage │
24694 * 64G -->├────────────┤<-- MACH_VM_MIN_GPU_CARVEOUT_ADDRESS
24695 * │ │
24696 * ╎ GPU ╎
24697 * ╎ carveout ╎
24698 * │ │
24699 * 448G -->├────────────┤<-- MACH_VM_MAX_GPU_CARVEOUT_ADDRESS
24700 * │ │
24701 * ╎ ╎
24702 * ╎ ╎
24703 * │ │
24704 * 512G -->╘════════════╛<-- (1ull << ARM_16K_TT_L1_SHIFT)
24705 *
24706 * When this drawing was made, "max_va" was smaller than
24707 * ARM64_MAX_OFFSET_DEVICE_LARGE (~15.5G), leaving shy of
24708 * 12G of address space for the zero-page, slide, files,
24709 * binaries, heap ...
24710 *
24711 * We will want to make a "heap/data" carve out inside
24712 * the jumbo range of half of that usable space, assuming
24713 * that this is less than a forth of the jumbo range.
24714 *
24715 * The assert below intends to catch when max_va grows
24716 * too large for this heuristic.
24717 */
24718
24719 vm_map_lock_read(map);
24720 default_end = vm_map_max(map);
24721 vm_map_unlock_read(map);
24722
24723 /*
24724 * Check that we're not already jumbo'd,
24725 * or our address space was somehow modified.
24726 *
24727 * If so we cannot guarantee that we can set up the ranges
24728 * safely without interfering with the existing map.
24729 */
24730 if (default_end > vm_compute_max_offset(true)) {
24731 vmlp_api_end(VM_MAP_RANGE_CONFIGURE, KERN_NO_SPACE);
24732 return KERN_NO_SPACE;
24733 }
24734
24735 if (pmap_max_offset(true, ARM_PMAP_MAX_OFFSET_DEFAULT)) {
24736 /*
24737 * an override boot-arg was set, disable user-ranges
24738 *
24739 * XXX: this is problematic because it means these boot-args
24740 * no longer test the behavior changing the value
24741 * of ARM64_MAX_OFFSET_DEVICE_* would have.
24742 */
24743 vmlp_api_end(VM_MAP_RANGE_CONFIGURE, KERN_NOT_SUPPORTED);
24744 return KERN_NOT_SUPPORTED;
24745 }
24746
24747 /* expand the default VM space to 64GB */
24748 vm_map_set_jumbo(map);
24749
24750 assert3u(7 * GiB(10) / 2, <=, vm_map_max(map) - default_end);
24751 data_range = vm_map_range_random_uniform(GiB(10),
24752 default_end + PAGE_SIZE, vm_map_max(map), offmask);
24753
24754#endif /* !XNU_PLATFORM_MacOSX */
24755
24756 /*
24757 * Poke holes so that ASAN or people listing regions
24758 * do not think this space is free.
24759 */
24760
24761 if (default_end != data_range.min_address) {
24762 kr = vm_map_enter(map, &default_end,
24763 data_range.min_address - default_end,
24764 0, VM_MAP_KERNEL_FLAGS_FIXED_PERMANENT(), VM_OBJECT_NULL,
24765 0, FALSE, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_DEFAULT);
24766 assert(kr == KERN_SUCCESS);
24767 }
24768
24769 if (data_range.max_address != vm_map_max(map)) {
24770 vm_map_entry_t entry;
24771 vm_size_t size;
24772
24773 /*
24774 * Extend the end of the hole to the next VM entry or the end of the map,
24775 * whichever comes first.
24776 */
24777 vm_map_lock_read(map);
24778 vm_map_lookup_entry_or_next(map, data_range.max_address, &entry);
24779
24780 if (entry != vm_map_to_entry(map) && !entry->is_sub_map) {
24781 vmlp_range_event_entry(map, entry);
24782 }
24783
24784 if (entry == vm_map_to_entry(map) || entry->vme_start > vm_map_max(map)) {
24785 size = vm_map_max(map) - data_range.max_address;
24786 } else {
24787 size = entry->vme_start - data_range.max_address;
24788 }
24789 vm_map_unlock_read(map);
24790
24791 kr = vm_map_enter(map, &data_range.max_address, size,
24792 0, VM_MAP_KERNEL_FLAGS_FIXED_PERMANENT(), VM_OBJECT_NULL,
24793 0, FALSE, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_DEFAULT);
24794 assert(kr == KERN_SUCCESS);
24795 }
24796
24797#if XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT
24798 if (needs_extra_jumbo_va) {
24799 /* This will grow the address space to MACH_VM_MAX_ADDRESS */
24800 vm_map_set_extra_jumbo(map);
24801 }
24802#endif /* XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT */
24803
24804 vm_map_lock(map);
24805 map->default_range.min_address = vm_map_min(map);
24806 map->default_range.max_address = default_end;
24807 map->data_range = data_range;
24808#if XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT
24809 /* If process has "extra jumbo" entitlement, enable large file range */
24810 if (needs_extra_jumbo_va) {
24811 map->large_file_range = vm_map_range_random_uniform(TiB(1),
24812 MACH_VM_JUMBO_ADDRESS, MACH_VM_MAX_ADDRESS, offmask);
24813 }
24814#endif /* XNU_TARGET_OS_IOS && EXTENDED_USER_VA_SUPPORT */
24815 map->uses_user_ranges = true;
24816 vm_map_unlock(map);
24817
24818 vmlp_api_end(VM_MAP_RANGE_CONFIGURE, KERN_SUCCESS);
24819 return KERN_SUCCESS;
24820}
24821
24822/*
24823 * vm_map_range_fork:
24824 * clones the array of ranges from old_map to new_map in support
24825 * of a VM map fork.
24826 */
24827void
24828vm_map_range_fork(vm_map_t new_map, vm_map_t old_map)
24829{
24830 if (!old_map->uses_user_ranges) {
24831 /* nothing to do */
24832 return;
24833 }
24834
24835 new_map->default_range = old_map->default_range;
24836 new_map->data_range = old_map->data_range;
24837
24838 if (old_map->extra_ranges_count) {
24839 vm_map_user_range_t otable, ntable;
24840 uint16_t count;
24841
24842 otable = old_map->extra_ranges;
24843 count = old_map->extra_ranges_count;
24844 ntable = kalloc_data(count * sizeof(struct vm_map_user_range),
24845 Z_WAITOK | Z_ZERO | Z_NOFAIL);
24846 memcpy(ntable, otable,
24847 count * sizeof(struct vm_map_user_range));
24848
24849 new_map->extra_ranges_count = count;
24850 new_map->extra_ranges = ntable;
24851 }
24852
24853 new_map->uses_user_ranges = true;
24854}
24855
24856/*
24857 * vm_map_get_user_range:
24858 * copy the VM user range for the given VM map and range ID.
24859 */
24860kern_return_t
24861vm_map_get_user_range(
24862 vm_map_t map,
24863 vm_map_range_id_t range_id,
24864 mach_vm_range_t range)
24865{
24866 if (map == NULL || !map->uses_user_ranges || range == NULL) {
24867 return KERN_INVALID_ARGUMENT;
24868 }
24869
24870 switch (range_id) {
24871 case UMEM_RANGE_ID_DEFAULT:
24872 *range = map->default_range;
24873 return KERN_SUCCESS;
24874
24875 case UMEM_RANGE_ID_HEAP:
24876 *range = map->data_range;
24877 return KERN_SUCCESS;
24878
24879 case UMEM_RANGE_ID_LARGE_FILE:
24880 /*
24881 * Because this function tells a user-space process about the user
24882 * ranges in its VM map, this case communicates whether the large file
24883 * range is in use. Note that this is different from how the large file
24884 * range ID is handled in `vm_map_get_range()`: there, we "resolve" the
24885 * VA policy and return either the large file range or data range,
24886 * depending on whether the large file range is enabled.
24887 */
24888 if (map->large_file_range.min_address != map->large_file_range.max_address) {
24889 /* large file range is configured and should be used */
24890 *range = map->large_file_range;
24891 } else {
24892 return KERN_INVALID_ARGUMENT;
24893 }
24894 return KERN_SUCCESS;
24895
24896 default:
24897 return KERN_INVALID_ARGUMENT;
24898 }
24899}
24900
24901static vm_map_range_id_t
24902vm_map_user_range_resolve(
24903 vm_map_t map,
24904 mach_vm_address_t addr,
24905 mach_vm_size_t size,
24906 mach_vm_range_t range)
24907{
24908 struct mach_vm_range tmp;
24909
24910 vm_map_lock_assert_held(map);
24911
24912 static_assert((int)UMEM_RANGE_ID_DEFAULT == MACH_VM_RANGE_DEFAULT);
24913 static_assert((int)UMEM_RANGE_ID_HEAP == MACH_VM_RANGE_DATA);
24914
24915 if (mach_vm_range_contains(&map->default_range, addr, size)) {
24916 if (range) {
24917 *range = map->default_range;
24918 }
24919 return UMEM_RANGE_ID_DEFAULT;
24920 }
24921
24922 if (mach_vm_range_contains(&map->data_range, addr, size)) {
24923 if (range) {
24924 *range = map->data_range;
24925 }
24926 return UMEM_RANGE_ID_HEAP;
24927 }
24928
24929 if (mach_vm_range_contains(&map->large_file_range, addr, size)) {
24930 if (range) {
24931 *range = map->large_file_range;
24932 }
24933 return UMEM_RANGE_ID_LARGE_FILE;
24934 }
24935
24936 for (size_t i = 0; i < map->extra_ranges_count; i++) {
24937 vm_map_user_range_t r = &map->extra_ranges[i];
24938
24939 tmp.min_address = r->vmur_min_address;
24940 tmp.max_address = r->vmur_max_address;
24941
24942 if (mach_vm_range_contains(&tmp, addr, size)) {
24943 if (range) {
24944 *range = tmp;
24945 }
24946 return r->vmur_range_id;
24947 }
24948 }
24949
24950 if (range) {
24951 range->min_address = range->max_address = 0;
24952 }
24953 return UMEM_RANGE_ID_DEFAULT;
24954}
24955#endif /* CONFIG_MAP_RANGES */
24956
24957void
24958vm_map_kernel_flags_update_range_id(
24959 vm_map_kernel_flags_t *vmkf,
24960 vm_map_t map,
24961 __unused vm_map_size_t size)
24962{
24963 if (map == kernel_map) {
24964 if (vmkf->vmkf_range_id == KMEM_RANGE_ID_NONE) {
24965 vmkf->vmkf_range_id = KMEM_RANGE_ID_DATA;
24966 }
24967#if CONFIG_MAP_RANGES
24968 } else if (vmkf->vm_tag < VM_MEMORY_COUNT &&
24969 vmkf->vmkf_range_id == UMEM_RANGE_ID_DEFAULT) {
24970 if (bitmap_test(vm_map_user_range_large_file_map, vmkf->vm_tag)
24971 || size >= VM_LARGE_FILE_THRESHOLD) {
24972 /*
24973 * if the map doesn't have the large file range configured,
24974 * the range will get resolved to the heap range in `vm_map_get_range`
24975 */
24976 vmkf->vmkf_range_id = UMEM_RANGE_ID_LARGE_FILE;
24977 } else if (bitmap_test(vm_map_user_range_heap_map, vmkf->vm_tag)) {
24978 vmkf->vmkf_range_id = UMEM_RANGE_ID_HEAP;
24979 }
24980#endif /* CONFIG_MAP_RANGES */
24981 }
24982}
24983
24984/*
24985 * vm_map_entry_has_device_pager:
24986 * Check if the vm map entry specified by the virtual address has a device pager.
24987 * If the vm map entry does not exist or if the map is NULL, this returns FALSE.
24988 */
24989boolean_t
24990vm_map_entry_has_device_pager(vm_map_t map, vm_map_offset_t vaddr)
24991{
24992 vm_map_entry_t entry;
24993 vm_object_t object;
24994 boolean_t result;
24995
24996 vmlp_api_start(VM_MAP_ENTRY_HAS_DEVICE_PAGER);
24997
24998 if (map == NULL) {
24999 vmlp_api_end(VM_MAP_ENTRY_HAS_DEVICE_PAGER, FALSE);
25000 return FALSE;
25001 }
25002
25003 vm_map_lock_read(map);
25004 while (TRUE) {
25005 if (!vm_map_lookup_entry(map, vaddr, &entry)) {
25006 result = FALSE;
25007 break;
25008 }
25009 if (entry->is_sub_map) {
25010 // Check the submap
25011 vm_map_t submap = VME_SUBMAP(entry);
25012 assert(submap != NULL);
25013 vm_map_lock_read(submap);
25014 vm_map_unlock_read(map);
25015 map = submap;
25016 continue;
25017 }
25018
25019 vmlp_range_event_entry(map, entry);
25020
25021 object = VME_OBJECT(entry);
25022 if (object != NULL && object->pager != NULL && is_device_pager_ops(object->pager->mo_pager_ops)) {
25023 result = TRUE;
25024 break;
25025 }
25026 result = FALSE;
25027 break;
25028 }
25029
25030 vm_map_unlock_read(map);
25031 vmlp_api_end(VM_MAP_ENTRY_HAS_DEVICE_PAGER, result);
25032 return result;
25033}
25034
25035bool
25036vm_map_is_sealed(
25037 vm_map_t map)
25038{
25039 return map->vmmap_sealed == VM_MAP_SEALED;
25040}
25041
25042void
25043vm_map_seal(
25044 vm_map_t map,
25045 bool nested_pmap)
25046{
25047 vm_map_entry_t entry;
25048
25049 vm_map_lock(map);
25050
25051 assert3u(map->vmmap_sealed, ==, VM_MAP_WILL_BE_SEALED);
25052 if (nested_pmap && map->pmap != PMAP_NULL) {
25053 map->mapped_in_other_pmaps = true;
25054 }
25055
25056 for (entry = vm_map_first_entry(map);
25057 entry != vm_map_to_entry(map);
25058 entry = entry->vme_next) {
25059 vm_object_t object;
25060
25061 assert(!entry->is_sub_map);
25062 if (VME_OBJECT(entry) == VM_OBJECT_NULL) {
25063 object = vm_object_allocate(entry->vme_end - entry->vme_start, map->serial_id);
25064 VME_OBJECT_SET(entry, object, true, 0);
25065 VME_OFFSET_SET(entry, 0);
25066 entry->needs_copy = false;
25067 }
25068 object = VME_OBJECT(entry);
25069 if (entry->needs_copy) {
25070 assert(object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC);
25071 VME_OBJECT_SHADOW(entry, entry->vme_end - entry->vme_start, TRUE);
25072 entry->needs_copy = FALSE;
25073 object = VME_OBJECT(entry);
25074 }
25075 vm_object_lock(object);
25076 if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
25077 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
25078 object->true_share = true;
25079 }
25080 vm_object_unlock(object);
25081 assert(VME_OBJECT(entry) != VM_OBJECT_NULL);
25082 assert(VME_OBJECT(entry)->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC);
25083 }
25084
25085 map->vmmap_sealed = VM_MAP_SEALED;
25086 /* we can't hold a write lock on a sealed map so downgrade */
25087 vm_map_lock_write_to_read(map);
25088 vm_map_unlock_read(map);
25089}
25090
25091
25092#if DEVELOPMENT || DEBUG
25093
25094/*
25095 * Support functions for userspace tests of constant submaps.
25096 *
25097 * Two functions below can be called by userspace via sysctl:
25098 * vm_map_testing_make_sealed_submap()
25099 * vm_map_testing_remap_submap()
25100 *
25101 * To write a test that uses a submap:
25102 * 1. Create allocations in your map that will become the new submap's contents.
25103 * 2. Call vm_map_testing_make_sealed_submap() to replace those
25104 * allocations with a submap containing those allocations.
25105 * 3. Call vm_map_testing_remap_submap() to create additional
25106 * mappings of the submap (or portions thereof) in the parent map.
25107 */
25108
25109/*
25110 * Look for a submap mapped in parent_map at submap_base_address.
25111 * Panic if it is not there.
25112 */
25113static void
25114vm_map_testing_require_submap_at_address(
25115 vm_map_t parent_map,
25116 mach_vm_address_t address,
25117 vm_map_t * const out_submap,
25118 vm_map_entry_t * const out_parent_entry)
25119{
25120 vm_map_entry_t entry;
25121
25122 vm_map_lock_assert_held(parent_map);
25123
25124 if (!vm_map_lookup_entry(parent_map, address, &entry)) {
25125 panic("no map entry contains address");
25126 }
25127 assertf(entry->vme_start == address,
25128 "submap test: submap_base_address is not the start of a map entry");
25129 assertf(entry->is_sub_map,
25130 "submap test: entry at submap_base_address is not a submap");
25131
25132 if (out_submap) {
25133 *out_submap = VME_SUBMAP(entry);
25134 }
25135 if (out_parent_entry) {
25136 *out_parent_entry = entry;
25137 }
25138}
25139
25140/*
25141 * Map a submap into current_map().
25142 * current_map's submap entry will be at [start, end).
25143 * The start of the mapping will be at submap_offset in the submap.
25144 *
25145 * parent_map must be locked on entry and is unlocked on exit.
25146 *
25147 * For testing purposes only.
25148 */
25149static void
25150vm_map_testing_remap_submap_and_unlock(
25151 vm_map_t parent_map,
25152 vm_map_t submap,
25153 mach_vm_address_t start,
25154 mach_vm_address_t end,
25155 mach_vm_address_t submap_offset)
25156{
25157 kern_return_t kr;
25158 mach_vm_address_t submap_end_offset;
25159 mach_vm_address_t new_start;
25160 vm_prot_t cur_prot, max_prot;
25161 vm_map_kernel_flags_t vmk_flags;
25162 bool overflowed;
25163
25164 assertf(!vm_kernel_map_is_kernel(parent_map),
25165 "submap test: for userspace maps only");
25166 assertf(!vm_map_is_sealed(parent_map),
25167 "submap test: parent map may not be sealed");
25168
25169 assertf(parent_map != submap,
25170 "submap test: parent map and submap must be distinct");
25171 assertf(!vm_kernel_map_is_kernel(submap),
25172 "submap test: submap must not be the kernel map");
25173 assertf(vm_map_is_sealed(submap),
25174 "submap test: submap must be sealed");
25175 assertf(VM_MAP_PAGE_MASK(parent_map) == VM_MAP_PAGE_MASK(submap),
25176 "submap test: parent map and submap must have the same page size");
25177
25178 assertf((start & VM_MAP_PAGE_MASK(parent_map)) == 0,
25179 "submap test: start address must be page-aligned");
25180 assertf((end & VM_MAP_PAGE_MASK(parent_map)) == 0,
25181 "submap test: end address must be page-aligned");
25182 assertf((submap_offset & VM_MAP_PAGE_MASK(parent_map)) == 0,
25183 "submap test: offset in submap must be page-aligned");
25184 assertf(start < end,
25185 "submap test: start must precede end");
25186
25187 /* submap_end_offset = submap_offset + (end - start) */
25188 overflowed = os_add_overflow(submap_offset, end - start, &submap_end_offset);
25189 assertf(!overflowed, "arithmetic overflow in submap_offset + (end - start)");
25190
25191 /*
25192 * The range to be mapped must exist in the submap.
25193 * We assume here that a sealed map has no holes.
25194 */
25195 assertf(vm_map_first_entry(submap) != vm_map_to_entry(submap),
25196 "submap test: submap must not be empty");
25197 assertf(vm_map_first_entry(submap)->vme_start <= submap_offset,
25198 "submap test: submap range to remap is unmapped in the submap");
25199 assertf(vm_map_last_entry(submap)->vme_end >= submap_end_offset,
25200 "submap test: submap range to remap is unmapped in the submap");
25201
25202 vmk_flags = VM_MAP_KERNEL_FLAGS_FIXED(.vmkf_submap = true);
25203
25204 /*
25205 * Compute protections for the submap's map entry in the parent map.
25206 * Copied from vm_shared_region_insert_submap(): we want to do as
25207 * many of the same things as real shared region submaps as we can.
25208 */
25209 cur_prot = VM_PROT_READ;
25210 if (VM_MAP_POLICY_WRITABLE_SHARED_REGION(parent_map)) {
25211 max_prot = VM_PROT_ALL;
25212 } else {
25213 max_prot = VM_PROT_READ;
25214 vmk_flags.vmf_permanent = true;
25215 }
25216
25217 vm_map_reference(submap);
25218 vm_map_unlock(parent_map);
25219
25220 /* Map the submap. */
25221 new_start = start;
25222 kr = vm_map_enter(parent_map, &new_start, end - start, 0,
25223 vmk_flags, (vm_object_t)(uintptr_t)submap, submap_offset, true /* copy */,
25224 cur_prot, max_prot, VM_INHERIT_SHARE /* same as vm_shared_region.c */);
25225 assertf(kr == KERN_SUCCESS,
25226 "submap test: vm_map_enter of submap entry into parent map failed");
25227 assertf(new_start == start,
25228 "submap test: submap entry was inserted at the wrong address");
25229}
25230
25231/*
25232 * Map part of a submap as a new submap entry in parent_map.
25233 * The submap must already be mapped in its entirety at submap_base_address.
25234 * The remapping destination is [start..end) in parent_map.
25235 * The remapping source is [offset, offset + (end-start)) in the submap.
25236 *
25237 * For testing purposes only.
25238 */
25239void
25240vm_map_testing_remap_submap(
25241 vm_map_t parent_map,
25242 mach_vm_address_t submap_base_address,
25243 mach_vm_address_t start,
25244 mach_vm_address_t end,
25245 mach_vm_address_t offset)
25246{
25247 vm_map_t submap;
25248
25249 vm_map_lock(parent_map);
25250
25251 /* Find the submap. It is mapped in parent_map at submap_base_address. */
25252 vm_map_testing_require_submap_at_address(
25253 parent_map, submap_base_address, &submap, NULL);
25254
25255 /* Map the submap as requested. */
25256 vm_map_testing_remap_submap_and_unlock(parent_map, submap, start, end, offset);
25257}
25258
25259/*
25260 * Create a new constant/sealed submap. Map it into parent_map at [start, end).
25261 * The new submap's contents are the map entries initially in the range [start, end).
25262 * The new submap does not use a nested pmap.
25263 * On entry: no existing map entry may cross start or end
25264 *
25265 * For testing purposes only.
25266 */
25267void
25268vm_map_testing_make_sealed_submap(
25269 vm_map_t parent_map,
25270 mach_vm_address_t start,
25271 mach_vm_address_t end)
25272{
25273 vm_map_t submap;
25274 vm_map_entry_t entry, next_entry;
25275
25276 assertf(!vm_kernel_map_is_kernel(parent_map),
25277 "submap test: for userspace maps only");
25278 assertf(!vm_map_is_sealed(parent_map),
25279 "submap test: parent map may not be sealed");
25280
25281 assertf((start & VM_MAP_PAGE_MASK(parent_map)) == 0,
25282 "submap test: start address must be page-aligned");
25283 assertf((end & VM_MAP_PAGE_MASK(parent_map)) == 0,
25284 "submap test: end address must be page-aligned");
25285 assertf(start < end,
25286 "submap test: start must precede end");
25287
25288 vm_map_lock(parent_map);
25289
25290 /*
25291 * Create the map that will become the submap.
25292 *
25293 * Submap's address range starts at 0 to match the real shared region.
25294 *
25295 * PPL/SPTM allows only one pmap_nested submap per map.
25296 * The real shared region gets that, so we can't test pmap nesting.
25297 * Instead this submap gets a NULL pmap.
25298 */
25299 submap = vm_map_create_options(NULL /* pmap */, 0, end - start, VM_MAP_CREATE_PAGEABLE);
25300 assert(submap);
25301 submap->is_nested_map = true;
25302 submap->vmmap_sealed = VM_MAP_WILL_BE_SEALED;
25303 vm_map_set_page_shift(submap, VM_MAP_PAGE_SHIFT(parent_map));
25304
25305 /*
25306 * Move map entries from the parent map into the submap.
25307 * Also verify that no entry crosses start or end.
25308 *
25309 * This is not a copy+delete operation because for testing purposes
25310 * we want to preserve as much of the map entry state as possible.
25311 * This operation temporarily overrides things like wire count and
25312 * permanent, but for testing purposes that is acceptable.
25313 */
25314 next_entry = NULL;
25315 for (vm_map_lookup_entry_or_next(parent_map, start, &entry);
25316 entry != vm_map_to_entry(parent_map) && entry->vme_start < end;
25317 entry = next_entry) {
25318 vm_map_offset_t entry_size;
25319
25320 /* Fetch next_entry now because we're about to unlink this entry. */
25321 next_entry = entry->vme_next;
25322
25323 /*
25324 * Executable or TPRO memory in the submap is unimplemented.
25325 * Real shared region submaps get vm_map_set_tpro()
25326 * and vm_map_cs_enforcement_set(true).
25327 */
25328 assertf((entry->protection & VM_PROT_ALLEXEC) == 0,
25329 "submap test: executable memory is unimplemented");
25330 assertf((entry->max_protection & VM_PROT_ALLEXEC) == 0,
25331 "submap test: executable memory is unimplemented");
25332#if __arm64e__
25333 assertf(!entry->used_for_tpro,
25334 "submap test: TPRO memory is unimplemented");
25335#endif
25336
25337 /*
25338 * Entry ends after our start address, guaranteed by
25339 * vm_map_lookup_entry_or_next() and our loop condition.
25340 * If the entry starts before our start address then
25341 * it crosses our start address which is not allowed.
25342 */
25343 assertf(entry->vme_start >= start,
25344 "submap test: entry crosses new submap bounds"); /* verify */
25345 assertf(entry->vme_end > start,
25346 "submap test: entry crosses new submap bounds"); /* known */
25347
25348 /*
25349 * Entry starts before our end address, guaranteed by our
25350 * loop condition. If the entry ends after our end address
25351 * then it crosses our end address which is not allowed.
25352 */
25353 assertf(entry->vme_start < end,
25354 "submap test: entry crosses new submap bounds"); /* known */
25355 assertf(entry->vme_end <= end,
25356 "submap test: entry crosses new submap bounds"); /* verify */
25357
25358 /* Entry's address range is good. Move it. */
25359
25360 assertf(!entry->is_sub_map,
25361 "submap test: can't move submap entry into a submap");
25362 assertf(!entry->in_transition,
25363 "submap test: can't move in_transition entry into a submap");
25364
25365 /* Unlink map entry from parent map. */
25366 entry_size = entry->vme_end - entry->vme_start;
25367 vm_map_store_entry_unlink(parent_map, entry, false /* check_permanent */);
25368 parent_map->size -= entry_size;
25369
25370 /*
25371 * Address `start` in the parent map is address 0 in the submap.
25372 * Subtract `start` from the entry's bounds to move it to its
25373 * place in the submap.
25374 */
25375 entry->vme_start -= start;
25376 entry->vme_end -= start;
25377
25378 /* Link map entry into the submap. */
25379 vm_map_store_entry_link(submap, vm_map_last_entry(submap), entry, VM_MAP_KERNEL_FLAGS_NONE);
25380 submap->size += entry_size;
25381 }
25382
25383 /* Submap is now populated. Seal it. */
25384 vm_map_seal(submap, false /* nested_pmap */);
25385
25386 /*
25387 * Verify that the parent map now contains nothing in [start, end).
25388 * Find the first map entry containing our start address or after it.
25389 * Either there must be no such entry,
25390 * or that entry must start after our end address.
25391 */
25392 vm_map_lookup_entry_or_next(parent_map, start, &entry);
25393 assertf(entry == vm_map_to_entry(parent_map) || entry->vme_start >= end,
25394 "submap test: intended submap range is not empty");
25395
25396 /*
25397 * Map the entire submap into the parent map at the same range we depopulated.
25398 * Also unlocks parent_map.
25399 */
25400 vm_map_testing_remap_submap_and_unlock(parent_map, submap,
25401 start, end, /* parent map range */
25402 0 /* start offset in the submap we created */);
25403 vm_map_deallocate(submap); /* now referenced only by the map entry */
25404}
25405
25406#endif /* DEVELOPMENT || DEBUG */
25407
25408#if MACH_ASSERT
25409
25410extern int pmap_ledgers_panic;
25411extern int pmap_ledgers_panic_leeway;
25412
25413#define LEDGER_DRIFT(__LEDGER) \
25414 int __LEDGER##_over; \
25415 ledger_amount_t __LEDGER##_over_total; \
25416 ledger_amount_t __LEDGER##_over_max; \
25417 int __LEDGER##_under; \
25418 ledger_amount_t __LEDGER##_under_total; \
25419 ledger_amount_t __LEDGER##_under_max
25420
25421struct {
25422 uint64_t num_pmaps_checked;
25423
25424 LEDGER_DRIFT(phys_footprint);
25425 LEDGER_DRIFT(internal);
25426 LEDGER_DRIFT(internal_compressed);
25427 LEDGER_DRIFT(external);
25428 LEDGER_DRIFT(reusable);
25429 LEDGER_DRIFT(iokit_mapped);
25430 LEDGER_DRIFT(alternate_accounting);
25431 LEDGER_DRIFT(alternate_accounting_compressed);
25432 LEDGER_DRIFT(page_table);
25433 LEDGER_DRIFT(purgeable_volatile);
25434 LEDGER_DRIFT(purgeable_nonvolatile);
25435 LEDGER_DRIFT(purgeable_volatile_compressed);
25436 LEDGER_DRIFT(purgeable_nonvolatile_compressed);
25437 LEDGER_DRIFT(tagged_nofootprint);
25438 LEDGER_DRIFT(tagged_footprint);
25439 LEDGER_DRIFT(tagged_nofootprint_compressed);
25440 LEDGER_DRIFT(tagged_footprint_compressed);
25441 LEDGER_DRIFT(network_volatile);
25442 LEDGER_DRIFT(network_nonvolatile);
25443 LEDGER_DRIFT(network_volatile_compressed);
25444 LEDGER_DRIFT(network_nonvolatile_compressed);
25445 LEDGER_DRIFT(media_nofootprint);
25446 LEDGER_DRIFT(media_footprint);
25447 LEDGER_DRIFT(media_nofootprint_compressed);
25448 LEDGER_DRIFT(media_footprint_compressed);
25449 LEDGER_DRIFT(graphics_nofootprint);
25450 LEDGER_DRIFT(graphics_footprint);
25451 LEDGER_DRIFT(graphics_nofootprint_compressed);
25452 LEDGER_DRIFT(graphics_footprint_compressed);
25453 LEDGER_DRIFT(neural_nofootprint);
25454 LEDGER_DRIFT(neural_footprint);
25455 LEDGER_DRIFT(neural_nofootprint_compressed);
25456 LEDGER_DRIFT(neural_footprint_compressed);
25457 LEDGER_DRIFT(neural_nofootprint_total);
25458} pmap_ledgers_drift;
25459
25460void
25461vm_map_pmap_check_ledgers(
25462 pmap_t pmap,
25463 ledger_t ledger,
25464 int pid,
25465 char *procname)
25466{
25467 ledger_amount_t bal;
25468 boolean_t do_panic;
25469
25470 do_panic = FALSE;
25471
25472 pmap_ledgers_drift.num_pmaps_checked++;
25473
25474#define LEDGER_CHECK_BALANCE(__LEDGER) \
25475MACRO_BEGIN \
25476 int panic_on_negative = TRUE; \
25477 ledger_get_balance(ledger, \
25478 task_ledgers.__LEDGER, \
25479 &bal); \
25480 ledger_get_panic_on_negative(ledger, \
25481 task_ledgers.__LEDGER, \
25482 &panic_on_negative); \
25483 if (bal != 0) { \
25484 if (panic_on_negative || \
25485 (pmap_ledgers_panic && \
25486 pmap_ledgers_panic_leeway > 0 && \
25487 (bal > (pmap_ledgers_panic_leeway * PAGE_SIZE) || \
25488 bal < (-pmap_ledgers_panic_leeway * PAGE_SIZE)))) { \
25489 do_panic = TRUE; \
25490 } \
25491 printf("LEDGER BALANCE proc %d (%s) " \
25492 "\"%s\" = %lld\n", \
25493 pid, procname, #__LEDGER, bal); \
25494 if (bal > 0) { \
25495 pmap_ledgers_drift.__LEDGER##_over++; \
25496 pmap_ledgers_drift.__LEDGER##_over_total += bal; \
25497 if (bal > pmap_ledgers_drift.__LEDGER##_over_max) { \
25498 pmap_ledgers_drift.__LEDGER##_over_max = bal; \
25499 } \
25500 } else if (bal < 0) { \
25501 pmap_ledgers_drift.__LEDGER##_under++; \
25502 pmap_ledgers_drift.__LEDGER##_under_total += bal; \
25503 if (bal < pmap_ledgers_drift.__LEDGER##_under_max) { \
25504 pmap_ledgers_drift.__LEDGER##_under_max = bal; \
25505 } \
25506 } \
25507 } \
25508MACRO_END
25509
25510 LEDGER_CHECK_BALANCE(phys_footprint);
25511 LEDGER_CHECK_BALANCE(internal);
25512 LEDGER_CHECK_BALANCE(internal_compressed);
25513 LEDGER_CHECK_BALANCE(external);
25514 LEDGER_CHECK_BALANCE(reusable);
25515 LEDGER_CHECK_BALANCE(iokit_mapped);
25516 LEDGER_CHECK_BALANCE(alternate_accounting);
25517 LEDGER_CHECK_BALANCE(alternate_accounting_compressed);
25518 LEDGER_CHECK_BALANCE(page_table);
25519 LEDGER_CHECK_BALANCE(purgeable_volatile);
25520 LEDGER_CHECK_BALANCE(purgeable_nonvolatile);
25521 LEDGER_CHECK_BALANCE(purgeable_volatile_compressed);
25522 LEDGER_CHECK_BALANCE(purgeable_nonvolatile_compressed);
25523 LEDGER_CHECK_BALANCE(tagged_nofootprint);
25524 LEDGER_CHECK_BALANCE(tagged_footprint);
25525 LEDGER_CHECK_BALANCE(tagged_nofootprint_compressed);
25526 LEDGER_CHECK_BALANCE(tagged_footprint_compressed);
25527 LEDGER_CHECK_BALANCE(network_volatile);
25528 LEDGER_CHECK_BALANCE(network_nonvolatile);
25529 LEDGER_CHECK_BALANCE(network_volatile_compressed);
25530 LEDGER_CHECK_BALANCE(network_nonvolatile_compressed);
25531 LEDGER_CHECK_BALANCE(media_nofootprint);
25532 LEDGER_CHECK_BALANCE(media_footprint);
25533 LEDGER_CHECK_BALANCE(media_nofootprint_compressed);
25534 LEDGER_CHECK_BALANCE(media_footprint_compressed);
25535 LEDGER_CHECK_BALANCE(graphics_nofootprint);
25536 LEDGER_CHECK_BALANCE(graphics_footprint);
25537 LEDGER_CHECK_BALANCE(graphics_nofootprint_compressed);
25538 LEDGER_CHECK_BALANCE(graphics_footprint_compressed);
25539 LEDGER_CHECK_BALANCE(neural_nofootprint);
25540 LEDGER_CHECK_BALANCE(neural_footprint);
25541 LEDGER_CHECK_BALANCE(neural_nofootprint_compressed);
25542 LEDGER_CHECK_BALANCE(neural_footprint_compressed);
25543 LEDGER_CHECK_BALANCE(neural_nofootprint_total);
25544
25545 if (do_panic) {
25546 if (pmap_ledgers_panic) {
25547 panic("pmap_destroy(%p) %d[%s] has imbalanced ledgers",
25548 pmap, pid, procname);
25549 } else {
25550 printf("pmap_destroy(%p) %d[%s] has imbalanced ledgers\n",
25551 pmap, pid, procname);
25552 }
25553 }
25554}
25555
25556void
25557vm_map_pmap_set_process(
25558 vm_map_t map,
25559 int pid,
25560 char *procname)
25561{
25562 pmap_set_process(vm_map_pmap(map), pid, procname);
25563}
25564
25565#endif /* MACH_ASSERT */
25566
25567__attribute__((always_inline))
25568vm_size_t
25569vm_map_kernel_max_simple_mappable_size(void)
25570{
25571#ifdef __arm64__
25572 return (2ULL << 30) - PAGE_SIZE;
25573#else
25574 /* No particular size limit */
25575 return -1;
25576#endif
25577}
25578
25579/**
25580 * Check if a given given map operation size is valid for the given map, taking
25581 * in to account whether or not the map operation has overridden the soft limit.
25582 *
25583 * This function is meant to be inlined wherever possible as it can, in some
25584 * modes, generates telemetry events which capture shallow backtraces. To
25585 * maximize the usefulness of this backtrace, we want to minize the depth at
25586 * which the backtrace is taken.
25587 */
25588__attribute__((always_inline))
25589bool
25590vm_map_is_map_size_valid(
25591 vm_map_t target_map,
25592 vm_size_t size,
25593 bool no_soft_limit)
25594{
25595#ifdef __x86_64__
25596 // Do not enforce any additional limits on x64
25597 (void)target_map;
25598 (void)size;
25599 (void)no_soft_limit;
25600 return true;
25601#else
25602 if (__probable(target_map->pmap != kernel_pmap ||
25603 size <= vm_map_kernel_max_simple_mappable_size() || no_soft_limit)) {
25604 // Allocation size matches policy
25605 return true;
25606 }
25607
25608 switch (vm_map_kernel_alloc_limit_mode) {
25609 default:
25610 case VM_MAP_KERNEL_ALLOC_LIMIT_MODE_BYPASS:
25611 return true;
25612 case VM_MAP_KERNEL_ALLOC_LIMIT_MODE_TRAP:
25613 trap_telemetry_report_kernel_soft_error(
25614 TRAP_TELEMETRY_KERNEL_SOFT_ERROR_VM_KERNEL_MAX_ALLOC_SIZE,
25615 /* report_once_per_site */ false);
25616 return true;
25617 case VM_MAP_KERNEL_ALLOC_LIMIT_MODE_REJECT:
25618 return false;
25619 case VM_MAP_KERNEL_ALLOC_LIMIT_MODE_PANIC:
25620 panic("2,000,000K ought to be enough for anybody "
25621 "(requested %lu bytes)", size);
25622 }
25623#endif /* __x86_64__ */
25624}
25625
25626vm_map_serial_t
25627vm_map_maybe_serial_id(vm_map_t maybe_vm_map)
25628{
25629 return maybe_vm_map != NULL ? maybe_vm_map->serial_id : VM_MAP_SERIAL_NONE;
25630}