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), &regions); 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 &copy_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 &copy); 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 &copy); 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, &current); 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(&copy->cpy_hdr); 10059 VMH_PREV_SET(&copy->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(&copy->cpy_hdr)->vme_next = 10108 next_copy; 10109 VMH_PREV_SET(&copy->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(&copy->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(&copy->cpy_hdr); 10193 VMH_PREV_SET(&copy->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(&copy->cpy_hdr)->vme_next = 10225 next_copy; 10226 VMH_PREV_SET(&copy->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(&copy->cpy_hdr)->vme_next = 10256 next_copy; 10257 VMH_PREV_SET(&copy->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(&copy->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 &copy_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 &copy_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 &copy_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, &copy) 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, &regions); 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 &copy_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 &copy_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, &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}